Minor selftests improvements
Subsystems (3)
cover Minor selftests improvements
This improves and robustifies the ldt_gdt test and fixes compiler warnings in the protection_keys test.
Andy Lutomirski (5):
selftests/x86/protection_keys: Fix syscall NR redefinition warnings selftests/x86/ldt_gdt: Robustify against set_thread_area() and LAR
oddities
selftests/x86/ldt_gdt: Add infrastructure to test set_thread_area() selftests/x86/ldt_gdt: Run most existing LDT test cases against the
GDT as well
selftests/x86/ldt_get: Add a few additional tests for limits
tools/testing/selftests/x86/ldt_gdt.c | 88 +++++++++++++++++++++------ tools/testing/selftests/x86/protection_keys.c | 24 ++++++-- 2 files changed, 88 insertions(+), 24 deletions(-)
Signature · 1 line
2.13.6
PATCH 1/5 selftests/x86/protection_keys: Fix syscall NR redefinition warnings
On new enough glibc, the pkey syscalls numbers are available. Check first before defining them to avoid warnings like:
protection_keys.c:198:0: warning: "SYS_pkey_alloc" redefined
--- tools/testing/selftests/x86/protection_keys.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
tools/testing/selftests/x86/protection_keys.c +18 -6
@@ -188,17 +188,29 @@ void lots_o_noops_around_write(int *write_to_me)#define u64 uint64_t#ifdef __i386__ -#define SYS_mprotect_key 380 -#define SYS_pkey_alloc 381 -#define SYS_pkey_free 382 + +#ifndef SYS_mprotect_key +# define SYS_mprotect_key 380 +#endif +#ifndef SYS_pkey_alloc +# define SYS_pkey_alloc 381 +# define SYS_pkey_free 382 +#endif #define REG_IP_IDX REG_EIP#define si_pkey_offset 0x14 +#else -#define SYS_mprotect_key 329 -#define SYS_pkey_alloc 330 -#define SYS_pkey_free 331 + +#ifndef SYS_mprotect_key +# define SYS_mprotect_key 329 +#endif +#ifndef SYS_pkey_alloc +# define SYS_pkey_alloc 330 +# define SYS_pkey_free 331 +#endif #define REG_IP_IDX REG_RIP#define si_pkey_offset 0x20 +#endif void dump_mem (void *dumpme,int len_bytes)
Signature · 1 line
2.13.6
tip-bot for Andy Lutomirski
merge bot[tip:x86/asm] selftests/x86/protection_keys: Fix syscall NR redefinition warnings
selftests/x86/protection_keys: Fix syscall NR redefinition warnings
Commit-ID: 693cb5580fdb026922363aa103add64b3ecd572e Gitweb: https://git.kernel.org/tip/693cb5580fdb026922363aa103add64b3ecd572e Author: Andy Lutomirski <[email protected]> AuthorDate: Sat, 4 Nov 2017 04:19:48 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 7 Nov 2017 11:13:42 +0100
selftests/x86/protection_keys: Fix syscall NR redefinition warnings
On new enough glibc, the pkey syscalls numbers are available. Check first before defining them to avoid warnings like:
protection_keys.c:198:0: warning: "SYS_pkey_alloc" redefined
--- tools/testing/selftests/x86/protection_keys.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
tools/testing/selftests/x86/protection_keys.c +18 -6
@@ -189,17 +189,29 @@ void lots_o_noops_around_write(int *write_to_me)#define u64 uint64_t#ifdef __i386__ -#define SYS_mprotect_key 380 -#define SYS_pkey_alloc 381 -#define SYS_pkey_free 382 + +#ifndef SYS_mprotect_key +# define SYS_mprotect_key 380 +#endif +#ifndef SYS_pkey_alloc +# define SYS_pkey_alloc 381 +# define SYS_pkey_free 382 +#endif #define REG_IP_IDX REG_EIP#define si_pkey_offset 0x14 +#else -#define SYS_mprotect_key 329 -#define SYS_pkey_alloc 330 -#define SYS_pkey_free 331 + +#ifndef SYS_mprotect_key +# define SYS_mprotect_key 329 +#endif +#ifndef SYS_pkey_alloc +# define SYS_pkey_alloc 330 +# define SYS_pkey_free 331 +#endif #define REG_IP_IDX REG_RIP#define si_pkey_offset 0x20 +#endif void dump_mem (void *dumpme,int len_bytes)
PATCH 2/5 selftests/x86/ldt_gdt: Robustify against set_thread_area() and LAR oddities
In reply to Andy LutomirskiBits 19:16 of LAR's result are undefined, and some upcoming improvements to the test case seem to trigger this. Mask off those bits to avoid spurious failures.
commit 5b781c7e317f ("x86/tls: Forcibly set the accessed bit in TLS segments") adds a valid case in which LAR's output doesn't quite agree with set_thread_area()'s input. This isn't triggered in the test as is, but it will be if we start calling set_thread_area() with the accessed bit clear. Work around this discrepency.
I've added a Fixes tag so that -stable can pick this up if neccesary.
--- tools/testing/selftests/x86/ldt_gdt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
tools/testing/selftests/x86/ldt_gdt.c +9 -1
@@ -114,7 +114,15 @@ static void check_valid_segment(uint16_t index, int ldt,return ; } -if (ar != expected_ar) { +/* The SDM says "bits 19:16 are undefined". Thanks. */ + ar &= ~0xF0000 ; + +/* +* NB: Different Linux versions do different things with the +* accessed bit in set_thread_area(). +*/ +if (ar != expected_ar && + (ldt || ar != (expected_ar |AR_ACCESSED ))) {printf ("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n" , (ldt ?"LDT" :"GDT" ), index, ar, expected_ar); nerrs++;
Signature · 1 line
2.13.6
tip-bot for Andy Lutomirski
merge bot[tip:x86/asm] selftests/x86/ldt_gdt: Robustify against set_thread_area() and LAR oddities
selftests/x86/ldt_gdt: Robustify against set_thread_area() and LAR oddities
Commit-ID: d60ad744c9741586010d4bea286f09a063a90fbd Gitweb: https://git.kernel.org/tip/d60ad744c9741586010d4bea286f09a063a90fbd Author: Andy Lutomirski <[email protected]> AuthorDate: Sat, 4 Nov 2017 04:19:49 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 7 Nov 2017 11:13:42 +0100
selftests/x86/ldt_gdt: Robustify against set_thread_area() and LAR oddities
Bits 19:16 of LAR's result are undefined, and some upcoming improvements to the test case seem to trigger this. Mask off those bits to avoid spurious failures.
commit 5b781c7e317f ("x86/tls: Forcibly set the accessed bit in TLS segments") adds a valid case in which LAR's output doesn't quite agree with set_thread_area()'s input. This isn't triggered in the test as is, but it will be if we start calling set_thread_area() with the accessed bit clear. Work around this discrepency.
I've added a Fixes tag so that -stable can pick this up if neccesary.
--- tools/testing/selftests/x86/ldt_gdt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
tools/testing/selftests/x86/ldt_gdt.c +9 -1
@@ -115,7 +115,15 @@ static void check_valid_segment(uint16_t index, int ldt,return ; } -if (ar != expected_ar) { +/* The SDM says "bits 19:16 are undefined". Thanks. */ + ar &= ~0xF0000 ; + +/* +* NB: Different Linux versions do different things with the +* accessed bit in set_thread_area(). +*/ +if (ar != expected_ar && + (ldt || ar != (expected_ar |AR_ACCESSED ))) {printf ("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n" , (ldt ?"LDT" :"GDT" ), index, ar, expected_ar); nerrs++;
PATCH 3/5 selftests/x86/ldt_gdt: Add infrastructure to test set_thread_area()
In reply to Andy LutomirskiMuch of the test design could apply to set_thread_area() (i.e. GDT), not just modify_ldt(). Add set_thread_area() to the install_valid_mode() helper.
--- tools/testing/selftests/x86/ldt_gdt.c | 53 ++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 16 deletions(-)
tools/testing/selftests/x86/ldt_gdt.c +37 -16
@@ -136,30 +136,51 @@ static void check_valid_segment(uint16_t index, int ldt, } } -static bool install_valid_mode (const struct user_desc *desc,uint32_t ar, -bool oldmode) +static bool install_valid_mode (const struct user_desc *d,uint32_t ar, +bool oldmode,bool ldt) { -int ret =syscall (SYS_modify_ldt, oldmode ?1 :0x11 , - desc,sizeof (*desc)); -if (ret <-1 ) - errno = -ret; +struct user_desc desc = *d; +int ret; + +if (!ldt) { +#ifndef __i386__ +/* No point testing set_thread_area in a 64-bit build */ +return false; +#endif +if (!gdt_entry_num) +return false; + desc.entry_number = gdt_entry_num; + + ret =syscall (SYS_set_thread_area, &desc); + }else { + ret =syscall (SYS_modify_ldt, oldmode ?1 :0x11 , + &desc,sizeof (desc)); + +if (ret <-1 ) + errno = -ret; + +if (ret !=0 && errno ==ENOSYS ) { +printf ("[OK]\tmodify_ldt returned -ENOSYS\n" ); +return false; + } + } +if (ret ==0 ) { -uint32_t limit = desc->limit; -if (desc->limit_in_pages) +uint32_t limit = desc.limit; +if (desc.limit_in_pages) limit = (limit <<12 ) +4095 ; -check_valid_segment (desc->entry_number,1 , ar, limit, true); +check_valid_segment (desc.entry_number, ldt, ar, limit, true);return true; - }else if (errno ==ENOSYS ) { -printf ("[OK]\tmodify_ldt returned -ENOSYS\n" ); -return false; }else { -if (desc->seg_32bit) { -printf ("[FAIL]\tUnexpected modify_ldt failure %d\n" , +if (desc.seg_32bit) { +printf ("[FAIL]\tUnexpected %s failure %d\n" , + ldt ?"modify_ldt" :"set_thread_area" , errno); nerrs++;return false; }else { -printf ("[OK]\tmodify_ldt rejected 16 bit segment\n" ); +printf ("[OK]\t%s rejected 16 bit segment\n" , + ldt ?"modify_ldt" :"set_thread_area" );return false; } }
@@ -167,7 +188,7 @@ static bool install_valid_mode(const struct user_desc *desc, uint32_t ar,static bool install_valid (const struct user_desc *desc,uint32_t ar) { -return install_valid_mode (desc, ar, false); +return install_valid_mode (desc, ar, false, true); }static void install_invalid (const struct user_desc *desc,bool oldmode)
Signature · 1 line
2.13.6
tip-bot for Andy Lutomirski
merge bot[tip:x86/asm] selftests/x86/ldt_gdt: Add infrastructure to test set_thread_area()
selftests/x86/ldt_gdt: Add infrastructure to test set_thread_area()
Commit-ID: d744dcad39094c9187075e274d1cdef79c57c8b5 Gitweb: https://git.kernel.org/tip/d744dcad39094c9187075e274d1cdef79c57c8b5 Author: Andy Lutomirski <[email protected]> AuthorDate: Sat, 4 Nov 2017 04:19:50 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 7 Nov 2017 11:13:42 +0100
selftests/x86/ldt_gdt: Add infrastructure to test set_thread_area()
Much of the test design could apply to set_thread_area() (i.e. GDT), not just modify_ldt(). Add set_thread_area() to the install_valid_mode() helper.
--- tools/testing/selftests/x86/ldt_gdt.c | 53 ++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 16 deletions(-)
tools/testing/selftests/x86/ldt_gdt.c +37 -16
@@ -137,30 +137,51 @@ static void check_valid_segment(uint16_t index, int ldt, } } -static bool install_valid_mode (const struct user_desc *desc,uint32_t ar, -bool oldmode) +static bool install_valid_mode (const struct user_desc *d,uint32_t ar, +bool oldmode,bool ldt) { -int ret =syscall (SYS_modify_ldt, oldmode ?1 :0x11 , - desc,sizeof (*desc)); -if (ret <-1 ) - errno = -ret; +struct user_desc desc = *d; +int ret; + +if (!ldt) { +#ifndef __i386__ +/* No point testing set_thread_area in a 64-bit build */ +return false; +#endif +if (!gdt_entry_num) +return false; + desc.entry_number = gdt_entry_num; + + ret =syscall (SYS_set_thread_area, &desc); + }else { + ret =syscall (SYS_modify_ldt, oldmode ?1 :0x11 , + &desc,sizeof (desc)); + +if (ret <-1 ) + errno = -ret; + +if (ret !=0 && errno ==ENOSYS ) { +printf ("[OK]\tmodify_ldt returned -ENOSYS\n" ); +return false; + } + } +if (ret ==0 ) { -uint32_t limit = desc->limit; -if (desc->limit_in_pages) +uint32_t limit = desc.limit; +if (desc.limit_in_pages) limit = (limit <<12 ) +4095 ; -check_valid_segment (desc->entry_number,1 , ar, limit, true); +check_valid_segment (desc.entry_number, ldt, ar, limit, true);return true; - }else if (errno ==ENOSYS ) { -printf ("[OK]\tmodify_ldt returned -ENOSYS\n" ); -return false; }else { -if (desc->seg_32bit) { -printf ("[FAIL]\tUnexpected modify_ldt failure %d\n" , +if (desc.seg_32bit) { +printf ("[FAIL]\tUnexpected %s failure %d\n" , + ldt ?"modify_ldt" :"set_thread_area" , errno); nerrs++;return false; }else { -printf ("[OK]\tmodify_ldt rejected 16 bit segment\n" ); +printf ("[OK]\t%s rejected 16 bit segment\n" , + ldt ?"modify_ldt" :"set_thread_area" );return false; } }
@@ -168,7 +189,7 @@ static bool install_valid_mode(const struct user_desc *desc, uint32_t ar,static bool install_valid (const struct user_desc *desc,uint32_t ar) { -return install_valid_mode (desc, ar, false); +return install_valid_mode (desc, ar, false, true); }static void install_invalid (const struct user_desc *desc,bool oldmode)
PATCH 4/5 selftests/x86/ldt_gdt: Run most existing LDT test cases against the GDT as well
In reply to Andy LutomirskiNow that the main test infrastructure supports the GDT, run tests that will pass the kernel's GDT permission tests against the GDT.
--- tools/testing/selftests/x86/ldt_gdt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
tools/testing/selftests/x86/ldt_gdt.c +9 -1
@@ -188,7 +188,15 @@ static bool install_valid_mode(const struct user_desc *d, uint32_t ar,static bool install_valid (const struct user_desc *desc,uint32_t ar) { -return install_valid_mode (desc, ar, false, true); +bool ret =install_valid_mode (desc, ar, false, true); + +if (desc->contents <=1 && desc->seg_32bit && + !desc->seg_not_present) { +/* Should work in the GDT, too. */ +install_valid_mode (desc, ar, false, false); + } + +return ret; }static void install_invalid (const struct user_desc *desc,bool oldmode)
Signature · 1 line
2.13.6
tip-bot for Andy Lutomirski
merge bot[tip:x86/asm] selftests/x86/ldt_gdt: Run most existing LDT test cases against the GDT as well
selftests/x86/ldt_gdt: Run most existing LDT test cases against the GDT as well
Commit-ID: adedf2893c192dd09b1cc2f2dcfdd7cad99ec49d Gitweb: https://git.kernel.org/tip/adedf2893c192dd09b1cc2f2dcfdd7cad99ec49d Author: Andy Lutomirski <[email protected]> AuthorDate: Sat, 4 Nov 2017 04:19:51 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 7 Nov 2017 11:13:43 +0100
selftests/x86/ldt_gdt: Run most existing LDT test cases against the GDT as well
Now that the main test infrastructure supports the GDT, run tests that will pass the kernel's GDT permission tests against the GDT.
--- tools/testing/selftests/x86/ldt_gdt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
tools/testing/selftests/x86/ldt_gdt.c +9 -1
@@ -189,7 +189,15 @@ static bool install_valid_mode(const struct user_desc *d, uint32_t ar,static bool install_valid (const struct user_desc *desc,uint32_t ar) { -return install_valid_mode (desc, ar, false, true); +bool ret =install_valid_mode (desc, ar, false, true); + +if (desc->contents <=1 && desc->seg_32bit && + !desc->seg_not_present) { +/* Should work in the GDT, too. */ +install_valid_mode (desc, ar, false, false); + } + +return ret; }static void install_invalid (const struct user_desc *desc,bool oldmode)
PATCH 5/5 selftests/x86/ldt_get: Add a few additional tests for limits
In reply to Andy LutomirskiWe weren't testing the .limit and .limit_in_pages fields very well. Add more tests.
This addition seems to trigger the "bits 16:19 are undefined" issue that was fixed in an earlier patch. I think that, at least on my CPU, the high nibble of the limit ends in LAR bits 16:19.
--- tools/testing/selftests/x86/ldt_gdt.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
tools/testing/selftests/x86/ldt_gdt.c +16 -1
@@ -403,9 +403,24 @@ static void do_simple_tests(void)install_invalid (&desc, false); desc.seg_not_present =0 ; - desc.read_exec_only =0 ; desc.seg_32bit =1 ; + desc.read_exec_only =0 ; + desc.limit =0xfffff ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RWDATA |AR_S |AR_P |AR_DB ); + + desc.limit_in_pages =1 ; + +install_valid (&desc,AR_DPL3 |AR_TYPE_RWDATA |AR_S |AR_P |AR_DB |AR_G ); + desc.read_exec_only =1 ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RODATA |AR_S |AR_P |AR_DB |AR_G ); + desc.contents =1 ; + desc.read_exec_only =0 ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RWDATA_EXPDOWN |AR_S |AR_P |AR_DB |AR_G ); + desc.read_exec_only =1 ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RODATA_EXPDOWN |AR_S |AR_P |AR_DB |AR_G ); + + desc.limit =0 ;install_invalid (&desc, true); }
Signature · 1 line
2.13.6
tip-bot for Andy Lutomirski
merge bot[tip:x86/asm] selftests/x86/ldt_get: Add a few additional tests for limits
selftests/x86/ldt_get: Add a few additional tests for limits
Commit-ID: fec8f5ae1715a01c72ad52cb2ecd8aacaf142302 Gitweb: https://git.kernel.org/tip/fec8f5ae1715a01c72ad52cb2ecd8aacaf142302 Author: Andy Lutomirski <[email protected]> AuthorDate: Sat, 4 Nov 2017 04:19:52 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 7 Nov 2017 11:13:43 +0100
selftests/x86/ldt_get: Add a few additional tests for limits
We weren't testing the .limit and .limit_in_pages fields very well. Add more tests.
This addition seems to trigger the "bits 16:19 are undefined" issue that was fixed in an earlier patch. I think that, at least on my CPU, the high nibble of the limit ends in LAR bits 16:19.
--- tools/testing/selftests/x86/ldt_gdt.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
tools/testing/selftests/x86/ldt_gdt.c +16 -1
@@ -404,9 +404,24 @@ static void do_simple_tests(void)install_invalid (&desc, false); desc.seg_not_present =0 ; - desc.read_exec_only =0 ; desc.seg_32bit =1 ; + desc.read_exec_only =0 ; + desc.limit =0xfffff ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RWDATA |AR_S |AR_P |AR_DB ); + + desc.limit_in_pages =1 ; + +install_valid (&desc,AR_DPL3 |AR_TYPE_RWDATA |AR_S |AR_P |AR_DB |AR_G ); + desc.read_exec_only =1 ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RODATA |AR_S |AR_P |AR_DB |AR_G ); + desc.contents =1 ; + desc.read_exec_only =0 ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RWDATA_EXPDOWN |AR_S |AR_P |AR_DB |AR_G ); + desc.read_exec_only =1 ; +install_valid (&desc,AR_DPL3 |AR_TYPE_RODATA_EXPDOWN |AR_S |AR_P |AR_DB |AR_G ); + + desc.limit =0 ;install_invalid (&desc, true); }
Quoted 12 lines · Andy Lutomirski
This improves and robustifies the
ldt_gdttest and fixes compiler warnings in theprotection_keystest.Andy Lutomirski (5):
selftests/x86/protection_keys: Fix syscall NR redefinition warnings selftests/x86/ldt_gdt: Robustify againstset_thread_area()and LAR
oddities
selftests/x86/ldt_gdt: Add infrastructure to testset_thread_area()selftests/x86/ldt_gdt: Run most existing LDT test cases against the
GDT as well
selftests/x86/ldt_get: Add a few additional tests for limits
Quoted 3 lines
tools/testing/selftests/x86/ldt_gdt.c | 88 +++++++++++++++++++++------ tools/testing/selftests/x86/protection_keys.c | 24 ++++++-- 2 files changed, 88 insertions(+), 24 deletions(-)
I'm still getting this build failure when typing 'make' in tools/testing/selftests/x86:
gcc -m32 -o /home/mingo/tip/tools/testing/selftests/x86/protection_keys_32 -O2 -g -std=gnu99 -pthread -Wall -no-pie protection_keys.c -lrt -ldl -lm In file included from /usr/include/signal.h:57:0,
from protection_keys.c:33:
protection_keys.c: In function ‘signal_handler’:
protection_keys.c:253:6: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
u64 si_pkey;
^protection_keys.c:253:6: error: expected expression before ‘.’ token
...
Makefile:47: recipe for target '/home/mingo/tip/tools/testing/selftests/x86/protection_keys_32' failed
Plus I'm also getting these warnings even with all your fixes applied:
gcc -m32 -o /home/mingo/tip/tools/testing/selftests/x86/mpx-mini-test_32 -O2 -g -std=gnu99 -pthread -Wall -no-pie mpx-mini-test.c -lrt -ldl -lm mpx-mini-test.c: In function ‘insn_test_failed’:
mpx-mini-test.c:1406:3: warning: array subscript is above array bounds [-Warray-bounds]
printf("bte[1]: %lx\n", bte->contents[1]);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mpx-mini-test.c:1407:3: warning: array subscript is above array bounds [-Warray-bounds]
printf("bte[2]: %lx\n", bte->contents[2]);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mpx-mini-test.c:1408:3: warning: array subscript is above array bounds [-Warray-bounds]
printf("bte[3]: %lx\n", bte->contents[3]);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Thanks,
Ingo