Created attachment 14032 [details] ld.so/cc1 ld.so --verify cc1 segfaults with attached files on arm 32bit (these are arm6hf, but verified behavior is the same also on armv7hf). For plenty other binaries it works fine, it appears to have issues with those coming from gcc though.
Looks like it might be related to linux kernel 5.17. It appears to work fine with 5.15 and 5.16. likely not very useful but strace between versions: 5.15: execve("/lib/ld-linux-armhf.so.3", ["/lib/ld-linux-armhf.so.3", "--verify", "/usr/lib/gcc/armv6hl-pld-linux-g"...], 0x7e8365ac /* 52 vars */) = 0 brk(NULL) = 0xd93000 openat(AT_FDCWD, "/usr/lib/gcc/armv6hl-pld-linux-gnueabi/11.2.0/cc1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\2\0(\0\1\0\0\0P(\32\0004\0\0\0"..., 512) = 512 mmap2(0x10000, 20832256, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x10000 mmap2(0x13fe000, 98304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x13de000) = 0x13fe000 mmap2(0x1416000, 945808, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x1416000 close(3) = 0 exit_group(0) = ? +++ exited with 0 +++ 5.17: execve("/lib/ld-linux-armhf.so.3", ["/lib/ld-linux-armhf.so.3", "--verify", "/usr/lib/gcc/armv6hl-pld-linux-g"...], 0x7ec004ec /* 57 vars */) = 0 brk(NULL) = 0xc89000 openat(AT_FDCWD, "/usr/lib/gcc/armv6hl-pld-linux-gnueabi/11.2.0/cc1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\2\0(\0\1\0\0\0P(\32\0004\0\0\0"..., 512) = 512 mmap2(0x10000, 20832256, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x10000 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x10} ---
It seems to be caused by fixed address 0x10000 used for mmap as seen in strace. With kernel 5.16 plenty of space is available: /proc/<pid>/maps just before mmap (5.16): 76fc4000-76fed000 r-xp 00000000 b3:02 393320 /lib/ld-linux-armhf.so.3 76ffa000-76ffb000 r-xp 00000000 00:00 0 [sigpage] 76ffb000-76ffc000 r--p 00000000 00:00 0 [vvar] 76ffc000-76ffd000 r-xp 00000000 00:00 0 [vdso] 76ffd000-77000000 rw-p 00029000 b3:02 393320 /lib/ld-linux-armhf.so.3 7efdf000-7f000000 rw-p 00000000 00:00 0 [stack] ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors] /proc/<pid>/maps just before mmap (5.17): 00400000-00429000 r-xp 00000000 b3:02 393320 /lib/ld-linux-armhf.so.3 00439000-0043c000 rw-p 00029000 b3:02 393320 /lib/ld-linux-armhf.so.3 76ffd000-76ffe000 r-xp 00000000 00:00 0 [sigpage] 76ffe000-76fff000 r--p 00000000 00:00 0 [vvar] 76fff000-77000000 r-xp 00000000 00:00 0 [vdso] 7efdf000-7f000000 rw-p 00000000 00:00 0 [stack] ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors] so larger binaries (>4MB) start to overlap with first region under 5.17 and result in SIGSEGV. Not sure who's to blame for this situation though.
Address for mmap is defined as "l->l_addr + c->mapstart" where l->l_addr==0 and c->mapstart==0x10000. As far as I can tell the latter comes from ELF so either 5.17 loads binary in wrong place or l->l_addr should be adjusted accordingly. In this code path nothing seems to set l->l_addr to anything but 0 though admittedly this is all way over my head.
cc1 is an ET_EXEC, so it can only be loaded at a fixed address. This looks like a kernel bug if it loads a shared object at such a low address.
For reference kernel issue reported at: https://bugzilla.kernel.org/show_bug.cgi?id=215734