diff options
author | Mike Frysinger <vapier@gentoo.org> | 2016-03-29 23:44:29 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2016-03-29 23:46:35 -0400 |
commit | cb51c818a0d2b2f1a64e084411ac5717ebb3ef38 (patch) | |
tree | b4d384b99d690da3be15ad44ad9137b0cd7eae5f | |
parent | sys-libs/newlib: version bump to 2.4.0 (diff) | |
download | gentoo-cb51c818a0d2b2f1a64e084411ac5717ebb3ef38.tar.gz gentoo-cb51c818a0d2b2f1a64e084411ac5717ebb3ef38.tar.bz2 gentoo-cb51c818a0d2b2f1a64e084411ac5717ebb3ef38.zip |
sys-apps/sandbox: fix crashes w/some ELFs #578524
-rw-r--r-- | sys-apps/sandbox/files/sandbox-2.11-exec-hash.patch | 96 | ||||
-rw-r--r-- | sys-apps/sandbox/sandbox-2.11-r1.ebuild (renamed from sys-apps/sandbox/sandbox-2.11.ebuild) | 1 |
2 files changed, 97 insertions, 0 deletions
diff --git a/sys-apps/sandbox/files/sandbox-2.11-exec-hash.patch b/sys-apps/sandbox/files/sandbox-2.11-exec-hash.patch new file mode 100644 index 000000000000..8a4cd9b0b9b7 --- /dev/null +++ b/sys-apps/sandbox/files/sandbox-2.11-exec-hash.patch @@ -0,0 +1,96 @@ +From e11815bb7f0656f39e122073e0e3284ec7f5d021 Mon Sep 17 00:00:00 2001 +From: Mike Frysinger <vapier@gentoo.org> +Date: Tue, 29 Mar 2016 23:35:44 -0400 +Subject: [PATCH] libsandbox: fix symtab walking with some ELFs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The strtab assumption works if there is no SysV hash table. +Add logic to handle that scenario. + +URL: https://bugs.gentoo.org/578524 +Reported-by: Toralf Förster <toralf.foerster@gmx.de> +Signed-off-by: Mike Frysinger <vapier@gentoo.org> +--- + libsandbox/wrapper-funcs/__wrapper_exec.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/libsandbox/wrapper-funcs/__wrapper_exec.c b/libsandbox/wrapper-funcs/__wrapper_exec.c +index f7f51ab..d372366 100644 +--- a/libsandbox/wrapper-funcs/__wrapper_exec.c ++++ b/libsandbox/wrapper-funcs/__wrapper_exec.c +@@ -83,10 +83,10 @@ static bool sb_check_exec(const char *filename, char *const argv[]) + ({ \ + Elf##n##_Ehdr *ehdr = (void *)elf; \ + Elf##n##_Phdr *phdr = (void *)(elf + ehdr->e_phoff); \ +- Elf##n##_Addr vaddr, filesz, vsym = 0, vstr = 0; \ +- Elf##n##_Off offset, symoff = 0, stroff = 0; \ ++ Elf##n##_Addr vaddr, filesz, vsym = 0, vstr = 0, vhash = 0; \ ++ Elf##n##_Off offset, symoff = 0, stroff = 0, hashoff = 0; \ + Elf##n##_Dyn *dyn; \ +- Elf##n##_Sym *sym; \ ++ Elf##n##_Sym *sym, *symend; \ + uint##n##_t ent_size = 0, str_size = 0; \ + bool dynamic = false; \ + size_t i; \ +@@ -106,6 +106,7 @@ static bool sb_check_exec(const char *filename, char *const argv[]) + case DT_SYMENT: ent_size = dyn->d_un.d_val; break; \ + case DT_STRTAB: vstr = dyn->d_un.d_val; break; \ + case DT_STRSZ: str_size = dyn->d_un.d_val; break; \ ++ case DT_HASH: vhash = dyn->d_un.d_val; break; \ + } \ + ++dyn; \ + } \ +@@ -123,6 +124,8 @@ static bool sb_check_exec(const char *filename, char *const argv[]) + symoff = offset + (vsym - vaddr); \ + if (vstr >= vaddr && vstr < vaddr + filesz) \ + stroff = offset + (vstr - vaddr); \ ++ if (vhash >= vaddr && vhash < vaddr + filesz) \ ++ hashoff = offset + (vhash - vaddr); \ + } \ + \ + /* Finally walk the symbol table. This should generally be fast as \ +@@ -130,18 +133,20 @@ static bool sb_check_exec(const char *filename, char *const argv[]) + * out there do not export any symbols at all. \ + */ \ + if (symoff && stroff) { \ +- sym = (void *)(elf + symoff); \ ++ /* Hash entries are always 32-bits. */ \ ++ uint32_t *hashes = (void *)(elf + hashoff); \ + /* Nowhere is the # of symbols recorded, or the size of the symbol \ +- * table. Instead, we do what glibc does: assume that the string \ +- * table always follows the symbol table. This seems like a poor \ +- * assumption to make, but glibc has gotten by this long. We could \ +- * rely on DT_HASH and walking all the buckets to find the largest \ +- * symbol index, but that's also a bit hacky. \ ++ * table. Instead, we do what glibc does: use the sysv hash table \ ++ * if it exists, else assume that the string table always directly \ ++ * follows the symbol table. This seems like a poor assumption to \ ++ * make, but glibc has gotten by this long. \ + * \ + * We don't sanity check the ranges here as you aren't executing \ + * corrupt programs in the sandbox. \ + */ \ +- for (i = 0; i < (vstr - vsym) / ent_size; ++i) { \ ++ sym = (void *)(elf + symoff); \ ++ symend = vhash ? (sym + hashes[1]) : (void *)(elf + stroff); \ ++ while (sym < symend) { \ + char *symname = (void *)(elf + stroff + sym->st_name); \ + if (ELF##n##_ST_VISIBILITY(sym->st_other) == STV_DEFAULT && \ + sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE && \ +@@ -149,9 +154,8 @@ static bool sb_check_exec(const char *filename, char *const argv[]) + /* Minor optimization to avoid strcmp. */ \ + symname[0] == '_' && symname[1] == '_') { \ + /* Blacklist internal C library symbols. */ \ +- size_t j; \ +- for (j = 0; j < ARRAY_SIZE(libc_alloc_syms); ++j) \ +- if (!strcmp(symname, libc_alloc_syms[j])) { \ ++ for (i = 0; i < ARRAY_SIZE(libc_alloc_syms); ++i) \ ++ if (!strcmp(symname, libc_alloc_syms[i])) { \ + run_in_process = false; \ + goto use_trace; \ + } \ +-- +2.7.4 + diff --git a/sys-apps/sandbox/sandbox-2.11.ebuild b/sys-apps/sandbox/sandbox-2.11-r1.ebuild index 0bbf588cd3df..80013163c5f7 100644 --- a/sys-apps/sandbox/sandbox-2.11.ebuild +++ b/sys-apps/sandbox/sandbox-2.11-r1.ebuild @@ -32,6 +32,7 @@ sandbox_death_notice() { } src_prepare() { + epatch "${FILESDIR}"/${P}-exec-hash.patch #578524 epatch_user } |