summaryrefslogtreecommitdiff
path: root/src/ldso
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2013-07-31 14:42:08 -0400
committerRich Felker <dalias@aerifal.cx>2013-07-31 14:42:08 -0400
commit339516addbde87760f3c0f175a4abcf5d629df54 (patch)
treed367924554efd34bb36581dc047d53190a14a358 /src/ldso
parentc4f49a6a726fcd07bb15198ac4556100320934a9 (diff)
downloadmusl-339516addbde87760f3c0f175a4abcf5d629df54.tar.gz
add some sanity checks in dynamic loader code
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.
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/dynlink.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 59ec5b79..f4988e73 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -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;