selftests/x86: fsgsbase test updates
Subsystems (3)
cover selftests/x86: fsgsbase test updates
This fixes a minor bug and adds a test for the recent NULL pointer dereference.
Andy Lutomirski (2):
selftests/x86/fsgsbase: Reap a forgotten child selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid
LDT GS
tools/testing/selftests/x86/fsgsbase.c | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+)
Signature · 1 line
2.25.4
PATCH 1/2 selftests/x86/fsgsbase: Reap a forgotten child
The ptrace() test forgot to reap its child. Reap it.
--- tools/testing/selftests/x86/fsgsbase.c | 3 +++ 1 file changed, 3 insertions(+)
tools/testing/selftests/x86/fsgsbase.c +3 -0
@@ -517,6 +517,9 @@ static void test_ptrace_write_gsbase(void) END:ptrace (PTRACE_CONT , child,NULL ,NULL ); +wait (&status); +if (!WIFEXITED (status)) +printf ("[WARN]\tChild didn't exit cleanly.\n" ); }int main ()
Signature · 1 line
2.25.4
[tip: x86/fsgsbase] selftests/x86/fsgsbase: Reap a forgotten child
The following commit has been merged into the x86/fsgsbase branch of tip:
The following commit has been merged into the x86/fsgsbase branch of tip:
Commit-ID: ab2dd173330a3f07142e68cd65682205036cd00f Gitweb: https://git.kernel.org/tip/ab2dd173330a3f07142e68cd65682205036cd00f Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 26 Aug 2020 10:00:45 -07:00 Committer: Ingo Molnar <[email protected]> CommitterDate: Wed, 26 Aug 2020 20:54:17 +02:00
selftests/x86/fsgsbase: Reap a forgotten child
The ptrace() test forgot to reap its child. Reap it.
--- tools/testing/selftests/x86/fsgsbase.c | 3 +++ 1 file changed, 3 insertions(+)
tools/testing/selftests/x86/fsgsbase.c +3 -0
@@ -517,6 +517,9 @@ static void test_ptrace_write_gsbase(void) END:ptrace (PTRACE_CONT , child,NULL ,NULL ); +wait (&status); +if (!WIFEXITED (status)) +printf ("[WARN]\tChild didn't exit cleanly.\n" ); }int main ()
PATCH 2/2 selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
In reply to Andy LutomirskiThis tesst commit 8ab49526b53d ("x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task"). Unpatched kernels will OOPS.
--- tools/testing/selftests/x86/fsgsbase.c | 65 ++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
tools/testing/selftests/x86/fsgsbase.c +65 -0
@@ -443,6 +443,68 @@ static void test_unexpected_base(void)#define USER_REGS_OFFSET (r) offsetof(struct user_regs_struct, r) +static void test_ptrace_write_gs_read_base (void ) +{ +int status; +pid_t child =fork (); + +if (child <0 ) +err (1 ,"fork" ); + +if (child ==0 ) { +printf ("[RUN]\tPTRACE_POKE GS, read GSBASE back\n" ); + +printf ("[RUN]\tARCH_SET_GS to 1\n" ); +if (syscall (SYS_arch_prctl,ARCH_SET_GS ,1 ) !=0 ) +err (1 ,"ARCH_SET_GS" ); + +if (ptrace (PTRACE_TRACEME ,0 ,NULL ,NULL ) !=0 ) +err (1 ,"PTRACE_TRACEME" ); + +raise (SIGTRAP ); +_exit (0 ); + } + +wait (&status); + +if (WSTOPSIG (status) ==SIGTRAP ) { +unsigned long base; +unsigned long gs_offset =USER_REGS_OFFSET (gs); +unsigned long base_offset =USER_REGS_OFFSET (gs_base); + +/* Read the initial base. It should be 1. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); +if (base ==1 ) { +printf ("[OK]\tGSBASE started at 1\n" ); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE started at 0x%lx\n" , base); + } + +printf ("[RUN]\tSet GS = 0x7, read GSBASE\n" ); + +/* Poke an LDT selector into GS. */ +if (ptrace (PTRACE_POKEUSER , child, gs_offset,0x7 ) !=0 ) +err (1 ,"PTRACE_POKEUSER" ); + +/* And read the base. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); + +if (base ==0 || base ==1 ) { +printf ("[OK]\tGSBASE reads as 0x%lx with invalid GS\n" , base); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE=0x%lx (should be 0 or 1)\n" , base); + } + } + +ptrace (PTRACE_CONT , child,NULL ,NULL ); + +wait (&status); +if (!WIFEXITED (status)) +printf ("[WARN]\tChild didn't exit cleanly.\n" ); +} +static void test_ptrace_write_gsbase (void ) {int status;
@@ -529,6 +591,9 @@ int main() shared_scratch =mmap (NULL ,4096 ,PROT_READ |PROT_WRITE ,MAP_ANONYMOUS |MAP_SHARED ,-1 ,0 ); +/* Do these tests before we have an LDT. */ +test_ptrace_write_gs_read_base (); +/* Probe FSGSBASE */ sethandler (SIGILL , sigill,0 );if (sigsetjmp (jmpbuf,1 ) ==0 ) {
Signature · 1 line
2.25.4
[tip: x86/fsgsbase] selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
The following commit has been merged into the x86/fsgsbase branch of tip:
The following commit has been merged into the x86/fsgsbase branch of tip:
Commit-ID: 1b9abd1755ad947d7c9913e92e7837b533124c90 Gitweb: https://git.kernel.org/tip/1b9abd1755ad947d7c9913e92e7837b533124c90 Author: Andy Lutomirski <[email protected]> AuthorDate: Wed, 26 Aug 2020 10:00:46 -07:00 Committer: Ingo Molnar <[email protected]> CommitterDate: Wed, 26 Aug 2020 20:54:18 +02:00
selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
This tests commit:
8ab49526b53d ("x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task")
Unpatched kernels will OOPS.
--- tools/testing/selftests/x86/fsgsbase.c | 65 +++++++++++++++++++++++++- 1 file changed, 65 insertions(+)
tools/testing/selftests/x86/fsgsbase.c +65 -0
@@ -443,6 +443,68 @@ static void test_unexpected_base(void)#define USER_REGS_OFFSET (r) offsetof(struct user_regs_struct, r) +static void test_ptrace_write_gs_read_base (void ) +{ +int status; +pid_t child =fork (); + +if (child <0 ) +err (1 ,"fork" ); + +if (child ==0 ) { +printf ("[RUN]\tPTRACE_POKE GS, read GSBASE back\n" ); + +printf ("[RUN]\tARCH_SET_GS to 1\n" ); +if (syscall (SYS_arch_prctl,ARCH_SET_GS ,1 ) !=0 ) +err (1 ,"ARCH_SET_GS" ); + +if (ptrace (PTRACE_TRACEME ,0 ,NULL ,NULL ) !=0 ) +err (1 ,"PTRACE_TRACEME" ); + +raise (SIGTRAP ); +_exit (0 ); + } + +wait (&status); + +if (WSTOPSIG (status) ==SIGTRAP ) { +unsigned long base; +unsigned long gs_offset =USER_REGS_OFFSET (gs); +unsigned long base_offset =USER_REGS_OFFSET (gs_base); + +/* Read the initial base. It should be 1. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); +if (base ==1 ) { +printf ("[OK]\tGSBASE started at 1\n" ); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE started at 0x%lx\n" , base); + } + +printf ("[RUN]\tSet GS = 0x7, read GSBASE\n" ); + +/* Poke an LDT selector into GS. */ +if (ptrace (PTRACE_POKEUSER , child, gs_offset,0x7 ) !=0 ) +err (1 ,"PTRACE_POKEUSER" ); + +/* And read the base. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); + +if (base ==0 || base ==1 ) { +printf ("[OK]\tGSBASE reads as 0x%lx with invalid GS\n" , base); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE=0x%lx (should be 0 or 1)\n" , base); + } + } + +ptrace (PTRACE_CONT , child,NULL ,NULL ); + +wait (&status); +if (!WIFEXITED (status)) +printf ("[WARN]\tChild didn't exit cleanly.\n" ); +} +static void test_ptrace_write_gsbase (void ) {int status;
@@ -529,6 +591,9 @@ int main() shared_scratch =mmap (NULL ,4096 ,PROT_READ |PROT_WRITE ,MAP_ANONYMOUS |MAP_SHARED ,-1 ,0 ); +/* Do these tests before we have an LDT. */ +test_ptrace_write_gs_read_base (); +/* Probe FSGSBASE */ sethandler (SIGILL , sigill,0 );if (sigsetjmp (jmpbuf,1 ) ==0 ) {