ldd(1) overrides ld.so(1)'s _rtld_pagesz, but it may causes SIGFPE in xmalloc().

Issue #86 resolved
Takehiko NOZAKI repo owner created an issue

first, _rtld_pagesz is used for ld.so(1)'s own malloc(so called imalloc).

http://nxr.netbsd.org/xref/src/libexec/ld.elf_so/xmalloc.c#188

    175 static void *
    176 imalloc(size_t nbytes)
    177 {
    ...
    187         if (pagesz == 0) {
    188                 pagesz = n = _rtld_pagesz;
    189                 if (morepages(NPOOLPAGES) == 0)
    190                         return NULL;

_rtld_pagesz may assigned certain value(>0) in _rtld().

http://nxr.netbsd.org/xref/src/libexec/ld.elf_so/rtld.c#519

    402 Elf_Addr
    403 _rtld(Elf_Addr *sp, Elf_Addr relocbase)
    404 {
    ...
    519     _rtld_pagesz = (int)pAUX_pagesz->a_v;

but ldd(1) may override this symbol.

http://nxr.netbsd.org/xref/src/usr.bin/ldd/ldd.c#103

    103 size_t _rtld_pagesz;

and assign value(>0) taken from sysconf(3) in elf{32,64}_ldd().

http://nxr.netbsd.org/xref/src/usr.bin/ldd/ldd_elfxx.c#105

     94 int
     95 ELFNAME(ldd)(int fd, char *path, const char *fmt1, const char *fmt2)
     96 {
    ...
    105     _rtld_pagesz = sysconf(_SC_PAGESIZE);

so that if ld.so(1) load ldd(1)'s binary and don't call elf{32,64}_ldd() _rtld_pagesz is leaved as zero.

$ gdb --quiet /usr/bin/ldd
Reading symbols from /usr/bin/ldd...done.
(gdb) b usage
Breakpoint 1 at 0x401510: file /usr/src/usr.bin/ldd/build/../ldd.c, line 111.
(gdb) run
Starting program: /usr/bin/ldd

Breakpoint 1, usage () at /usr/src/usr.bin/ldd/build/../ldd.c:111
111     {
(gdb) print _rtld_pagesz
$1 = 0
(gdb)

so, if libc called ld.so(3)'s function that uses imalloc internally (eg: _rtld_tls_get_addr() for Thread Local Storage), imalloc's NPOOLPAGES macro may throws SIGFPE(division by zero exception).

http://nxr.netbsd.org/xref/src/libexec/ld.elf_so/xmalloc.c#98

     98 #define NPOOLPAGES  (32*1024/pagesz)
    ...
    188                 pagesz = n = _rtld_pagesz;
    189                 if (morepages(NPOOLPAGES) == 0)

Comments (4)

  1. Takehiko NOZAKI reporter

    i believe NetBSD's ldd(1) implentation is evil. don't try to parse ELF binary itself. ld.so(1) should implement LD_TRACE_LOADED_OBJECT=1 trace function and ldd(1) must be ld.so(1)'s wrapper application.

  2. Takehiko NOZAKI reporter

    this is kludge fix, again and again real fix is implement LD_TRACE_LOADED_OBJECT=1 trace function.

  3. Log in to comment