selftests/size: Fix SIGSEGV on 32-bit x86 due to uninitialized vDSO pointer
PATCH 1/1 selftests/size: Fix SIGSEGV on 32-bit x86 due to uninitialized vDSO pointer
Commit 6b64a650f0b2 ("kselftest: Minimise dependency of get_size on C library interfaces") replaced direct C library calls with syscall() to avoid accessing uninitialized TLS on x86_64 when built with -nostartfiles.
However, on 32-bit x86 (i386), the C library's syscall() wrapper itself relies on CRT startup initialization to dispatch system calls via the vDSO entry point:
- In glibc (libc.a), syscall() executes "call *%gs:0x10", reading the __kernel_vsyscall pointer from the Thread Control Block (TCB).
- In Android Bionic (libc.a), syscall() calls __kernel_syscall(), which returns the global __libc_sysinfo pointer in .bss.
Because get_size is compiled with -static -ffreestanding -nostartfiles and defines its own _start, CRT and TLS initialization never run. As a result, calling libc's syscall() on 32-bit x86 dereferences an uninitialized %gs selector or jumps to NULL (0x0), crashing immediately with SIGSEGV.
Provide a local syscall() implementation on __i386__ that invokes "int $0x80" directly, avoiding the C library's syscall() wrapper and its CRT initialization dependency.
--- tools/testing/selftests/size/get_size.c | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
tools/testing/selftests/size/get_size.c +29 -0
@@ -32,6 +32,35 @@#define STDOUT_FILENO 1 +#ifdef __i386__ +#include <stdarg.h> + +/* +* On 32-bit x86, libc's syscall() wrapper invokes the vDSO entry point +* stored in TLS (%gs:0x10 in glibc) or a global variable (__libc_sysinfo +* in Bionic) initialized by CRT startup routines. Because this binary is +* built with -nostartfiles, those pointers remain uninitialized and +* calling libc's syscall() crashes with SIGSEGV. Use int $0x80 directly. +*/ +long syscall (long num, ...) +{ +va_list ap; +long a1, a2, a3, ret; + +va_start (ap, num); + a1 =va_arg (ap, long); + a2 =va_arg (ap, long); + a3 =va_arg (ap, long); +va_end (ap); + + __asm__volatile ("int $0x80" + :"=a" (ret) + :"a" (num),"b" (a1),"c" (a2),"d" (a3) + :"memory" ,"cc" ); +return ret; +} +#endif +static int const char *s) {size_t len =0 ;
Signature · 1 line
2.56.0.rc1.315.gc6ed9934b7-goog