On Mon, Jan 23, 2023 at 05:40:23PM -0800, H. Peter Anvin wrote:
So as per Andrew's comment, add:
register void * rsp asm("%rsp");
...
"+r" (rsp) /* clobber the redzone */
... as the right way to avoid redzone problems.
I played with this more. I found something wrong with this. This doesn't work for me. The compiler still uses red zone despite I use "+r" (rsp).
What did I do wrong?
-----
ammarfaizi2@integral2:/tmp$ gcc -fno-stack-protector -O2 -Wall -Wextra test.c -o test ammarfaizi2@integral2:/tmp$ objdump --no-show-raw-insn -d test | grep "a_leaf_func_with_red_zone>:" -A8 0000000000001180 <a_leaf_func_with_red_zone>: 1180: endbr64 1184: mov $0x1,%eax 1189: mov %rax,-0x8(%rsp) ## BUG!!! 118e: pushf 118f: pop %rax 1190: mov -0x8(%rsp),%rax ## BUG!!! 1195: ret
ammarfaizi2@integral2:/tmp$ clang -O2 -Wall -Wextra test.c -o test ammarfaizi2@integral2:/tmp$ objdump --no-show-raw-insn -d test | grep "a_leaf_func_with_red_zone>:" -A6 0000000000001140 <a_leaf_func_with_red_zone>: 1140: mov $0x1,%eax 1145: mov %rax,-0x8(%rsp) ## BUG!!! 114a: pushf 114b: pop %rax 114c: mov -0x8(%rsp),%rax ## BUG!!! 1151: ret
----- ammarfaizi2@integral2:~$ gcc --version gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ammarfaizi2@integral2:~$ clang --version Ubuntu clang version 16.0.0 (++20230124031324+d63e492562f2-1~exp1~20230124151444.705) Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin
----- test.c:
#include <stdio.h> static inline void clobber_redzone(void) { register void *rsp __asm__("%rsp"); unsigned long rflags;
__asm__ volatile ("pushf; popq %1" : "+r" (rsp), "=r" (rflags)); }
static inline void set_red_zone(long *mem, long val) { __asm__ volatile ("movq %[val], %[mem]" : [mem] "=m" (*mem) : [val] "r" (val)); }
static inline long get_red_zone(long *mem) { long ret;
__asm__ volatile ("movq %[in], %[out]" : [out] "=r" (ret) : [in] "m" (*mem)); return ret; }
__attribute__((__noinline__)) long a_leaf_func_with_red_zone(void) { long x;
set_red_zone(&x, 1); clobber_redzone(); /* The correct retval is 1 */ return get_red_zone(&x); }
int main(void) { printf("ret = %ld\n", a_leaf_func_with_red_zone()); return 0; }