Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Mar 2024 16:55:59 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 277635] ldd (ld-elf.so.1) integer wrap when computing mmap() argument
Message-ID:  <bug-277635-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D277635

            Bug ID: 277635
           Summary: ldd (ld-elf.so.1) integer wrap when computing mmap()
                    argument
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: rtm@lcs.mit.edu

Created attachment 249097
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=3D249097&action=
=3Dedit
elf with huge vaddr that causes ldd / ld.so integer wrap

The attached elf file has a LOAD segment with a p_vaddr big enough
that p_vaddr + p_filesz wraps. This causes rtld-elf's map_object.c to
compute a huge size argument for a call to mmap() to map in the
segment, which causes the segment to be mapped over something
critical. This causes ld-elf.so.1 to crash when called by ldd.

Specifically, data_vaddr ends up larger than data_vlimit in this
map_object() code, so data_vlimit - data_vaddr wraps:

    for (i =3D 0; i <=3D nsegs; i++) {
        /* Overlay the segment onto the proper region. */
        data_offset =3D rtld_trunc_page(segs[i]->p_offset);
        data_vaddr =3D rtld_trunc_page(segs[i]->p_vaddr);
        data_vlimit =3D rtld_round_page(segs[i]->p_vaddr + segs[i]->p_files=
z);
        data_addr =3D mapbase + (data_vaddr - base_vaddr);
        ...;
        if (data_vlimit !=3D data_vaddr &&
            mmap(data_addr, data_vlimit - data_vaddr, data_prot,
            data_flags | MAP_PREFAULT_READ, fd, data_offset) =3D=3D MAP_FAI=
LED) {

Similarly, clever choices of p_vaddr and p_filesz can cause the later

            clear_vaddr =3D segs[i]->p_vaddr + segs[i]->p_filesz;
            clear_addr =3D mapbase + (clear_vaddr - base_vaddr);
            ...;
                memset(clear_addr, 0, nclear);

to write memory outside of mapbase..(mapbase+mapsize).

The attached elf file demonstrates the first problem, though only on riscv.

# objdump -x ldd1c.exe
...
    LOAD off    0x0000000000000700 vaddr 0xffffffffffec5701 paddr
0x0000000000001700 align 2**12
         filesz 0x0000003fbffff0b2 memsz 0x00000000000001b0 flags --x
# ldd ldd1c.exe
ldd1c.exe:
pid 35 (ld-elf.so.1), jid 0, uid 0: exited on signal 11 (core dumped)
/ldd1c.exe: signal 11

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-277635-227>