From d941b59087d34cb93053b638c066bf080122e7bb Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Wed, 16 Jan 2019 22:39:24 -0800 Subject: [PATCH] Turn ptr_to_globals and bb_errno to be non const writing to a const variable is undefined behavior This is undefined as per (C99 6.7.3 paragraph 5) see [1] errno and ptr_to_globals is written to in code, this fails with segfaults when compiled with clang unsigned FAST_FUNC bb_strtou(const char *arg, char **endp, int base) { unsigned long v; char *endptr; if (!endp) endp = &endptr; *endp = (char*) arg; if (!isalnum(arg[0])) return ret_ERANGE(); errno = 0; v = strtoul(arg, endp, base); if (v > UINT_MAX) return ret_ERANGE(); return handle_errors(v, endp); } without 'const' ( working code ) Dump of assembler code for function bb_strtou: 0x0000555555568298 <+0>: push %rbx 0x0000555555568299 <+1>: sub $0x10,%rsp 0x000055555556829d <+5>: test %rsi,%rsi 0x00005555555682a0 <+8>: lea 0x8(%rsp),%rbx 0x00005555555682a5 <+13>: cmovne %rsi,%rbx 0x00005555555682a9 <+17>: mov %rdi,(%rbx) 0x00005555555682ac <+20>: mov (%rdi),%al 0x00005555555682ae <+22>: lea -0x30(%rax),%ecx 0x00005555555682b1 <+25>: cmp $0xa,%cl 0x00005555555682b4 <+28>: jb 0x5555555682be 0x00005555555682b6 <+30>: or $0x20,%al 0x00005555555682b8 <+32>: add $0x9f,%al 0x00005555555682ba <+34>: cmp $0x1a,%al 0x00005555555682bc <+36>: jae 0x5555555682dc 0x00005555555682be <+38>: mov 0x107da3(%rip),%rax # 0x555555670068 => 0x00005555555682c5 <+45>: movl $0x0,(%rax) 0x00005555555682cb <+51>: mov %rbx,%rsi 0x00005555555682ce <+54>: callq 0x555555564310 0x00005555555682d3 <+59>: mov %rax,%rcx 0x00005555555682d6 <+62>: shr $0x20,%rcx 0x00005555555682da <+66>: je 0x5555555682f0 0x00005555555682dc <+68>: mov 0x107d85(%rip),%rax # 0x555555670068 0x00005555555682e3 <+75>: movl $0x22,(%rax) 0x00005555555682e9 <+81>: mov $0xffffffff,%eax 0x00005555555682ee <+86>: jmp 0x5555555682fb 0x00005555555682f0 <+88>: mov %rax,%rdi 0x00005555555682f3 <+91>: mov %rbx,%rsi 0x00005555555682f6 <+94>: callq 0x5555555681e8 0x00005555555682fb <+99>: add $0x10,%rsp 0x00005555555682ff <+103>: pop %rbx 0x0000555555568300 <+104>: retq here address of bb_errno is valid rax = 0x7ffff7cac6c0 with 'const' ( non-working code ) Dump of assembler code for function bb_strtou: 0x00005555555682a4 <+0>: push %r14 0x00005555555682a6 <+2>: push %rbx 0x00005555555682a7 <+3>: push %rax 0x00005555555682a8 <+4>: test %rsi,%rsi 0x00005555555682ab <+7>: mov %rsp,%rbx 0x00005555555682ae <+10>: cmovne %rsi,%rbx 0x00005555555682b2 <+14>: mov %rdi,(%rbx) 0x00005555555682b5 <+17>: mov (%rdi),%al 0x00005555555682b7 <+19>: lea -0x30(%rax),%ecx 0x00005555555682ba <+22>: cmp $0xa,%cl 0x00005555555682bd <+25>: jb 0x5555555682d6 0x00005555555682bf <+27>: or $0x20,%al 0x00005555555682c1 <+29>: add $0x9f,%al 0x00005555555682c3 <+31>: cmp $0x1a,%al 0x00005555555682c5 <+33>: jb 0x5555555682d6 0x00005555555682c7 <+35>: mov 0x107d9a(%rip),%rax # 0x555555670068 0x00005555555682ce <+42>: movl $0x22,(%rax) 0x00005555555682d4 <+48>: jmp 0x5555555682fc 0x00005555555682d6 <+50>: mov 0x107d8b(%rip),%r14 # 0x555555670068 => 0x00005555555682dd <+57>: movl $0x0,(%r14) 0x00005555555682e4 <+64>: mov %rbx,%rsi 0x00005555555682e7 <+67>: callq 0x555555564300 0x00005555555682ec <+72>: mov %rax,%rcx 0x00005555555682ef <+75>: shr $0x20,%rcx 0x00005555555682f3 <+79>: je 0x555555568303 0x00005555555682f5 <+81>: movl $0x22,(%r14) 0x00005555555682fc <+88>: mov $0xffffffff,%eax 0x0000555555568301 <+93>: jmp 0x55555556830e 0x0000555555568303 <+95>: mov %rax,%rdi 0x0000555555568306 <+98>: mov %rbx,%rsi 0x0000555555568309 <+101>: callq 0x5555555681f4 0x000055555556830e <+106>: add $0x8,%rsp 0x0000555555568312 <+110>: pop %rbx 0x0000555555568313 <+111>: pop %r14 0x0000555555568315 <+113>: retq r14 is 0x0 and writing to this ofcourse ends up in segfault [1] https://bugs.llvm.org/show_bug.cgi?id=39919 Signed-off-by: Khem Raj --- coreutils/test.c | 2 +- include/libbb.h | 4 ++-- libbb/lineedit.c | 2 +- shell/ash.c | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) --- a/coreutils/test.c +++ b/coreutils/test.c @@ -401,7 +401,7 @@ struct test_statics { }; /* See test_ptr_hack.c */ -extern struct test_statics *const test_ptr_to_statics; +extern struct test_statics *test_ptr_to_statics; #define S (*test_ptr_to_statics) #define args (S.args ) --- a/include/libbb.h +++ b/include/libbb.h @@ -342,7 +342,7 @@ struct BUG_off_t_size_is_misdetected { #if defined(__GLIBC__) /* glibc uses __errno_location() to get a ptr to errno */ /* We can just memorize it once - no multithreading in busybox :) */ -extern int *const bb_errno; +extern int *bb_errno; #undef errno #define errno (*bb_errno) #endif @@ -2168,7 +2168,7 @@ struct globals; /* '*const' ptr makes gcc optimize code much better. * Magic prevents ptr_to_globals from going into rodata. * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */ -extern struct globals *const ptr_to_globals; +extern struct globals *ptr_to_globals; #if defined(__clang_major__) && __clang_major__ >= 9 /* Clang/llvm drops assignment to "constant" storage. Silently. --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -181,7 +181,7 @@ struct lineedit_statics { }; /* See lineedit_ptr_hack.c */ -extern struct lineedit_statics *const lineedit_ptr_to_statics; +extern struct lineedit_statics * lineedit_ptr_to_statics; #define S (*lineedit_ptr_to_statics) #define state (S.state ) --- a/shell/ash.c +++ b/shell/ash.c @@ -300,10 +300,9 @@ typedef long arith_t; * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable * this optimization. */ -#ifndef BB_GLOBAL_CONST -# define BB_GLOBAL_CONST const -#endif +#undef BB_GLOBAL_CONST +#define BB_GLOBAL_CONST /* ============ Hash table sizes. Configurable. */