2121#include <sys/uio.h>
2222
2323#include "helpers.h"
24+ #include "../kselftest.h"
2425
2526#ifdef __x86_64__
2627# define VSYS (x ) (x)
3940/* max length of lines in /proc/self/maps - anything longer is skipped here */
4041#define MAPS_LINE_LEN 128
4142
42- static void sethandler (int sig , void (* handler )(int , siginfo_t * , void * ),
43- int flags )
44- {
45- struct sigaction sa ;
46- memset (& sa , 0 , sizeof (sa ));
47- sa .sa_sigaction = handler ;
48- sa .sa_flags = SA_SIGINFO | flags ;
49- sigemptyset (& sa .sa_mask );
50- if (sigaction (sig , & sa , 0 ))
51- err (1 , "sigaction" );
52- }
53-
5443/* vsyscalls and vDSO */
5544bool vsyscall_map_r = false, vsyscall_map_x = false;
5645
@@ -96,64 +85,6 @@ static void init_vdso(void)
9685 printf ("[WARN]\tfailed to find getcpu in vDSO\n" );
9786}
9887
99- static int init_vsys (void )
100- {
101- #ifdef __x86_64__
102- int nerrs = 0 ;
103- FILE * maps ;
104- char line [MAPS_LINE_LEN ];
105- bool found = false;
106-
107- maps = fopen ("/proc/self/maps" , "r" );
108- if (!maps ) {
109- printf ("[WARN]\tCould not open /proc/self/maps -- assuming vsyscall is r-x\n" );
110- vsyscall_map_r = true;
111- return 0 ;
112- }
113-
114- while (fgets (line , MAPS_LINE_LEN , maps )) {
115- char r , x ;
116- void * start , * end ;
117- char name [MAPS_LINE_LEN ];
118-
119- /* sscanf() is safe here as strlen(name) >= strlen(line) */
120- if (sscanf (line , "%p-%p %c-%cp %*x %*x:%*x %*u %s" ,
121- & start , & end , & r , & x , name ) != 5 )
122- continue ;
123-
124- if (strcmp (name , "[vsyscall]" ))
125- continue ;
126-
127- printf ("\tvsyscall map: %s" , line );
128-
129- if (start != (void * )0xffffffffff600000 ||
130- end != (void * )0xffffffffff601000 ) {
131- printf ("[FAIL]\taddress range is nonsense\n" );
132- nerrs ++ ;
133- }
134-
135- printf ("\tvsyscall permissions are %c-%c\n" , r , x );
136- vsyscall_map_r = (r == 'r' );
137- vsyscall_map_x = (x == 'x' );
138-
139- found = true;
140- break ;
141- }
142-
143- fclose (maps );
144-
145- if (!found ) {
146- printf ("\tno vsyscall map in /proc/self/maps\n" );
147- vsyscall_map_r = false;
148- vsyscall_map_x = false;
149- }
150-
151- return nerrs ;
152- #else
153- return 0 ;
154- #endif
155- }
156-
15788/* syscalls */
15889static inline long sys_gtod (struct timeval * tv , struct timezone * tz )
15990{
@@ -176,17 +107,6 @@ static inline long sys_getcpu(unsigned * cpu, unsigned * node,
176107 return syscall (SYS_getcpu , cpu , node , cache );
177108}
178109
179- static jmp_buf jmpbuf ;
180- static volatile unsigned long segv_err ;
181-
182- static void sigsegv (int sig , siginfo_t * info , void * ctx_void )
183- {
184- ucontext_t * ctx = (ucontext_t * )ctx_void ;
185-
186- segv_err = ctx -> uc_mcontext .gregs [REG_ERR ];
187- siglongjmp (jmpbuf , 1 );
188- }
189-
190110static double tv_diff (const struct timeval * a , const struct timeval * b )
191111{
192112 return (double )(a -> tv_sec - b -> tv_sec ) +
@@ -396,9 +316,33 @@ static int test_getcpu(int cpu)
396316 return nerrs ;
397317}
398318
319+ #ifdef __x86_64__
320+
321+ static jmp_buf jmpbuf ;
322+ static volatile unsigned long segv_err ;
323+
324+ static void sethandler (int sig , void (* handler )(int , siginfo_t * , void * ),
325+ int flags )
326+ {
327+ struct sigaction sa ;
328+ memset (& sa , 0 , sizeof (sa ));
329+ sa .sa_sigaction = handler ;
330+ sa .sa_flags = SA_SIGINFO | flags ;
331+ sigemptyset (& sa .sa_mask );
332+ if (sigaction (sig , & sa , 0 ))
333+ err (1 , "sigaction" );
334+ }
335+
336+ static void sigsegv (int sig , siginfo_t * info , void * ctx_void )
337+ {
338+ ucontext_t * ctx = (ucontext_t * )ctx_void ;
339+
340+ segv_err = ctx -> uc_mcontext .gregs [REG_ERR ];
341+ siglongjmp (jmpbuf , 1 );
342+ }
343+
399344static int test_vsys_r (void )
400345{
401- #ifdef __x86_64__
402346 printf ("[RUN]\tChecking read access to the vsyscall page\n" );
403347 bool can_read ;
404348 if (sigsetjmp (jmpbuf , 1 ) == 0 ) {
@@ -420,14 +364,12 @@ static int test_vsys_r(void)
420364 printf ("[OK]\tWe do not have read access: #PF(0x%lx)\n" ,
421365 segv_err );
422366 }
423- #endif
424367
425368 return 0 ;
426369}
427370
428371static int test_vsys_x (void )
429372{
430- #ifdef __x86_64__
431373 if (vsyscall_map_x ) {
432374 /* We already tested this adequately. */
433375 return 0 ;
@@ -454,8 +396,6 @@ static int test_vsys_x(void)
454396 segv_err );
455397 return 1 ;
456398 }
457- #endif
458-
459399 return 0 ;
460400}
461401
@@ -472,7 +412,6 @@ static int test_vsys_x(void)
472412 */
473413static int test_process_vm_readv (void )
474414{
475- #ifdef __x86_64__
476415 char buf [4096 ];
477416 struct iovec local , remote ;
478417 int ret ;
@@ -504,12 +443,63 @@ static int test_process_vm_readv(void)
504443 printf ("[FAIL]\tprocess_rm_readv() succeeded, but it should have failed in this configuration\n" );
505444 return 1 ;
506445 }
507- #endif
508-
509446 return 0 ;
510447}
511448
512- #ifdef __x86_64__
449+ static int init_vsys (void )
450+ {
451+ int nerrs = 0 ;
452+ FILE * maps ;
453+ char line [MAPS_LINE_LEN ];
454+ bool found = false;
455+
456+ maps = fopen ("/proc/self/maps" , "r" );
457+ if (!maps ) {
458+ printf ("[WARN]\tCould not open /proc/self/maps -- assuming vsyscall is r-x\n" );
459+ vsyscall_map_r = true;
460+ return 0 ;
461+ }
462+
463+ while (fgets (line , MAPS_LINE_LEN , maps )) {
464+ char r , x ;
465+ void * start , * end ;
466+ char name [MAPS_LINE_LEN ];
467+
468+ /* sscanf() is safe here as strlen(name) >= strlen(line) */
469+ if (sscanf (line , "%p-%p %c-%cp %*x %*x:%*x %*u %s" ,
470+ & start , & end , & r , & x , name ) != 5 )
471+ continue ;
472+
473+ if (strcmp (name , "[vsyscall]" ))
474+ continue ;
475+
476+ printf ("\tvsyscall map: %s" , line );
477+
478+ if (start != (void * )0xffffffffff600000 ||
479+ end != (void * )0xffffffffff601000 ) {
480+ printf ("[FAIL]\taddress range is nonsense\n" );
481+ nerrs ++ ;
482+ }
483+
484+ printf ("\tvsyscall permissions are %c-%c\n" , r , x );
485+ vsyscall_map_r = (r == 'r' );
486+ vsyscall_map_x = (x == 'x' );
487+
488+ found = true;
489+ break ;
490+ }
491+
492+ fclose (maps );
493+
494+ if (!found ) {
495+ printf ("\tno vsyscall map in /proc/self/maps\n" );
496+ vsyscall_map_r = false;
497+ vsyscall_map_x = false;
498+ }
499+
500+ return nerrs ;
501+ }
502+
513503static volatile sig_atomic_t num_vsyscall_traps ;
514504
515505static void sigtrap (int sig , siginfo_t * info , void * ctx_void )
@@ -559,20 +549,20 @@ int main(int argc, char **argv)
559549 int nerrs = 0 ;
560550
561551 init_vdso ();
552+ #ifdef __x86_64__
562553 nerrs += init_vsys ();
554+ #endif
563555
564556 nerrs += test_gtod ();
565557 nerrs += test_time ();
566558 nerrs += test_getcpu (0 );
567559 nerrs += test_getcpu (1 );
568560
561+ #ifdef __x86_64__
569562 sethandler (SIGSEGV , sigsegv , 0 );
570563 nerrs += test_vsys_r ();
571564 nerrs += test_vsys_x ();
572-
573565 nerrs += test_process_vm_readv ();
574-
575- #ifdef __x86_64__
576566 nerrs += test_emulation ();
577567#endif
578568
0 commit comments