* [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/
@ 2012-06-24 0:06 Mike Frysinger
0 siblings, 0 replies; 7+ messages in thread
From: Mike Frysinger @ 2012-06-24 0:06 UTC (permalink / raw
To: gentoo-commits
commit: d035e5bb78cb8ac0672f4644854db8a75bc1e2d8
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Sat Jun 23 23:30:10 2012 +0000
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Sun Jun 24 00:02:12 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/sandbox.git;a=commit;h=d035e5bb
libsandbox: do not leak file handles from tracing checks
Make sure we use O_CLOEXEC, and clean things up before forking off a
tracing process.
Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>
---
libsandbox/wrapper-funcs/__wrapper_exec.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/libsandbox/wrapper-funcs/__wrapper_exec.c b/libsandbox/wrapper-funcs/__wrapper_exec.c
index bbdb103..c3536c3 100644
--- a/libsandbox/wrapper-funcs/__wrapper_exec.c
+++ b/libsandbox/wrapper-funcs/__wrapper_exec.c
@@ -26,8 +26,9 @@ static void sb_check_exec(const char *filename, char *const argv[])
int fd;
unsigned char *elf;
struct stat st;
+ bool do_trace = false;
- fd = open(filename, O_RDONLY);
+ fd = open(filename, O_RDONLY|O_CLOEXEC);
if (fd == -1)
return;
if (stat(filename, &st))
@@ -64,8 +65,8 @@ static void sb_check_exec(const char *filename, char *const argv[])
else
PARSE_ELF(64);
- /* We only support tracing of host personality atm */
- trace_main(filename, argv);
+ do_trace = true;
+ /* Now that we're done with stuff, clean up before forking */
done:
@@ -73,6 +74,9 @@ static void sb_check_exec(const char *filename, char *const argv[])
munmap(elf, st.st_size);
out_fd:
close(fd);
+
+ if (do_trace)
+ trace_main(filename, argv);
}
static char **_sb_check_envp(char **envp, bool is_environ)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/
@ 2012-12-24 8:02 Mike Frysinger
0 siblings, 0 replies; 7+ messages in thread
From: Mike Frysinger @ 2012-12-24 8:02 UTC (permalink / raw
To: gentoo-commits
commit: 26ad6af1a4f246bda3cd7a19a24c1767ec9c835e
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Mon Dec 3 06:15:15 2012 +0000
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Mon Dec 24 08:01:36 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/sandbox.git;a=commit;h=26ad6af1
libsandbox: fall back to tracing set*id programs
If we are non-root and run a set*id program, the ldso will ignore our
LD_PRELOAD (rightly so). Unfortunately, this opens up the ability to
run set*id apps that modify things and sandbox cannot catch it.
Instead, force ptracing of these ELFs. While the kernel will disallow
the set*id aspect when running, for the most part, that shouldn't be a
problem if it was already safe.
URL: http://bugs.gentoo.org/442172
Reported-by: Nikoli <nikoli <AT> lavabit.com>
Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>
---
libsandbox/wrapper-funcs/__wrapper_exec.c | 23 ++++++++++++++++++-----
1 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/libsandbox/wrapper-funcs/__wrapper_exec.c b/libsandbox/wrapper-funcs/__wrapper_exec.c
index 0ffc08a..b7c7dfa 100644
--- a/libsandbox/wrapper-funcs/__wrapper_exec.c
+++ b/libsandbox/wrapper-funcs/__wrapper_exec.c
@@ -31,7 +31,7 @@ static void sb_check_exec(const char *filename, char *const argv[])
fd = open(filename, O_RDONLY|O_CLOEXEC);
if (fd == -1)
return;
- if (stat(filename, &st))
+ if (fstat(fd, &st))
goto out_fd;
if (st.st_size < sizeof(Elf64_Ehdr))
goto out_fd;
@@ -47,6 +47,17 @@ static void sb_check_exec(const char *filename, char *const argv[])
elf[EI_CLASS] != ELFCLASS64))
goto out_mmap;
+ /* If we are non-root but attempt to execute a set*id program,
+ * our LD_PRELOAD trick won't work. So skip the static check.
+ * This might break some apps, but it shouldn't, and is better
+ * than doing nothing since it might mean `mount` or `umount`
+ * won't get caught if/when they modify things. #442172
+ *
+ * Only other option is to code a set*id sandbox helper that
+ * gains root just to preload libsandbox.so. That unfortunately
+ * could easily open up people to root vulns.
+ */
+ if (getuid() == 0 || !(st.st_mode & (S_ISUID | S_ISGID))) {
#define PARSE_ELF(n) \
({ \
Elf##n##_Ehdr *ehdr = (void *)elf; \
@@ -60,10 +71,12 @@ static void sb_check_exec(const char *filename, char *const argv[])
if (phdr[p].p_type == PT_INTERP) \
goto done; \
})
- if (elf[EI_CLASS] == ELFCLASS32)
- PARSE_ELF(32);
- else
- PARSE_ELF(64);
+ if (elf[EI_CLASS] == ELFCLASS32)
+ PARSE_ELF(32);
+ else
+ PARSE_ELF(64);
+#undef PARSE_ELF
+ }
do_trace = trace_possible(filename, argv, elf);
/* Now that we're done with stuff, clean up before forking */
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/
@ 2013-02-25 4:03 Mike Frysinger
0 siblings, 0 replies; 7+ messages in thread
From: Mike Frysinger @ 2013-02-25 4:03 UTC (permalink / raw
To: gentoo-commits
commit: 0b8a6d9773cc0e6d86bf1187f46817d5716698fe
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Tue Dec 25 00:41:49 2012 +0000
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Mon Feb 25 04:01:53 2013 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/sandbox.git;a=commit;h=0b8a6d97
libsandbox: reject "" paths with *at funcs before checking the dirfd [missing file]
When it comes to processing errors, an empty path is checked before
an invalid dirfd. Make sure sandbox matches that behavior for the
random testsuites out there that look for this.
Forgot to `git add` in the previous commit :/.
URL: https://bugs.gentoo.org/346929
Reported-by: Marien Zwart <marienz <AT> gentoo.org>
Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>
---
libsandbox/wrapper-funcs/__pre_at_check.c | 34 +++++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/libsandbox/wrapper-funcs/__pre_at_check.c b/libsandbox/wrapper-funcs/__pre_at_check.c
new file mode 100644
index 0000000..f72c40c
--- /dev/null
+++ b/libsandbox/wrapper-funcs/__pre_at_check.c
@@ -0,0 +1,34 @@
+/*
+ * common *at() pre-checks.
+ *
+ * Copyright 1999-2012 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+/* We assume the parent has nested use with save/restore errno */
+bool sb_common_at_pre_check(const char *func, const char **pathname, int dirfd,
+ char *dirfd_path, size_t dirfd_path_len)
+{
+ /* the empty path name should fail with ENOENT before any dirfd
+ * checks get a chance to run #346929
+ */
+ if (*pathname && *pathname[0] == '\0') {
+ errno = ENOENT;
+ sb_debug_dyn("EARLY FAIL: %s(%s): %s\n",
+ func, *pathname, strerror(errno));
+ return false;
+ }
+
+ /* Expand the dirfd path first */
+ switch (resolve_dirfd_path(dirfd, *pathname, dirfd_path, dirfd_path_len)) {
+ case -1:
+ sb_debug_dyn("EARLY FAIL: %s(%s) @ resolve_dirfd_path: %s\n",
+ func, *pathname, strerror(errno));
+ return false;
+ case 0:
+ *pathname = dirfd_path;
+ break;
+ }
+
+ return true;
+}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/
@ 2016-03-30 5:16 Mike Frysinger
0 siblings, 0 replies; 7+ messages in thread
From: Mike Frysinger @ 2016-03-30 5:16 UTC (permalink / raw
To: gentoo-commits
commit: e11815bb7f0656f39e122073e0e3284ec7f5d021
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Wed Mar 30 03:35:44 2016 +0000
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Wed Mar 30 03:35:44 2016 +0000
URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=e11815bb
libsandbox: fix symtab walking with some ELFs
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 <AT> gmx.de>
Signed-off-by: Mike Frysinger <vapier <AT> 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; \
} \
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/
@ 2016-11-16 22:19 Mike Frysinger
0 siblings, 0 replies; 7+ messages in thread
From: Mike Frysinger @ 2016-11-16 22:19 UTC (permalink / raw
To: gentoo-commits
commit: 3ff625739ab2660e7f0adeb99f75ee44c20fef09
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Wed Nov 16 20:59:28 2016 +0000
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Wed Nov 16 20:59:28 2016 +0000
URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=3ff62573
libsandbox: fix symtab walking with prelinked ELFs
When prelink runs on an ELF, it moves the string table from right
after the symbol table to the end, and then replaces the string
table with its liblist table. This ends up breaking sandbox's
assumption that the string table always follows the symbol table
leading to prelinked ELFs crashing.
Update the range check to use the liblist table when available.
Since the prelink code has this logic hardcoded (swapping the
string table for the liblist table), this should be OK for now.
URL: https://bugs.gentoo.org/599894
Reported-by: Anders Larsson <anders.gentoo <AT> larsson.xyz>
Reported-by: Kenton Groombridge <rustyvega <AT> comcast.net>
Reported-by: Marien Zwart <marien.zwart <AT> gmail.com>
Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>
libsandbox/wrapper-funcs/__wrapper_exec.c | 39 ++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 11 deletions(-)
diff --git a/libsandbox/wrapper-funcs/__wrapper_exec.c b/libsandbox/wrapper-funcs/__wrapper_exec.c
index d372366..226c0c0 100644
--- a/libsandbox/wrapper-funcs/__wrapper_exec.c
+++ b/libsandbox/wrapper-funcs/__wrapper_exec.c
@@ -83,8 +83,8 @@ 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, vhash = 0; \
- Elf##n##_Off offset, symoff = 0, stroff = 0, hashoff = 0; \
+ Elf##n##_Addr vaddr, filesz, vsym = 0, vstr = 0, vhash = 0, vliblist = 0; \
+ Elf##n##_Off offset, symoff = 0, stroff = 0, hashoff = 0, liblistoff = 0; \
Elf##n##_Dyn *dyn; \
Elf##n##_Sym *sym, *symend; \
uint##n##_t ent_size = 0, str_size = 0; \
@@ -102,11 +102,12 @@ static bool sb_check_exec(const char *filename, char *const argv[])
dyn = (void *)(elf + phdr[i].p_offset); \
while (dyn->d_tag != DT_NULL) { \
switch (dyn->d_tag) { \
- case DT_SYMTAB: vsym = dyn->d_un.d_val; break; \
- 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; \
+ case DT_SYMTAB: vsym = dyn->d_un.d_val; break; \
+ 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; \
+ case DT_GNU_LIBLIST: vliblist = dyn->d_un.d_val; break; \
} \
++dyn; \
} \
@@ -126,6 +127,8 @@ static bool sb_check_exec(const char *filename, char *const argv[])
stroff = offset + (vstr - vaddr); \
if (vhash >= vaddr && vhash < vaddr + filesz) \
hashoff = offset + (vhash - vaddr); \
+ if (vliblist >= vaddr && vliblist < vaddr + filesz) \
+ liblistoff = offset + (vliblist - vaddr); \
} \
\
/* Finally walk the symbol table. This should generally be fast as \
@@ -133,19 +136,33 @@ static bool sb_check_exec(const char *filename, char *const argv[])
* out there do not export any symbols at all. \
*/ \
if (symoff && stroff) { \
- /* 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: 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. \
+ * make, but glibc has gotten by this long. See determine_info in \
+ * glibc's elf/dl-addr.c. \
+ * \
+ * Turns out prelink will violate that assumption. Fortunately it \
+ * will insert its liblist at the same location all the time -- it \
+ * replaces the string table with its liblist table. \
+ * \
+ * Long term, we should behave the same as glibc and walk the gnu \
+ * hash table first before falling back to the raw symbol table. \
* \
* We don't sanity check the ranges here as you aren't executing \
* corrupt programs in the sandbox. \
*/ \
sym = (void *)(elf + symoff); \
- symend = vhash ? (sym + hashes[1]) : (void *)(elf + stroff); \
+ if (vhash) { \
+ /* Hash entries are always 32-bits. */ \
+ uint32_t *hashes = (void *)(elf + hashoff); \
+ symend = sym + hashes[1]; \
+ } else if (vliblist) \
+ symend = (void *)(elf + liblistoff); \
+ else \
+ symend = (void *)(elf + stroff); \
+ \
while (sym < symend) { \
char *symname = (void *)(elf + stroff + sym->st_name); \
if (ELF##n##_ST_VISIBILITY(sym->st_other) == STV_DEFAULT && \
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/
@ 2019-03-09 19:21 Sergei Trofimovich
0 siblings, 0 replies; 7+ messages in thread
From: Sergei Trofimovich @ 2019-03-09 19:21 UTC (permalink / raw
To: gentoo-commits
commit: c8146cfbcd36f9be4a447bf057811fe2f6c543b2
Author: Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
AuthorDate: Sat Mar 2 19:15:14 2019 +0000
Commit: Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
CommitDate: Sat Mar 2 19:37:11 2019 +0000
URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=c8146cfb
exec wrapper: add support for GNU_HASH parser
In bug #672918 exec's ELF parser was going out of symbol table
range. It happened to trigger on a binary linked by LLVM's lld.
sandbox has no precise way to determine symbol table size and
uses the heuristic of detecting SYMTAB dynamic section size:
STRTAB (or GNU_LIBLIST for prelinked binaries).
This is a weak assumption and does not hold for lld-linked
binaries where the ordering is SYMTAB->GNU_HASH->STRTAB.
As a result sandbox SIGSEGVs when parses GNU_HASH as SYMTAB
entries.
The change adds GNU_HASH parser to iterate exactly through
exported symbols. That way we avoid heuristic code completely.
While at it repobe GNU_LIBLIST hack as we should not rely
on size heuristics anymore.
This has a nice side-effect of speeding up ELF parsing as
GHU_HASH only iterates through exported symbols. HASH
comparison has all dynamic symbols: both exported and
imported.
Reported-by: Dennis Schridde
Bug: https://bugs.gentoo.org/672918
Signed-off-by: Sergei Trofimovich <slyfox <AT> gentoo.org>
libsandbox/wrapper-funcs/__wrapper_exec.c | 108 ++++++++++++++++++++----------
1 file changed, 71 insertions(+), 37 deletions(-)
diff --git a/libsandbox/wrapper-funcs/__wrapper_exec.c b/libsandbox/wrapper-funcs/__wrapper_exec.c
index 974156e..766245a 100644
--- a/libsandbox/wrapper-funcs/__wrapper_exec.c
+++ b/libsandbox/wrapper-funcs/__wrapper_exec.c
@@ -83,8 +83,8 @@ 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, vhash = 0, vliblist = 0; \
- Elf##n##_Off offset, symoff = 0, stroff = 0, hashoff = 0, liblistoff = 0; \
+ Elf##n##_Addr vaddr, filesz, vsym = 0, vstr = 0, vhash = 0, vgnuhash = 0; \
+ Elf##n##_Off offset, symoff = 0, stroff = 0, hashoff = 0, gnuhashoff = 0; \
Elf##n##_Dyn *dyn; \
Elf##n##_Sym *sym, *symend; \
uint##n##_t ent_size = 0, str_size = 0; \
@@ -107,7 +107,7 @@ static bool sb_check_exec(const char *filename, char *const argv[])
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; \
- case DT_GNU_LIBLIST: vliblist = dyn->d_un.d_val; break; \
+ case DT_GNU_HASH: vgnuhash = dyn->d_un.d_val; break; \
} \
++dyn; \
} \
@@ -127,8 +127,8 @@ static bool sb_check_exec(const char *filename, char *const argv[])
stroff = offset + (vstr - vaddr); \
if (vhash >= vaddr && vhash < vaddr + filesz) \
hashoff = offset + (vhash - vaddr); \
- if (vliblist >= vaddr && vliblist < vaddr + filesz) \
- liblistoff = offset + (vliblist - vaddr); \
+ if (vgnuhash >= vaddr && vgnuhash < vaddr + filesz) \
+ gnuhashoff = offset + (vgnuhash - vaddr); \
} \
\
/* Finally walk the symbol table. This should generally be fast as \
@@ -137,47 +137,81 @@ static bool sb_check_exec(const char *filename, char *const argv[])
*/ \
if (symoff && stroff) { \
/* Nowhere is the # of symbols recorded, or the size of the symbol \
- * table. Instead, we do what glibc does: use the sysv hash table \
- * if it exists, else assume that the string table always directly \
+ * table. Instead, we do what glibc does: use the gnu or 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. See determine_info in \
* glibc's elf/dl-addr.c. \
* \
- * Turns out prelink will violate that assumption. Fortunately it \
- * will insert its liblist at the same location all the time -- it \
- * replaces the string table with its liblist table. \
- * \
- * Long term, we should behave the same as glibc and walk the gnu \
- * hash table first before falling back to the raw symbol table. \
- * \
* We don't sanity check the ranges here as you aren't executing \
* corrupt programs in the sandbox. \
*/ \
sym = (void *)(elf + symoff); \
- if (vhash) { \
- /* Hash entries are always 32-bits. */ \
- uint32_t *hashes = (void *)(elf + hashoff); \
- symend = sym + hashes[1]; \
- } else if (vliblist) \
- symend = (void *)(elf + liblistoff); \
- else \
- symend = (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 && \
- sym->st_name && \
- /* Minor optimization to avoid strcmp. */ \
- symname[0] == '_' && symname[1] == '_') { \
- /* Blacklist internal C library symbols. */ \
- for (i = 0; i < ARRAY_SIZE(libc_alloc_syms); ++i) \
- if (!strcmp(symname, libc_alloc_syms[i])) { \
- run_in_process = false; \
- goto use_trace; \
- } \
+ if (vgnuhash) { \
+ uint32_t *hash32 = (void *)(elf + gnuhashoff); \
+ /* use glibc's elf/dl-lookup.c:_dl_setup_hash() as a reference */ \
+ /* DT_GNU_HASH header: */ \
+ uint32_t nbuckets = *hash32++; \
+ uint32_t symbias = *hash32++; \
+ uint32_t bitmask_nwords = *hash32++; \
+ hash32++; /* gnu_shift */ \
+ hash32 += n / 32 * bitmask_nwords; /* gnu_bitmask */ \
+ uint32_t *gnu_buckets = hash32; \
+ hash32 += nbuckets; \
+ uint32_t *gnu_chain_zero = hash32 - symbias; \
+ \
+ uint32_t bucket; \
+ \
+ for (bucket = 0; bucket < nbuckets; bucket++) { \
+ uint32_t symndx = gnu_buckets[bucket]; \
+ if (symndx != 0) { \
+ const uint32_t *hasharr = &gnu_chain_zero[symndx]; \
+ do { \
+ Elf##n##_Sym * s = &sym[symndx]; \
+ \
+ /* keep in sync with 'vhash' case */ \
+ char *symname = (void *)(elf + stroff + s->st_name); \
+ if (ELF##n##_ST_VISIBILITY(s->st_other) == STV_DEFAULT && \
+ s->st_shndx != SHN_UNDEF && s->st_shndx < SHN_LORESERVE && \
+ s->st_name && \
+ /* Minor optimization to avoid strcmp. */ \
+ symname[0] == '_' && symname[1] == '_') { \
+ /* Blacklist internal C library symbols. */ \
+ for (i = 0; i < ARRAY_SIZE(libc_alloc_syms); ++i) \
+ if (!strcmp(symname, libc_alloc_syms[i])) { \
+ run_in_process = false; \
+ goto use_trace; \
+ } \
+ } \
+ ++symndx; \
+ } while ((*hasharr++ & 1u) == 0); \
+ } \
+ } \
+ } else { \
+ if (vhash) { \
+ /* Hash entries are always 32-bits. */ \
+ uint32_t *hashes = (void *)(elf + hashoff); \
+ symend = sym + hashes[1]; \
+ } else \
+ symend = (void *)(elf + stroff); \
+ \
+ while (sym < symend) { \
+ /* keep insync with 'vgnuhash' case */ \
+ 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 && \
+ sym->st_name && \
+ /* Minor optimization to avoid strcmp. */ \
+ symname[0] == '_' && symname[1] == '_') { \
+ /* Blacklist internal C library symbols. */ \
+ for (i = 0; i < ARRAY_SIZE(libc_alloc_syms); ++i) \
+ if (!strcmp(symname, libc_alloc_syms[i])) { \
+ run_in_process = false; \
+ goto use_trace; \
+ } \
+ } \
+ ++sym; \
} \
- ++sym; \
} \
} \
\
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/
@ 2021-10-18 5:21 Mike Frysinger
0 siblings, 0 replies; 7+ messages in thread
From: Mike Frysinger @ 2021-10-18 5:21 UTC (permalink / raw
To: gentoo-commits
commit: 948a4538cee831e7108539d4a427eeef255db3a1
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Sun Oct 17 03:15:49 2021 +0000
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Sun Oct 17 03:15:49 2021 +0000
URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=948a4538
libsandbox: add array bounds to times related funcs
While we don't care about them, the compiler does and warns about
mismatches, so add explicit [2] to them.
Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>
libsandbox/wrapper-funcs/futimesat.c | 2 +-
libsandbox/wrapper-funcs/lutimes.c | 2 +-
libsandbox/wrapper-funcs/utimensat.c | 2 +-
libsandbox/wrapper-funcs/utimes.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libsandbox/wrapper-funcs/futimesat.c b/libsandbox/wrapper-funcs/futimesat.c
index d549e6a..6f6481b 100644
--- a/libsandbox/wrapper-funcs/futimesat.c
+++ b/libsandbox/wrapper-funcs/futimesat.c
@@ -5,7 +5,7 @@
* Licensed under the GPL-2
*/
-#define WRAPPER_ARGS_PROTO int dirfd, const char *filename, const struct timeval times[]
+#define WRAPPER_ARGS_PROTO int dirfd, const char *filename, const struct timeval times[2]
#define WRAPPER_ARGS dirfd, filename, times
#define WRAPPER_SAFE() SB_SAFE_AT(dirfd, filename, 0)
#include "__wrapper_simple.c"
diff --git a/libsandbox/wrapper-funcs/lutimes.c b/libsandbox/wrapper-funcs/lutimes.c
index c608231..3192a33 100644
--- a/libsandbox/wrapper-funcs/lutimes.c
+++ b/libsandbox/wrapper-funcs/lutimes.c
@@ -5,7 +5,7 @@
* Licensed under the GPL-2
*/
-#define WRAPPER_ARGS_PROTO const char *filename, const struct timeval times[]
+#define WRAPPER_ARGS_PROTO const char *filename, const struct timeval times[2]
#define WRAPPER_ARGS filename, times
#define WRAPPER_SAFE() SB_SAFE(filename)
#include "__wrapper_simple.c"
diff --git a/libsandbox/wrapper-funcs/utimensat.c b/libsandbox/wrapper-funcs/utimensat.c
index e0d8ee1..840ff18 100644
--- a/libsandbox/wrapper-funcs/utimensat.c
+++ b/libsandbox/wrapper-funcs/utimensat.c
@@ -5,7 +5,7 @@
* Licensed under the GPL-2
*/
-#define WRAPPER_ARGS_PROTO int dirfd, const char *filename, const struct timespec times[], int flags
+#define WRAPPER_ARGS_PROTO int dirfd, const char *filename, const struct timespec times[2], int flags
#define WRAPPER_ARGS dirfd, filename, times, flags
#define WRAPPER_SAFE() SB_SAFE_AT(dirfd, filename, flags)
#include "__wrapper_simple.c"
diff --git a/libsandbox/wrapper-funcs/utimes.c b/libsandbox/wrapper-funcs/utimes.c
index c361c36..b117895 100644
--- a/libsandbox/wrapper-funcs/utimes.c
+++ b/libsandbox/wrapper-funcs/utimes.c
@@ -5,7 +5,7 @@
* Licensed under the GPL-2
*/
-#define WRAPPER_ARGS_PROTO const char *filename, const struct timeval times[]
+#define WRAPPER_ARGS_PROTO const char *filename, const struct timeval times[2]
#define WRAPPER_ARGS filename, times
#define WRAPPER_SAFE() SB_SAFE(filename)
#include "__wrapper_simple.c"
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-10-18 5:21 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-24 0:06 [gentoo-commits] proj/sandbox:master commit in: libsandbox/wrapper-funcs/ Mike Frysinger
-- strict thread matches above, loose matches on Subject: below --
2012-12-24 8:02 Mike Frysinger
2013-02-25 4:03 Mike Frysinger
2016-03-30 5:16 Mike Frysinger
2016-11-16 22:19 Mike Frysinger
2019-03-09 19:21 Sergei Trofimovich
2021-10-18 5:21 Mike Frysinger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox