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;
147165int nr_syscalls_emulated ;
148166int si_code ;
149167int si_errno ;
168+ unsigned long syscall_addr ;
150169
151170static 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+
326380TEST_HARNESS_MAIN
0 commit comments