The AT_PHDR of ELF auxiliary vectors should point to the memory address of program header. But binfmt_elf.c calculates this address as follow: NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); which is wrong since e_phoff is the file offset of program header and load_addr is the memory base address from PT_LOAD entry. The ld.so uses AT_PHDR as the memory address of program header. In normal case, since the e_phoff is usually 64 and in the first PT_LOAD region, it is the correct program header address. But if the address of program header isn't equal to the first PT_LOAD address + e_phoff (e.g. Put the program header in other non-consecutive PT_LOAD region), ld.so will try to read program header from wrong address then crash or use incorrect program header.
Created attachment 260719 [details] Example ELF with abnormal proram header offset I move the program header of this ELF to file offset 0x1040, which will be mapped to 0x601040. But AT_PHDR will be 0x401040, which is wrong.
I got the same problem. It seems that the issue still exists in the kernel.
I am now trying to make a patch to fix this issue and I think there are two problems around AT_PHDR. The first one is the current kernel use `exec->e_phoff` as the offset for program headers as discussed in this issue. The second one is it calculates `load_addr` from the first program header. This should be the minimum value for all program headers as discussed in https://bugs.launchpad.net/qemu/+bug/1885332.