From 25a00ab9758e784dd78d6a2e8a5ee6978fc0ae1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vivek=20Das=C2=A0Mohapatra?= <vivek@collabora.co.uk> Date: Wed, 24 May 2017 20:32:28 +0100 Subject: [PATCH] capsule-dlmopen.c: don't fake dynamic section size from wrap() When munging the ELF data structures from the capsule-export code path via dl_iterate_phdr, we get the dynamic section size as a callback arg so we can double-check we haven't ended up outside the memory region we expect to be working on. Unfortunately when using link_map traversal to do the same sort of thing to install wrapper functions inside the capsule we don't have this information. We were using SIZE_MAX on ELFCLASS64 to pass a "big enough" size parameter but this calculation does not work on ELFCLASS32. Rather than go out of our way to produce a bogus-but-big-enough value we now pass 0 for the size and have the called functions know that they can't do the double-check if passed a size of 0. The last entry in the dyn section should have a D_TAG of DT_NULL anyway so we'll only crash off the end of the dynamic section if the linker is broken or malicious (which is probably not worth defending against, all things considered). --- capsule/capsule-dlmopen.c | 3 +-- utils/process-pt-dynamic.c | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/capsule/capsule-dlmopen.c b/capsule/capsule-dlmopen.c index e800ae13a..97c77973b 100644 --- a/capsule/capsule-dlmopen.c +++ b/capsule/capsule-dlmopen.c @@ -1326,7 +1326,6 @@ wrap (const char *name, // // the utility functions expect an upper bound though so set that to // something suitably large: - size_t size = SIZE_MAX - base - (ElfW(Addr)) dyn; relocation_data_t rdata = { 0 }; rdata.target = name; @@ -1361,7 +1360,7 @@ wrap (const char *name, // install any required wrappers inside the capsule: process_pt_dynamic( (void *)start, // offset from phdr to dyn section - size, // fake size value (max possible value) + 0, // fake size value base, // address of phdr in memory process_dt_rela, process_dt_rel, diff --git a/utils/process-pt-dynamic.c b/utils/process-pt-dynamic.c index 0e0d31334..c84280848 100644 --- a/utils/process-pt-dynamic.c +++ b/utils/process-pt-dynamic.c @@ -84,7 +84,8 @@ find_strtab (ElfW(Addr) base, void *start, size_t size, int *siz) const char *tab = NULL; for( entry = start + base; - (entry->d_tag != DT_NULL) && ((void *)entry < (start + base + size)); + (entry->d_tag != DT_NULL) && + ((size == 0) || ((void *)entry < (start + base + size))); entry++ ) { if( entry->d_tag == DT_STRTAB ) @@ -474,7 +475,8 @@ process_pt_dynamic (void *start, "strtab is at %p: %s%s", strtab, strtab, strtab ? "…" : ""); for( entry = start + base; - (entry->d_tag != DT_NULL) && ((void *)entry < (start + base + size)); + (entry->d_tag != DT_NULL) && + ((size == 0) || ((void *)entry < (start + base + size))); entry++ ) switch( entry->d_tag ) { -- GitLab