]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Fix broken mmap() usage in nlist() by switching to pread()
authorGuillem Jover <guillem@hadrons.org>
Tue, 13 Jun 2017 23:49:25 +0000 (01:49 +0200)
committerGuillem Jover <guillem@hadrons.org>
Mon, 19 Jun 2017 01:17:21 +0000 (03:17 +0200)
The offset is not page aligned, which makes mmap() return EINVAL on
Linux. Switch to use pread() which handles unaligned offset and non-page
sized reads, and because we are already loading parts of the executable
by read() calls, so there's not much point in using mmap() anyway.

src/nlist.c

index e5dede07a2d3cdc45faee57f2d8004790289a3db..0932f59fa79e05ea16da701e8fb68248a515ebc4 100644 (file)
@@ -36,6 +36,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <nlist.h>
@@ -131,7 +132,6 @@ __fdnlist(int fd, struct nlist *list)
        char *strtab = NULL;
        Elf_Shdr *shdr = NULL;
        Elf_Word shdr_size;
-       void *base;
        struct stat st;
 
        /* Make sure obj is OK */
@@ -150,12 +150,13 @@ __fdnlist(int fd, struct nlist *list)
                return (-1);
        }
 
-       /* mmap section header table */
-       base = mmap(NULL, (size_t)shdr_size, PROT_READ, 0, fd,
-           (off_t)ehdr.e_shoff);
-       if (base == MAP_FAILED)
+       shdr = malloc((size_t)shdr_size);
+       if (shdr == NULL)
                return (-1);
-       shdr = (Elf_Shdr *)base;
+
+       /* Load section header table. */
+       if (pread(fd, shdr, (size_t)shdr_size, (off_t)ehdr.e_shoff) < 0)
+               goto done;
 
        /*
         * Find the symbol table entry and it's corresponding
@@ -179,16 +180,17 @@ __fdnlist(int fd, struct nlist *list)
                goto done;
        }
        /*
-        * Map string table into our address space.  This gives us
+        * Load string table into our address space.  This gives us
         * an easy way to randomly access all the strings, without
         * making the memory allocation permanent as with malloc/free
         * (i.e., munmap will return it to the system).
         */
-       base = mmap(NULL, (size_t)symstrsize, PROT_READ, 0, fd,
-           (off_t)symstroff);
-       if (base == MAP_FAILED)
+       strtab = malloc((size_t)symstrsize);
+       if (strtab == NULL)
+               goto done;
+
+       if (pread(fd, strtab, (size_t)symstrsize, (off_t)symstroff) < 0)
                goto done;
-       strtab = (char *)base;
 
        /*
         * clean out any left-over information for all valid entries.
@@ -230,6 +232,7 @@ __fdnlist(int fd, struct nlist *list)
                        name = strtab + s->st_name;
                        if (name[0] == '\0')
                                continue;
+
                        for (p = list; !ISLAST(p); p++) {
                                if ((p->n_un.n_name[0] == '_' &&
                                    strcmp(name, p->n_un.n_name+1) == 0)
@@ -244,10 +247,8 @@ __fdnlist(int fd, struct nlist *list)
        }
   done:
        errsave = errno;
-       if (strtab != NULL)
-               munmap(strtab, symstrsize);
-       if (shdr != NULL)
-               munmap(shdr, shdr_size);
+       free(strtab);
+       free(shdr);
        errno = errsave;
        return (nent);
 }