Skip to content

Commit b6a5a16

Browse files
dvyukovKAGA-KOKO
authored andcommitted
selftests: Add tests for PR_SYS_DISPATCH_INCLUSIVE_ON
Add tests for PR_SYS_DISPATCH_INCLUSIVE_ON correct/incorrect args, and a test that ensures that the specified range is respected by both PR_SYS_DISPATCH_EXCLUSIVE_ON and PR_SYS_DISPATCH_INCLUSIVE_ON. Signed-off-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/8df4b50b176b073550bab5b3f3faff752c5f8e17.1747839857.git.dvyukov@google.com
1 parent a2fc422 commit b6a5a16

1 file changed

Lines changed: 74 additions & 20 deletions

File tree

  • tools/testing/selftests/syscall_user_dispatch

tools/testing/selftests/syscall_user_dispatch/sud_test.c

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,24 @@
1010
#include <sys/sysinfo.h>
1111
#include <sys/syscall.h>
1212
#include <signal.h>
13+
#include <stdbool.h>
14+
#include <stdlib.h>
1315

1416
#include <asm/unistd.h>
1517
#include "../kselftest_harness.h"
1618

1719
#ifndef PR_SET_SYSCALL_USER_DISPATCH
1820
# define PR_SET_SYSCALL_USER_DISPATCH 59
1921
# define PR_SYS_DISPATCH_OFF 0
20-
# define PR_SYS_DISPATCH_ON 1
2122
# define SYSCALL_DISPATCH_FILTER_ALLOW 0
2223
# define SYSCALL_DISPATCH_FILTER_BLOCK 1
2324
#endif
2425

26+
#ifndef PR_SYS_DISPATCH_EXCLUSIVE_ON
27+
# define PR_SYS_DISPATCH_EXCLUSIVE_ON 1
28+
# define PR_SYS_DISPATCH_INCLUSIVE_ON 2
29+
#endif
30+
2531
#ifndef SYS_USER_DISPATCH
2632
# define SYS_USER_DISPATCH 2
2733
#endif
@@ -65,7 +71,7 @@ TEST_SIGNAL(dispatch_trigger_sigsys, SIGSYS)
6571
ret = sysinfo(&info);
6672
ASSERT_EQ(0, ret);
6773

68-
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &sel);
74+
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, &sel);
6975
ASSERT_EQ(0, ret) {
7076
TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
7177
}
@@ -118,8 +124,8 @@ TEST(bad_prctl_param)
118124
/* Valid parameter */
119125
prctl_valid(_metadata, op, 0x0, 0x0, 0x0);
120126

121-
/* PR_SYS_DISPATCH_ON */
122-
op = PR_SYS_DISPATCH_ON;
127+
/* PR_SYS_DISPATCH_EXCLUSIVE_ON */
128+
op = PR_SYS_DISPATCH_EXCLUSIVE_ON;
123129

124130
/* Dispatcher region is bad (offset > 0 && len == 0) */
125131
prctl_invalid(_metadata, op, 0x1, 0x0, &sel, EINVAL);
@@ -131,12 +137,24 @@ TEST(bad_prctl_param)
131137
/*
132138
* Dispatcher range overflows unsigned long
133139
*/
134-
prctl_invalid(_metadata, PR_SYS_DISPATCH_ON, 1, -1L, &sel, EINVAL);
140+
prctl_invalid(_metadata, PR_SYS_DISPATCH_EXCLUSIVE_ON, 1, -1L, &sel, EINVAL);
135141

136142
/*
137143
* Allowed range overflows usigned long
138144
*/
139-
prctl_invalid(_metadata, PR_SYS_DISPATCH_ON, -1L, 0x1, &sel, EINVAL);
145+
prctl_invalid(_metadata, PR_SYS_DISPATCH_EXCLUSIVE_ON, -1L, 0x1, &sel, EINVAL);
146+
147+
/* 0 len should fail for PR_SYS_DISPATCH_INCLUSIVE_ON */
148+
prctl_invalid(_metadata, PR_SYS_DISPATCH_INCLUSIVE_ON, 1, 0, 0, EINVAL);
149+
150+
/* Range wrap-around should fail */
151+
prctl_invalid(_metadata, PR_SYS_DISPATCH_INCLUSIVE_ON, -1L, 2, 0, EINVAL);
152+
153+
/* Normal range shouldn't fail */
154+
prctl_valid(_metadata, PR_SYS_DISPATCH_INCLUSIVE_ON, 2, 3, 0);
155+
156+
/* Invalid selector */
157+
prctl_invalid(_metadata, PR_SYS_DISPATCH_INCLUSIVE_ON, 2, 3, (void *) -1, EFAULT);
140158
}
141159

142160
/*
@@ -147,11 +165,13 @@ char glob_sel;
147165
int nr_syscalls_emulated;
148166
int si_code;
149167
int si_errno;
168+
unsigned long syscall_addr;
150169

151170
static void handle_sigsys(int sig, siginfo_t *info, void *ucontext)
152171
{
153172
si_code = info->si_code;
154173
si_errno = info->si_errno;
174+
syscall_addr = (unsigned long)info->si_call_addr;
155175

156176
if (info->si_syscall == MAGIC_SYSCALL_1)
157177
nr_syscalls_emulated++;
@@ -174,31 +194,34 @@ static void handle_sigsys(int sig, siginfo_t *info, void *ucontext)
174194
#endif
175195
}
176196

177-
TEST(dispatch_and_return)
197+
int setup_sigsys_handler(void)
178198
{
179-
long ret;
180199
struct sigaction act;
181200
sigset_t mask;
182201

183-
glob_sel = 0;
184-
nr_syscalls_emulated = 0;
185-
si_code = 0;
186-
si_errno = 0;
187-
188202
memset(&act, 0, sizeof(act));
189203
sigemptyset(&mask);
190-
191204
act.sa_sigaction = handle_sigsys;
192205
act.sa_flags = SA_SIGINFO;
193206
act.sa_mask = mask;
207+
return sigaction(SIGSYS, &act, NULL);
208+
}
194209

195-
ret = sigaction(SIGSYS, &act, NULL);
196-
ASSERT_EQ(0, ret);
210+
TEST(dispatch_and_return)
211+
{
212+
long ret;
213+
214+
glob_sel = 0;
215+
nr_syscalls_emulated = 0;
216+
si_code = 0;
217+
si_errno = 0;
218+
219+
ASSERT_EQ(0, setup_sigsys_handler());
197220

198221
/* Make sure selector is good prior to prctl. */
199222
SYSCALL_DISPATCH_OFF(glob_sel);
200223

201-
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &glob_sel);
224+
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, &glob_sel);
202225
ASSERT_EQ(0, ret) {
203226
TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
204227
}
@@ -254,7 +277,7 @@ TEST_SIGNAL(bad_selector, SIGSYS)
254277
/* Make sure selector is good prior to prctl. */
255278
SYSCALL_DISPATCH_OFF(glob_sel);
256279

257-
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &glob_sel);
280+
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, &glob_sel);
258281
ASSERT_EQ(0, ret) {
259282
TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
260283
}
@@ -278,7 +301,7 @@ TEST(disable_dispatch)
278301
struct sysinfo info;
279302
char sel = 0;
280303

281-
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &sel);
304+
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, &sel);
282305
ASSERT_EQ(0, ret) {
283306
TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
284307
}
@@ -310,7 +333,7 @@ TEST(direct_dispatch_range)
310333
* Instead of calculating libc addresses; allow the entire
311334
* memory map and lock the selector.
312335
*/
313-
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, -1L, &sel);
336+
ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, -1L, &sel);
314337
ASSERT_EQ(0, ret) {
315338
TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
316339
}
@@ -323,4 +346,35 @@ TEST(direct_dispatch_range)
323346
}
324347
}
325348

349+
static void test_range(struct __test_metadata *_metadata,
350+
unsigned long op, unsigned long off,
351+
unsigned long size, bool dispatch)
352+
{
353+
nr_syscalls_emulated = 0;
354+
SYSCALL_DISPATCH_OFF(glob_sel);
355+
EXPECT_EQ(0, prctl(PR_SET_SYSCALL_USER_DISPATCH, op, off, size, &glob_sel));
356+
SYSCALL_DISPATCH_ON(glob_sel);
357+
if (dispatch) {
358+
EXPECT_EQ(syscall(MAGIC_SYSCALL_1), MAGIC_SYSCALL_1);
359+
EXPECT_EQ(nr_syscalls_emulated, 1);
360+
} else {
361+
EXPECT_EQ(syscall(MAGIC_SYSCALL_1), -1);
362+
EXPECT_EQ(nr_syscalls_emulated, 0);
363+
}
364+
}
365+
366+
TEST(dispatch_range)
367+
{
368+
ASSERT_EQ(0, setup_sigsys_handler());
369+
test_range(_metadata, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, true);
370+
test_range(_metadata, PR_SYS_DISPATCH_EXCLUSIVE_ON, syscall_addr, 1, false);
371+
test_range(_metadata, PR_SYS_DISPATCH_EXCLUSIVE_ON, syscall_addr-100, 200, false);
372+
test_range(_metadata, PR_SYS_DISPATCH_EXCLUSIVE_ON, syscall_addr+1, 100, true);
373+
test_range(_metadata, PR_SYS_DISPATCH_EXCLUSIVE_ON, syscall_addr-100, 100, true);
374+
test_range(_metadata, PR_SYS_DISPATCH_INCLUSIVE_ON, syscall_addr, 1, true);
375+
test_range(_metadata, PR_SYS_DISPATCH_INCLUSIVE_ON, syscall_addr-1, 1, false);
376+
test_range(_metadata, PR_SYS_DISPATCH_INCLUSIVE_ON, syscall_addr+1, 1, false);
377+
SYSCALL_DISPATCH_OFF(glob_sel);
378+
}
379+
326380
TEST_HARNESS_MAIN

0 commit comments

Comments
 (0)