summaryrefslogtreecommitdiff
path: root/src/ldso
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-06-06 11:21:28 -0400
committerRich Felker <dalias@aerifal.cx>2012-06-06 11:21:28 -0400
commitf7d15dcc543c3b65c751064a5e51a0ec462f3cdb (patch)
tree1380d48118767c352e1f4604d46519226e2c6bd5 /src/ldso
parent908bed20cd877a6c0c290c0c56cc7057ecc00296 (diff)
downloadmusl-f7d15dcc543c3b65c751064a5e51a0ec462f3cdb.tar.gz
musl-f7d15dcc543c3b65c751064a5e51a0ec462f3cdb.tar.bz2
musl-f7d15dcc543c3b65c751064a5e51a0ec462f3cdb.tar.xz
musl-f7d15dcc543c3b65c751064a5e51a0ec462f3cdb.zip
treat failure of mprotect in map_library as a fatal load failure
the error will propagate up and be printed to the user at program start time; at runtime, dlopen will just fail and leave a message for dlerror. previously, if mprotect failed, subsequent attempts to perform relocations would crash the program. this was resulting in an increasing number of false bug reports on grsec systems where rwx permission is not possible in cases where users were wrongly attempting to use non-PIC code in shared libraries. supporting that usage is in theory possible, but the x86_64 toolchain does not even support textrels, and the cost of keeping around the necessary information to handle textrels without rwx permissions is disproportionate to the benefit (which is essentially just supporting broken library setups on grsec machines). also, i unified the error-out code in map_library now that there are 3 places from which munmap might have to be called.
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/dynlink.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 820e8a36..49ea5e9c 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -268,23 +268,20 @@ static void *map_library(int fd, size_t *lenp, unsigned char **basep, size_t *dy
prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
((ph->p_flags&PF_X) ? PROT_EXEC : 0));
- if (mmap(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED) {
- munmap(map, map_len);
- return 0;
- }
+ if (mmap(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
+ goto error;
if (ph->p_memsz > ph->p_filesz) {
size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
- if (pgbrk-(size_t)base < this_max && mmap((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
- munmap(map, map_len);
- return 0;
- }
+ if (pgbrk-(size_t)base < this_max && mmap((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
+ goto error;
}
}
for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
- mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC);
+ if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC) < 0)
+ goto error;
break;
}
if (!runtime) reclaim_gaps(base, (void *)((char *)buf + eh->e_phoff),
@@ -293,6 +290,9 @@ static void *map_library(int fd, size_t *lenp, unsigned char **basep, size_t *dy
*basep = base;
*dynp = dyn;
return map;
+error:
+ munmap(map, map_len);
+ return 0;
}
static int path_open(const char *name, const char *search, char *buf, size_t buf_size)