Bug 277629

Summary: ldd (ld-elf.so.1) uses p_vaddr without checking
Product: Base System Reporter: Robert Morris <rtm>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Some People CC: emaste, kib
Priority: ---    
Version: CURRENT   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
corrupt elf file that causes ldd to crash due to its use of p_vaddr none

Description Robert Morris 2024-03-11 13:57:27 UTC
Created attachment 249091 [details]
corrupt elf file that causes ldd to crash due to its use of p_vaddr

When ldd calls dlopen(..., RTLD_TRACE), ld-elf.so.1's map_object()
sets obj->dynamic from a p_vaddr without checking:

        case PT_DYNAMIC:
            phdyn = phdr;
    ...;
    obj->dynamic = (const Elf_Dyn *)(obj->relocbase + phdyn->p_vaddr);

and digest_dynamic1() dereferences it:

    dynp = obj->dynamic;
    ...;
    for (;  dynp->d_tag != DT_NULL;  dynp++) {

I've attached a corrupt elf file with the relevant p_vaddr set to
0x7ffffffff9699fff. This example happens to cause ldd to crash only on
a riscv machine (not amd64).

# uname -a
FreeBSD  15.0-CURRENT FreeBSD 15.0-CURRENT #270 main-n250982-48b12cb79520-dirty: Sat Mar  9 08:36:40 EST 2024     rtm@zika:/usr/obj/usr/rtm/symbsd/src/riscv.riscv64/sys/RTM riscv
# objdump -x ./ldd7a.exe | grep 0x7fff
 DYNAMIC off    0x0000000000000000 vaddr 0x7ffffffff9699fff paddr 0x0000000000000000 align 2**64
# ldd ./ldd7a.exe 
./ldd7a.exe:
pid 136 (ldd), jid 0, uid 0: exited on signal 11 (core dumped)