@@ -443,6 +443,68 @@ static void test_unexpected_base(void)
443443
444444#define USER_REGS_OFFSET (r ) offsetof(struct user_regs_struct, r)
445445
446+ static void test_ptrace_write_gs_read_base (void )
447+ {
448+ int status ;
449+ pid_t child = fork ();
450+
451+ if (child < 0 )
452+ err (1 , "fork" );
453+
454+ if (child == 0 ) {
455+ printf ("[RUN]\tPTRACE_POKE GS, read GSBASE back\n" );
456+
457+ printf ("[RUN]\tARCH_SET_GS to 1\n" );
458+ if (syscall (SYS_arch_prctl , ARCH_SET_GS , 1 ) != 0 )
459+ err (1 , "ARCH_SET_GS" );
460+
461+ if (ptrace (PTRACE_TRACEME , 0 , NULL , NULL ) != 0 )
462+ err (1 , "PTRACE_TRACEME" );
463+
464+ raise (SIGTRAP );
465+ _exit (0 );
466+ }
467+
468+ wait (& status );
469+
470+ if (WSTOPSIG (status ) == SIGTRAP ) {
471+ unsigned long base ;
472+ unsigned long gs_offset = USER_REGS_OFFSET (gs );
473+ unsigned long base_offset = USER_REGS_OFFSET (gs_base );
474+
475+ /* Read the initial base. It should be 1. */
476+ base = ptrace (PTRACE_PEEKUSER , child , base_offset , NULL );
477+ if (base == 1 ) {
478+ printf ("[OK]\tGSBASE started at 1\n" );
479+ } else {
480+ nerrs ++ ;
481+ printf ("[FAIL]\tGSBASE started at 0x%lx\n" , base );
482+ }
483+
484+ printf ("[RUN]\tSet GS = 0x7, read GSBASE\n" );
485+
486+ /* Poke an LDT selector into GS. */
487+ if (ptrace (PTRACE_POKEUSER , child , gs_offset , 0x7 ) != 0 )
488+ err (1 , "PTRACE_POKEUSER" );
489+
490+ /* And read the base. */
491+ base = ptrace (PTRACE_PEEKUSER , child , base_offset , NULL );
492+
493+ if (base == 0 || base == 1 ) {
494+ printf ("[OK]\tGSBASE reads as 0x%lx with invalid GS\n" , base );
495+ } else {
496+ nerrs ++ ;
497+ printf ("[FAIL]\tGSBASE=0x%lx (should be 0 or 1)\n" , base );
498+ }
499+ }
500+
501+ ptrace (PTRACE_CONT , child , NULL , NULL );
502+
503+ wait (& status );
504+ if (!WIFEXITED (status ))
505+ printf ("[WARN]\tChild didn't exit cleanly.\n" );
506+ }
507+
446508static void test_ptrace_write_gsbase (void )
447509{
448510 int status ;
@@ -529,6 +591,9 @@ int main()
529591 shared_scratch = mmap (NULL , 4096 , PROT_READ | PROT_WRITE ,
530592 MAP_ANONYMOUS | MAP_SHARED , -1 , 0 );
531593
594+ /* Do these tests before we have an LDT. */
595+ test_ptrace_write_gs_read_base ();
596+
532597 /* Probe FSGSBASE */
533598 sethandler (SIGILL , sigill , 0 );
534599 if (sigsetjmp (jmpbuf , 1 ) == 0 ) {
0 commit comments