freestanding hex dumper예요, x86-64 Linux, 자체 _start, raw syscall, -nostdlib -static -no-pie로 링크해요. 빌드는 undefined symbol 없이 깨끗하게 되는데, ./hexd -v < /etc/hostname을 실행하면 첫 note() 출력 전에 segfault가 나요.
gdb로 보면 fault는 hexd_main 맨 앞에서, 제가 쓰지 않은 %fs 경유 로드에서 나고 fault address는 0x28이에요. 그 전에는 아무것도 실행되지 않았어요. -fno-stack-protector를 주면 문제없어요.
protector가 필요로 한다고 생각한 두 심볼을 정의했어요:
unsigned long __stack_chk_guard = 0x595e9fbd94fda766UL;
__attribute__((noreturn))
void __stack_chk_fail(void) { /* write to fd 2, sys_exit(134) */ }
CFLAGS = -std=c11 -O2 -Wall -Wextra -ffreestanding -fno-pic -fno-asynchronous-unwind-tables -fstack-protector-strong
guard가 평범한 전역 변수로 바로 저기 있는데, 컴파일러는 왜 %fs를 읽는 걸까요? _start의 스택 정렬은 맞고, -mno-red-zone도 달라진 게 없어요. 뭔가를 호출하기 전에 prctl이랑 ARCH_SET_FS로 thread pointer를 직접 세팅해야 하는 건가요?
영어에서 번역·원문 보기Freestanding hex dumper, x86-64 Linux, own _start, raw syscalls, linked with -nostdlib -static -no-pie. It builds clean with no undefined symbols, but ./hexd -v < /etc/hostname segfaults before the first note() output.
Under gdb the fault is at the very top of hexd_main, on a load through %fs that I didn't write, fault address 0x28. Nothing else has run. With -fno-stack-protector it's fine.
I defined the two symbols I thought the protector wanted:
unsigned long __stack_chk_guard = 0x595e9fbd94fda766UL;
__attribute__((noreturn))
void __stack_chk_fail(void) { /* write to fd 2, sys_exit(134) */ }
CFLAGS = -std=c11 -O2 -Wall -Wextra -ffreestanding -fno-pic -fno-asynchronous-unwind-tables -fstack-protector-strong
Why is the compiler reading %fs at all, when the guard is sitting right there as a plain global? Stack alignment in _start is right, and -mno-red-zone changed nothing. Do I have to set up the thread pointer myself, with prctl and ARCH_SET_FS, before calling anything?