add some sanity checks in dynamic loader code
authorRich Felker <dalias@aerifal.cx>
Wed, 31 Jul 2013 18:42:08 +0000 (14:42 -0400)
committerRich Felker <dalias@aerifal.cx>
Wed, 31 Jul 2013 18:42:08 +0000 (14:42 -0400)
reject elf files which are not ET_EXEC/ET_DYN type as bad exec format,
and reject ET_EXEC files when they cannot be loaded at the correct
address, since they are not relocatable at runtime. the main practical
benefit of this is to make dlopen of the main program fail rather than
producing an unsafe-to-use handle.

src/ldso/dynlink.c

index 59ec5b79124b70a3d184b54d60b4303529428f56..f4988e7371a46eaa44d7957c4e28bef1d56d0679 100644 (file)
@@ -320,6 +320,10 @@ static void *map_library(int fd, struct dso *dso)
        ssize_t l = read(fd, buf, sizeof buf);
        if (l<(int)sizeof *eh) return 0;
        eh = buf;
+       if (eh->e_type != ET_DYN && eh->e_type != ET_EXEC) {
+               errno = ENOEXEC;
+               return 0;
+       }
        phsize = eh->e_phentsize * eh->e_phnum;
        if (phsize + sizeof *eh > l) return 0;
        if (eh->e_phoff + phsize > l) {
@@ -362,6 +366,12 @@ static void *map_library(int fd, struct dso *dso)
         * amount of virtual address space to map over later. */
        map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
        if (map==MAP_FAILED) return 0;
+       /* If the loaded file is not relocatable and the requested address is
+        * not available, then the load operation must fail. */
+       if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
+               errno = EBUSY;
+               goto error;
+       }
        base = map - addr_min;
        dso->phdr = 0;
        dso->phnum = 0;