Mark Brown broonie@kernel.org writes:
There are things like threads which nolibc struggles with which we want to add coverage for, and the ABI allows us to test most of these even if libc itself does not understand GCS so add a test application built using the system libc.
Reviewed-by: Thiago Jung Bauermann thiago.bauermann@linaro.org Signed-off-by: Mark Brown broonie@kernel.org
tools/testing/selftests/arm64/gcs/.gitignore | 1 + tools/testing/selftests/arm64/gcs/Makefile | 4 +- tools/testing/selftests/arm64/gcs/gcs-util.h | 10 + tools/testing/selftests/arm64/gcs/libc-gcs.c | 736 +++++++++++++++++++++++++++ 4 files changed, 750 insertions(+), 1 deletion(-)
In my FVP VM, this test gets a GCS SIGSEGV before running the first test:
$ sudo ./run_kselftest.sh -t arm64:libc-gcs [sudo] password for bauermann: TAP version 13 1..1 # timeout set to 45 # selftests: arm64: libc-gcs # TAP version 13 # 1..118 # # Starting 118 tests from 32 test cases. # # RUN global.can_call_function ... # Segmentation fault not ok 1 selftests: arm64: libc-gcs # exit=139 $
It happens when returning from the syscall() glibc function that does the clone3 syscall in kselftest_harness.h:
$ /var/tmp/gdb-gcs/bin/gdb -q arm64/libc-gcs Reading symbols from arm64/libc-gcs... (gdb) r Starting program: /var/tmp/selftests-v9/arm64/libc-gcs [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". TAP version 13 1..118 # Starting 118 tests from 32 test cases. # RUN global.can_call_function ... [Detaching after vfork from child process 823]
Program received signal SIGSEGV, Segmentation fault Guarded Control Stack error. syscall () at ../sysdeps/unix/sysv/linux/aarch64/syscall.S:41 [GCS error] warning: 41 ../sysdeps/unix/sysv/linux/aarch64/syscall.S: No such file or directory (gdb) p $_siginfo.si_signo $1 = 11 (gdb) p $_siginfo.si_code $2 = 10 (gdb) p $_siginfo._sifields._sigfault.si_addr $3 = (void *) 0xfffff7ed96b0 <syscall+48> (gdb) disassemble Dump of assembler code for function syscall: 0x0000fffff7ed9680 <+0>: nop 0x0000fffff7ed9684 <+4>: mov w8, w0 0x0000fffff7ed9688 <+8>: mov x0, x1 0x0000fffff7ed968c <+12>: mov x1, x2 0x0000fffff7ed9690 <+16>: mov x2, x3 0x0000fffff7ed9694 <+20>: mov x3, x4 0x0000fffff7ed9698 <+24>: mov x4, x5 0x0000fffff7ed969c <+28>: mov x5, x6 0x0000fffff7ed96a0 <+32>: mov x6, x7 0x0000fffff7ed96a4 <+36>: svc #0x0 0x0000fffff7ed96a8 <+40>: cmn x0, #0xfff 0x0000fffff7ed96ac <+44>: b.cs 0xfffff7ed96b4 <syscall+52> // b.hs, b.nlast => 0x0000fffff7ed96b0 <+48>: ret 0x0000fffff7ed96b4 <+52>: b 0xfffff7e18660 <__GI___syscall_error> 0x0000fffff7ed96b8 <+56>: b 0xfffff7e18660 <__GI___syscall_error> End of assembler dump. (gdb) bt #0 syscall () at ../sysdeps/unix/sysv/linux/aarch64/syscall.S:41 [GCS error] #1 0x0000aaaaaaaa4acc in clone3_vfork () at /home/bauermann/src/linux/tools/testing/selftests/kselftest_harness.h:93 #2 __run_test (f=f@entry=0xaaaaaaac0b88 <_fixture_global>, variant=variant@entry=0xffffffffee00, t=t@entry=0xaaaaaaac0018 <_can_call_function_object>) at /home/bauermann/src/linux/tools/testing/selftests/kselftest_harness.h:1239 [GCS error] #3 0x0000aaaaaaaa2c40 in test_harness_run (argv=0xfffffffff008, argc=1) at /home/bauermann/src/linux/tools/testing/selftests/kselftest_harness.h:1314 #4 main (argc=1, argv=0xfffffffff008) at libc-gcs.c:735 [GCS error] (gdb)
And indeed, the svc call in the disassemble above corrupts the GCS. This is the GCS and lr values right before the svc call:
(gdb) x/i $pc => 0xfffff7ed96a4 <syscall+36>: svc #0x0 (gdb) p/x $lr $3 = 0xaaaaaaaa4acc (gdb) p/x $gcspr $4 = 0xfffff7bfffe8 (gdb) x/g $gcspr 0xfffff7bfffe8: 0x0000aaaaaaaa4acc
So far so good, the tip of the GCS matches $lr. But then:
(gdb) stepi [Detaching after vfork from child process 2491] 39 in ../sysdeps/unix/sysv/linux/aarch64/syscall.S (gdb) x/i $pc => 0xfffff7ed96a8 <syscall+40>: cmn x0, #0xfff (gdb) p/x $gcspr $5 = 0xfffff7bfffe8 (gdb) x/g $gcspr 0xfffff7bfffe8: 0x0000aaaaaaaa4c04 (gdb) p/x $lr $6 = 0xaaaaaaaa4acc
So, right after svc returns, the tip of the GCS is corrupted and will cause the GCS error.