DynamoRIO / DynamoRIO/dynamorio
Match glibc behavior when passing arguments to ifunc resolvers in private loader
- Dominant language
- C
- Stars
- 3.2k
- Forks
- 629
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 31
Description
Currently, our private loader unconditionally passes no arguments to ifunc resolvers. On x86_64 and x86_32, this exactly matches the behavior of glibc 2.41[1][2]. But on aarch32, aarch64 and riscv64, ifunc resolvers take different arguments,
- aarch32: `Elf32_Addr (*)(unsigned long int hwcap)`[3]
- aarch64: `Elf64_Addr (*)(uint64_t hwcap, const __ifunc_arg_t *arg)`[4], where `__ifunc_arg_t` is defined as[5]
```
typedef struct __ifunc_arg_t {
unsigned long _size;
unsigned long _hwcap;
unsigned long _hwcap2;
} __ifunc_arg_t;
```
- riscv64: `ElfW(Addr) (*)(uint64_t hwcap, void *hwprobe, void *reserved)`[6], where hwprobe is a pointer to __riscv_hwprobe[7], a wrapper over riscv_hwprobe syscall, and reserved should be NULL.
Xref #7374 which corrects the prototype on riscv64. Wrong arguments passed to resolvers are causing segfaults with a newer glibc and clients depending on glibc attached.
Additionally, the prototype of ifunc resolvers varies between glibc versions,
- aarch32
- Before glibc commit `73da6bacfd (arm: Pass hwcap to ifuncs., 2012-05-25)` which landed in v2.17: `Elf32_Addr (*)(void)` (no argument)
- aarch64
- Before glibc commit `2b8a3c86e7 (aarch64: new ifunc resolver ABI, 2019-04-23)` which landed in v2.30: `Elf64_Addr (*)(uint64_t addr)`
- Before glibc commit `7520ff8c74 (aarch64: Enable ifunc support., 2013-11-25)` which landed v2.19: `Elf64_Addr (*)(void)`. But this is the commit that really enables ifunc support on AArch64, so maybe we could omit earlier versions.
- riscv64
- Before glibc commit `78308ce77a (riscv: Add __riscv_hwprobe pointer to ifunc calls, 2024-02-27)` which landed in v2.40: `ElfW(Addr) (*) (uint64_t hwcap, void *reserved)`, where reserved should be NULL.
We may parse the version of dynamic loader and pass the exactly same arguments to resolvers as the glibc loader does.
[1]: https://github.com/bminor/glibc/blob/74f59e9271cbb4071671e5a474e7d4f1622b186f/sysdeps/x86_64/].h#L32
[2]: https://github.com/bminor/glibc/blob/74f59e9271cbb4071671e5a474e7d4f1622b186f/sysdeps/i386/dl-irel.h#L32
[3]: https://github.com/bminor/glibc/blob/74f59e9271cbb4071671e5a474e7d4f1622b186f/sysdeps/arm/dl-irel.h#L33
[4]: https://github.com/bminor/glibc/blob/74f59e9271cbb4071671e5a474e7d4f1622b186f/sysdeps/aarch64/dl-irel.h#L40-L41
[5]: https://github.com/bminor/glibc/blob/74f59e9271cbb4071671e5a474e7d4f1622b186f/sysdeps/aarch64/sys/ifunc.h#L33-L38
[6]: https://github.com/bminor/glibc/blob/74f59e9271cbb4071671e5a474e7d4f1622b186f/sysdeps/riscv/dl-irel.h#L37-L38
[7]: https://github.com/bminor/glibc/blob/74f59e9271cbb4071671e5a474e7d4f1622b186f/sysdeps/unix/sysv/linux/riscv/hwprobe.c#L25-L36
Contributor guide
Assessment
This issue has not been assessed yet.