summaryrefslogtreecommitdiff
path: root/ldso/dynlink.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-06-28 12:20:58 -0400
committerRich Felker <dalias@aerifal.cx>2018-06-28 12:27:01 -0400
commit193338e619de7c993efa2c0e1a87240bd732c181 (patch)
tree1ecbb218d7c513cb41f3a0174762d8adb07e55b8 /ldso/dynlink.c
parentf6870d6b4f32c99fdbf4367422820218b2f638bb (diff)
downloadmusl-193338e619de7c993efa2c0e1a87240bd732c181.tar.gz
avoid spurious dso matches by dladdr outside bounds of load segments
since slack space at the beginning and/or end of writable load maps is donated to malloc, the application could obtain valid pointers in these ranges which dladdr would erroneously identify as part of the shared object whose mapping they came from. instead of checking the queried address against the mapping base and length, check it against the load segments from the program headers, and only match the dso if it lies within the bounds of one of them. as a shortcut, if the address does match the range of the mapping but not any of the load segments, we know it cannot match any other dso and can immediately return failure.
Diffstat (limited to 'ldso/dynlink.c')
-rw-r--r--ldso/dynlink.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index a773b782..41534e90 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1878,8 +1878,17 @@ static void *addr2dso(size_t a)
return p;
}
} else {
+ Phdr *ph = p->phdr;
+ size_t phcnt = p->phnum;
+ size_t entsz = p->phentsize;
+ size_t base = (size_t)p->base;
+ for (; phcnt--; ph=(void *)((char *)ph+entsz)) {
+ if (ph->p_type != PT_LOAD) continue;
+ if (a-base-ph->p_vaddr < ph->p_memsz)
+ return p;
+ }
if (a-(size_t)p->map < p->map_len)
- return p;
+ return 0;
}
}
return 0;