From 23f655a9313a6b962e072f12534982b925ecb8f7 Mon Sep 17 00:00:00 2001 From: Daniel Xu Date: Fri, 6 Dec 2024 12:36:07 -0800 Subject: [PATCH] Include header for basename() bpftrace has an appimage build which we configure through nix. Recently we upgraded from nix 24.05 to nix 24.11. After the upgrade, we started seeing a segfault on appimage startup: Program received signal SIGSEGV, Segmentation fault. 0x0000000000477598 in strlen () (gdb) where #0 0x0000000000477598 in strlen () #1 0x0000000000403c46 in build_mount_point () #2 0x00000000004016f8 in main () Disassembling build_mount_point() reveals the following: 0x0000000000403c36 <+22>: call 0x471833 0x0000000000403c3b <+27>: movslq %eax,%r13 0x0000000000403c3e <+30>: mov %r13,%rdi 0x0000000000403c41 <+33>: call 0x47758b That is, the call to basename() is on a valid string (I checked). But following the call, the return value is read from %eax as a 32-bit value and then extend moved into 64-bit %rdi - argument 1 for the subsequent call to strlen() - as specified by System V ABI for x86-64. Obviously truncating a 64-bit pointer into 32-bits and then sign extending it into a 64-bit value is not correct. I turned to the build logs to check for clues. That's where I found this warning: /nix/store/llifij4cb8171wy2y2a74wxv53v636zr-source/src/main.c: In function 'build_mount_point': /nix/store/llifij4cb8171wy2y2a74wxv53v636zr-source/src/main.c:781:21: warning: implicit declaration of function 'basename' [-Wimplicit-function-declaration] 781 | path_basename = basename(argv0); | ^~~~~~~~ /nix/store/llifij4cb8171wy2y2a74wxv53v636zr-source/src/main.c:781:19: warning: assignment to 'char *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 781 | path_basename = basename(argv0); | ^ It turns out the prototype for basename() was missing so the compiler defaulted to treating the return as an int. Which explains the pointer truncation. The annoying thing is nix hides build warnings by default. Otherwise I probably would've noticed earlier. The fix is to include the proper header. The segfault goes away after doing so. --- src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.c b/src/main.c index 82b4241..cd003bf 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ extern dev_t sqfs_makedev(int maj, int min); extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args* outargs); +#include #include #include #include