diff options
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | libsandbox/Makefile.am | 1 | ||||
-rw-r--r-- | libsandbox/canonicalize.c | 3 | ||||
-rw-r--r-- | libsandbox/eqawarn.c | 49 | ||||
-rw-r--r-- | libsandbox/libsandbox.c | 139 | ||||
-rw-r--r-- | libsandbox/libsandbox.h | 4 | ||||
-rw-r--r-- | libsandbox/memory.c | 6 | ||||
-rw-r--r-- | libsandbox/trace.c | 62 | ||||
-rw-r--r-- | libsandbox/trace/linux/x86_64.c | 2 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/fopen_pre_check.c | 5 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/mkdirat_pre_check.c | 15 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/openat_pre_check.c | 10 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/unlinkat_pre_check.c | 15 | ||||
-rw-r--r-- | libsbutil/Makefile.am | 4 | ||||
-rw-r--r-- | libsbutil/sb_backtrace.c | 15 | ||||
-rw-r--r-- | libsbutil/sb_efuncs.c | 190 | ||||
-rw-r--r-- | libsbutil/sb_memory.c | 37 | ||||
-rw-r--r-- | libsbutil/sb_printf.c | 25 | ||||
-rw-r--r-- | libsbutil/sb_proc.c | 31 | ||||
-rw-r--r-- | libsbutil/sb_write_fd.c | 42 | ||||
-rw-r--r-- | libsbutil/sbutil.h | 39 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/sandbox.c | 17 | ||||
-rw-r--r-- | tests/sb_printf_tst.c | 4 |
24 files changed, 415 insertions, 315 deletions
diff --git a/Makefile.am b/Makefile.am index 40fbcda..e326b23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,3 +30,12 @@ dist-hook: touch "$(distdir)/ChangeLog" ; \ fi ; \ fi + +install-exec-hook: + set -e ; \ + for f in $(bindir)/sandbox $(libdir)/libsandbox.so ; do \ + sed -i.tmp \ + 's:__SANDBOX_TESTING:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:' \ + $(DESTDIR)$$f ; \ + rm -f $(DESTDIR)$$f.tmp ; \ + done diff --git a/libsandbox/Makefile.am b/libsandbox/Makefile.am index 0856aa4..b25e4b3 100644 --- a/libsandbox/Makefile.am +++ b/libsandbox/Makefile.am @@ -24,7 +24,6 @@ libsandbox_la_LDFLAGS = \ -avoid-version \ $(LDFLAG_VER),libsandbox.map libsandbox_la_SOURCES = \ - eqawarn.c \ libsandbox.h \ libsandbox.c \ lock.c \ diff --git a/libsandbox/canonicalize.c b/libsandbox/canonicalize.c index 2bef6b1..6519340 100644 --- a/libsandbox/canonicalize.c +++ b/libsandbox/canonicalize.c @@ -80,8 +80,7 @@ erealpath(const char *name, char *resolved) /* We can't handle resolving a buffer inline, so demand * separate read and write strings. */ - if (name == resolved) - sb_abort(); + sb_assert(name != resolved); rpath = resolved; } rpath_limit = rpath + path_max; diff --git a/libsandbox/eqawarn.c b/libsandbox/eqawarn.c deleted file mode 100644 index e7b0a9c..0000000 --- a/libsandbox/eqawarn.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Dump a QA warning - * - * Copyright 1999-2009 Gentoo Foundation - * Licensed under the GPL-2 - */ - -#include "headers.h" -#include "libsandbox.h" -#include "sbutil.h" -#include "wrappers.h" - -/* First try to use the eqawarn program from portage. If that fails, fall - * back to writing to /dev/tty. While this might annoy some people, using - * stderr will break tests that try to validate output #261957. - */ -void sb_eqawarn(const char *format, ...) -{ - va_list args; - FILE *fp; - sighandler_t oldsig; - bool is_pipe; - - /* If popen() fails, then writes to it will trigger SIGPIPE */ - oldsig = signal(SIGPIPE, SIG_IGN); - - fp = sb_unwrapped_popen("xargs eqawarn 2>/dev/null", "we"); - is_pipe = true; - if (!fp) { - do_tty: - is_pipe = false; - fp = fopen("/dev/tty", "ae"); - if (!fp) - fp = stderr; - } - - sb_fprintf(fp, "QA Notice: "); - va_start(args, format); - sb_vfprintf(fp, format, args); - va_end(args); - - if (is_pipe) { - int status = pclose(fp); - if (WEXITSTATUS(status)) - goto do_tty; - } - - signal(SIGPIPE, oldsig); -} diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c index e0b291a..eac134e 100644 --- a/libsandbox/libsandbox.c +++ b/libsandbox/libsandbox.c @@ -59,9 +59,12 @@ typedef struct { } sbcontext_t; static char *cached_env_vars[MAX_DYN_PREFIXES]; +static char log_path[SB_PATH_MAX]; +static char debug_log_path[SB_PATH_MAX]; bool sandbox_on = true; static bool sb_init = false; int (*sbio_open)(const char *, int, mode_t) = sb_unwrapped_open; +FILE *(*sbio_popen)(const char *, const char *) = sb_unwrapped_popen; static char *resolve_path(const char *, int); static int check_prefixes(char **, int, const char *); @@ -69,6 +72,8 @@ static void clean_env_entries(char ***, int *); static void init_context(sbcontext_t *); static void init_env_entries(char ***, int *, const char *, const char *, int); +const char sbio_fallback_path[] = "/dev/tty"; + #ifdef SB_MEM_DEBUG __attribute__((constructor)) void libsb_init(void) @@ -79,29 +84,6 @@ void libsb_init(void) } #endif -static const char *sb_get_fd_dir(void) -{ -#if defined(SANDBOX_PROC_SELF_FD) - return "/proc/self/fd"; -#elif defined(SANDBOX_DEV_FD) - return "/dev/fd"; -#else -# error "how do i access a proc's fd/ tree ?" -#endif -} - -static const char *sb_get_cmdline(pid_t pid) -{ -#if !defined(SANDBOX_PROC_1_CMDLINE) && !defined(SANDBOX_PROC_SELF_CMDLINE) && !defined(SANDBOX_PROC_dd_CMDLINE) -# error "how do i access a proc's cmdline ?" -#endif - static char path[256]; - if (!pid) - pid = getpid(); - sprintf(path, "/proc/%i/cmdline", pid); - return path; -} - /* resolve_dirfd_path - get the path relative to a dirfd * * return value: @@ -134,9 +116,7 @@ int resolve_dirfd_path(int dirfd, const char *path, char *resolved_path, restore_errno(); return 2; } - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("AT_FD LOOKUP", " fail: %s: %s\n", - resolved_path, strerror(errno)); + sb_debug_dyn("AT_FD LOOKUP fail: %s: %s\n", resolved_path, strerror(errno)); /* If the fd isn't found, some guys (glibc) expect errno */ if (errno == ENOENT) errno = EBADF; @@ -173,8 +153,7 @@ int canonicalize(const char *path, char *resolved_path) /* We can't handle resolving a buffer inline (erealpath), * so demand separate read and write strings. */ - if (path == resolved_path) - sb_abort(); + sb_assert(path != resolved_path); retval = erealpath(path, resolved_path); @@ -382,80 +361,14 @@ char *egetcwd(char *buf, size_t size) return tmpbuf; } -static int sb_copy_file_to_fd(const char *file, int ofd) +void __sb_dump_backtrace(void) { - int ret = -1; - - int ifd = sb_open(file, O_RDONLY|O_CLOEXEC, 0); - if (ifd == -1) - return ret; - - size_t pagesz = getpagesize(); - char *buf = xmalloc(pagesz); - while (1) { - size_t len = sb_read(ifd, buf, pagesz); - if (len == -1) - goto error; - else if (!len) - break; - size_t i; - for (i = 0; i < len; ++i) - if (!buf[i]) - buf[i] = ' '; - if (sb_write(ofd, buf, len) != len) - goto error; - } - - ret = 0; - error: - sb_close(ifd); - free(buf); - return ret; -} - -void sb_dump_backtrace(void) -{ -#ifdef HAVE_BACKTRACE - void *funcs[10]; - int num_funcs; - num_funcs = backtrace(funcs, ARRAY_SIZE(funcs)); - backtrace_symbols_fd(funcs, num_funcs, STDERR_FILENO); -#endif const char *cmdline = sb_get_cmdline(trace_pid); sb_printf("%s: ", cmdline); sb_copy_file_to_fd(cmdline, STDERR_FILENO); sb_printf("\n\n"); } -__attribute__((noreturn)) -void sb_abort(void) -{ - sb_dump_backtrace(); - -#ifndef NDEBUG - if (is_env_on("SANDBOX_GDB")) { - SB_EINFO("\nattempting to autolaunch gdb", " please wait ...\n\n"); - pid_t crashed_pid = getpid(); - switch (fork()) { - case -1: break; - case 0: { - char pid[10]; - snprintf(pid, sizeof(pid), "%i", crashed_pid); - unsetenv(ENV_LD_PRELOAD); - /*sb_unwrapped_*/execlp("gdb", "gdb", "--quiet", "--pid", pid, "-ex", "bt full", NULL); - break; - } - default: { - int status; - wait(&status); - } - } - } -#endif - - abort(); -} - #define _SB_WRITE_STR(str) \ do { \ size_t _len = strlen(str); \ @@ -473,18 +386,16 @@ static bool write_logfile(const char *logfile, const char *func, const char *pat stat_ret = lstat(logfile, &log_stat); /* Do not care about failure */ errno = 0; - if ((0 == stat_ret) && - (0 == S_ISREG(log_stat.st_mode))) { - SB_EERROR("SECURITY BREACH", " '%s' %s\n", logfile, + if (stat_ret == 0 && S_ISREG(log_stat.st_mode) == 0) + sb_ebort("SECURITY BREACH: '%s' %s\n", logfile, "already exists and is not a regular file!"); - sb_abort(); - } logfd = sb_open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (logfd == -1) { - SB_EERROR("ISE:write_logfile ", "unable to append logfile\n"); + sb_eerror("ISE:%s: unable to append logfile: %s\n", + __func__, logfile); goto error; } @@ -920,7 +831,6 @@ static int check_syscall(sbcontext_t *sbcontext, int sb_nr, const char *func, { char *absolute_path = NULL; char *resolved_path = NULL; - char *log_path, *debug_log_path; int old_errno = errno; int result; bool access, debug, verbose; @@ -931,21 +841,21 @@ static int check_syscall(sbcontext_t *sbcontext, int sb_nr, const char *func, goto error; verbose = is_env_on(ENV_SANDBOX_VERBOSE); - log_path = getenv(ENV_SANDBOX_LOG); debug = is_env_on(ENV_SANDBOX_DEBUG); - if (debug) - debug_log_path = getenv(ENV_SANDBOX_DEBUG_LOG); result = check_access(sbcontext, sb_nr, func, flags, absolute_path, resolved_path); if (verbose) { int sym_len = SB_MAX_STRING_LEN + 1 - strlen(func); if (!result && sbcontext->show_access_violation) - SB_EERROR("ACCESS DENIED", " %s:%*s%s\n", func, sym_len, "", absolute_path); + sb_eerror("%sACCESS DENIED%s: %s:%*s%s\n", + COLOR_RED, COLOR_NORMAL, func, sym_len, "", absolute_path); else if (debug && sbcontext->show_access_violation) - SB_EINFO("ACCESS ALLOWED", " %s:%*s%s\n", func, sym_len, "", absolute_path); + sb_einfo("%sACCESS ALLOWED%s: %s:%*s%s\n", + COLOR_GREEN, COLOR_NORMAL, func, sym_len, "", absolute_path); else if (debug && !sbcontext->show_access_violation) - SB_EWARN("ACCESS PREDICTED", " %s:%*s%s\n", func, sym_len, "", absolute_path); + sb_ewarn("%sACCESS PREDICTED%s: %s:%*s%s\n", + COLOR_YELLOW, COLOR_NORMAL, func, sym_len, "", absolute_path); } if ((0 == result) && sbcontext->show_access_violation) @@ -953,13 +863,13 @@ static int check_syscall(sbcontext_t *sbcontext, int sb_nr, const char *func, else access = true; - if (log_path && !access) { + if (!access) { bool worked = write_logfile(log_path, func, file, absolute_path, resolved_path, access); if (!worked && errno) goto error; } - if (debug && debug_log_path) { + if (debug) { bool worked = write_logfile(debug_log_path, func, file, absolute_path, resolved_path, access); if (!worked && errno) goto error; @@ -989,10 +899,8 @@ static int check_syscall(sbcontext_t *sbcontext, int sb_nr, const char *func, return 2; /* If we get here, something bad happened */ - SB_EERROR("ISE ", "%s(%s): %s\n" - "\tabs_path: %s\n" "\tres_path: %s\n", - func, file, strerror(errno), absolute_path, resolved_path); - sb_abort(); + sb_ebort("ISE:\n\tabs_path: %s\n\tres_path: %s\n", + absolute_path, resolved_path); } bool is_sandbox_on(void) @@ -1056,6 +964,9 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in /* Get the path and name to this library */ get_sandbox_lib(sandbox_lib); + get_sandbox_log(log_path); + get_sandbox_debug_log(debug_log_path); + init_context(&sbcontext); sb_init = true; } diff --git a/libsandbox/libsandbox.h b/libsandbox/libsandbox.h index 3177253..38e983d 100644 --- a/libsandbox/libsandbox.h +++ b/libsandbox/libsandbox.h @@ -63,10 +63,6 @@ extern void sb_unlock(void); void trace_main(const char *filename, char *const argv[]); -__printf(1, 2) void sb_eqawarn(const char *format, ...); -void sb_dump_backtrace(void); -__noreturn void sb_abort(void); - /* glibc modified realpath() function */ char *erealpath(const char *, char *); char *egetcwd(char *, size_t); diff --git a/libsandbox/memory.c b/libsandbox/memory.c index bc0400f..5609208 100644 --- a/libsandbox/memory.c +++ b/libsandbox/memory.c @@ -54,11 +54,9 @@ void free(void *ptr) { if (ptr == NULL) return; - if (munmap(SB_MALLOC_TO_MMAP(ptr), SB_MALLOC_TO_SIZE(ptr))) { - SB_EERROR("sandbox memory corruption", " free(%p): %s\n", + if (munmap(SB_MALLOC_TO_MMAP(ptr), SB_MALLOC_TO_SIZE(ptr))) + sb_ebort("sandbox memory corruption with free(%p): %s\n", ptr, strerror(errno)); - sb_dump_backtrace(); - } } /* Hrm, implement a zalloc() ? */ diff --git a/libsandbox/trace.c b/libsandbox/trace.c index 5ccab87..a7b7c02 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -17,9 +17,9 @@ static long _do_ptrace(enum __ptrace_request request, const char *srequest, void #else # define SBDEBUG 0 #endif -#define __SB_DEBUG(fmt, args...) do { if (SBDEBUG) sb_printf(fmt, ## args); } while (0) -#define _SB_DEBUG(fmt, args...) do { if (SBDEBUG) SB_EWARN("TRACE ", "(pid=%i):%s: " fmt, getpid(), __func__, ## args); } while (0) -#define SB_DEBUG(fmt, args...) _SB_DEBUG(fmt "\n", ## args) +#define __sb_debug(fmt, args...) do { if (SBDEBUG) sb_printf(fmt, ## args); } while (0) +#define _sb_debug(fmt, args...) do { if (SBDEBUG) sb_ewarn("TRACE (pid=%i):%s: " fmt, getpid(), __func__, ## args); } while (0) +#define sb_debug(fmt, args...) _sb_debug(fmt "\n", ## args) #include "trace/os.c" @@ -64,9 +64,8 @@ static long _do_ptrace(enum __ptrace_request request, const char *srequest, void request == PTRACE_PEEKUSER) return ret; - SB_EERROR("ISE:_do_ptrace ", "ptrace(%s, ..., %p, %p): %s\n", + sb_ebort("ISE:_do_ptrace: ptrace(%s, ..., %p, %p): %s\n", srequest, addr, data, strerror(errno)); - sb_abort(); } return ret; } @@ -158,7 +157,7 @@ static const char *strsig(int sig) static void trace_child_signal(int signo, siginfo_t *info, void *context) { - SB_DEBUG("got sig %s(%i): code:%s(%i) status:%s(%i)", + sb_debug("got sig %s(%i): code:%s(%i) status:%s(%i)", strsig(signo), signo, strcld_chld(info->si_code), info->si_code, strsig(info->si_status), info->si_status); @@ -169,7 +168,7 @@ static void trace_child_signal(int signo, siginfo_t *info, void *context) trace_exit(128 + info->si_status); case CLD_EXITED: - __SB_DEBUG(" = %i\n", info->si_status); + __sb_debug(" = %i\n", info->si_status); trace_exit(info->si_status); case CLD_TRAPPED: @@ -190,7 +189,7 @@ static void trace_child_signal(int signo, siginfo_t *info, void *context) return; } - SB_EERROR("ISE:trace_child_signal ", "child (%i) signal %s(%i), code %s(%i), status %s(%i)\n", + sb_eerror("ISE:trace_child_signal: child (%i) signal %s(%i), code %s(%i), status %s(%i)\n", trace_pid, strsig(signo), signo, strcld_chld(info->si_code), info->si_code, @@ -221,7 +220,7 @@ struct syscall_state { static bool _trace_check_syscall_C(struct syscall_state *state, int ibase) { char *path = do_peekstr(trace_arg(state->regs, ibase)); - __SB_DEBUG("(\"%s\")", path); + __sb_debug("(\"%s\")", path); bool pre_ret, ret; if (state->pre_check) pre_ret = state->pre_check(state->func, path, AT_FDCWD); @@ -243,7 +242,7 @@ static bool __trace_check_syscall_DCF(struct syscall_state *state, int ibase, in { int dirfd = trace_arg(state->regs, ibase); char *path = do_peekstr(trace_arg(state->regs, ibase + 1)); - __SB_DEBUG("(%i, \"%s\", %x)", dirfd, path, flags); + __sb_debug("(%i, \"%s\", %x)", dirfd, path, flags); bool pre_ret, ret; if (state->pre_check) pre_ret = state->pre_check(state->func, path, dirfd); @@ -340,7 +339,7 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) else if (nr == SB_NR_ACCESS) { char *path = do_peekstr(trace_arg(regs, 1)); int flags = trace_arg(regs, 2); - __SB_DEBUG("(\"%s\", %x)", path, flags); + __sb_debug("(\"%s\", %x)", path, flags); ret = _SB_SAFE_ACCESS(nr, name, path, flags); free(path); return ret; @@ -349,7 +348,7 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) int dirfd = trace_arg(regs, 1); char *path = do_peekstr(trace_arg(regs, 2)); int flags = trace_arg(regs, 3); - __SB_DEBUG("(%i, \"%s\", %x)", dirfd, path, flags); + __sb_debug("(%i, \"%s\", %x)", dirfd, path, flags); ret = _SB_SAFE_ACCESS_AT(nr, name, dirfd, path, flags); free(path); return ret; @@ -357,7 +356,7 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) } else if (nr == SB_NR_OPEN) { char *path = do_peekstr(trace_arg(regs, 1)); int flags = trace_arg(regs, 2); - __SB_DEBUG("(\"%s\", %x)", path, flags); + __sb_debug("(\"%s\", %x)", path, flags); if (sb_openat_pre_check(name, path, AT_FDCWD, flags)) ret = _SB_SAFE_OPEN_INT(nr, name, path, flags); else @@ -369,7 +368,7 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) int dirfd = trace_arg(regs, 1); char *path = do_peekstr(trace_arg(regs, 2)); int flags = trace_arg(regs, 3); - __SB_DEBUG("(%i, \"%s\", %x)", dirfd, path, flags); + __sb_debug("(%i, \"%s\", %x)", dirfd, path, flags); if (sb_openat_pre_check(name, path, dirfd, flags)) ret = _SB_SAFE_OPEN_INT_AT(nr, name, dirfd, path, flags); else @@ -379,7 +378,7 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) } done: - __SB_DEBUG("(...)"); + __sb_debug("(...)"); return ret; } @@ -422,9 +421,9 @@ static void trace_loop(void) se = lookup_syscall_in_tbl(tbl_at_fork, nr); if (!before_syscall || !se || se->sys != SB_NR_EXECVE) { if (before_syscall) - _SB_DEBUG(">%s:%i", se ? se->name : "IDK", nr); + _sb_debug(">%s:%i", se ? se->name : "IDK", nr); else - __SB_DEBUG("(...pre-exec...) = ...\n"); + __sb_debug("(...pre-exec...) = ...\n"); goto loop_again; } ++exec_state; @@ -437,11 +436,9 @@ static void trace_loop(void) se = lookup_syscall(nr); ret = trace_get_regs(®s); if (before_syscall) { - _SB_DEBUG("%s:%i", se ? se->name : "IDK", nr); + _sb_debug("%s:%i", se ? se->name : "IDK", nr); if (!trace_check_syscall(se, ®s)) { - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("trace_loop", " forcing EPERM after %s\n", - se->name); + sb_debug_dyn("trace_loop: forcing EPERM after %s\n", se->name); trace_set_sysnum(®s, -1); fake_syscall_ret = true; } @@ -456,9 +453,9 @@ static void trace_loop(void) } else ret = trace_result(®s, &err); - __SB_DEBUG(" = %li", ret); + __sb_debug(" = %li", ret); if (err) { - __SB_DEBUG(" (errno: %i: %s)", err, strerror(err)); + __sb_debug(" (errno: %i: %s)", err, strerror(err)); /* If the exec() failed for whatever reason, kill the * child and have the parent resume like normal @@ -469,7 +466,7 @@ static void trace_loop(void) return; } } - __SB_DEBUG("\n"); + __sb_debug("\n"); exec_state = 2; } @@ -487,21 +484,16 @@ void trace_main(const char *filename, char *const argv[]) sa.sa_sigaction = trace_child_signal; sigaction(SIGCHLD, &sa, &old_sa); - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("trace_main", " tracing: %s\n", filename); + sb_debug_dyn("trace_main: tracing: %s\n", filename); - if (trace_pid) { - SB_EERROR("ISE:trace_main ", "trace code assumes multiple threads are not forking\n"); - sb_abort(); - } + if (trace_pid) + sb_ebort("ISE: trace code assumes multiple threads are not forking\n"); trace_pid = fork(); if (unlikely(trace_pid == -1)) { - SB_EERROR("ISE:trace_main ", "vfork() failed: %s\n", - strerror(errno)); - sb_abort(); + sb_ebort("ISE: vfork() failed: %s\n", strerror(errno)); } else if (trace_pid) { - SB_DEBUG("parent waiting for child (pid=%i) to signal", trace_pid); + sb_debug("parent waiting for child (pid=%i) to signal", trace_pid); waitpid(trace_pid, NULL, 0); #if defined(PTRACE_SETOPTIONS) && defined(PTRACE_O_TRACESYSGOOD) /* Not all kernel versions support this, so ignore return */ @@ -511,7 +503,7 @@ void trace_main(const char *filename, char *const argv[]) return; } - SB_DEBUG("child setting up ..."); + sb_debug("child setting up ..."); sigaction(SIGCHLD, &old_sa, NULL); do_ptrace(PTRACE_TRACEME, NULL, NULL); kill(getpid(), SIGSTOP); diff --git a/libsandbox/trace/linux/x86_64.c b/libsandbox/trace/linux/x86_64.c index 0110302..8a214f9 100644 --- a/libsandbox/trace/linux/x86_64.c +++ b/libsandbox/trace/linux/x86_64.c @@ -18,7 +18,7 @@ static bool pers_is_32(void) switch (do_peekuser(8 * CS)) { case 0x23: return true; case 0x33: return false; - default: sb_abort(); + default: sb_ebort("unknown x86_64 personality"); } } diff --git a/libsandbox/wrapper-funcs/fopen_pre_check.c b/libsandbox/wrapper-funcs/fopen_pre_check.c index 9ee3b60..765526e 100644 --- a/libsandbox/wrapper-funcs/fopen_pre_check.c +++ b/libsandbox/wrapper-funcs/fopen_pre_check.c @@ -13,9 +13,8 @@ bool sb_fopen_pre_check(const char *func, const char *pathname, const char *mode /* If we're trying to read, fail normally if file does not stat */ struct stat st; if (-1 == stat(pathname, &st)) { - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s): %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s): %s\n", + func, pathname, strerror(errno)); return false; } diff --git a/libsandbox/wrapper-funcs/mkdirat_pre_check.c b/libsandbox/wrapper-funcs/mkdirat_pre_check.c index 4fef14c..77a65df 100644 --- a/libsandbox/wrapper-funcs/mkdirat_pre_check.c +++ b/libsandbox/wrapper-funcs/mkdirat_pre_check.c @@ -15,9 +15,8 @@ bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) /* Expand the dirfd path first */ switch (resolve_dirfd_path(dirfd, pathname, dirfd_path, sizeof(dirfd_path))) { case -1: - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s) @ resolve_dirfd_path: %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s) @ resolve_dirfd_path: %s\n", + func, pathname, strerror(errno)); return false; case 0: pathname = dirfd_path; @@ -28,9 +27,8 @@ bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) if (-1 == canonicalize(pathname, canonic)) /* see comments in check_syscall() */ if (ENAMETOOLONG != errno) { - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s) @ canonicalize: %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s) @ canonicalize: %s\n", + func, pathname, strerror(errno)); return false; } @@ -43,9 +41,8 @@ bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) struct stat st; if (0 == lstat(canonic, &st)) { int new_errno; - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s[%s]) @ lstat: %s\n", - func, pathname, canonic, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s[%s]) @ lstat: %s\n", + func, pathname, canonic, strerror(errno)); new_errno = EEXIST; diff --git a/libsandbox/wrapper-funcs/openat_pre_check.c b/libsandbox/wrapper-funcs/openat_pre_check.c index 23149dc..c827ee6 100644 --- a/libsandbox/wrapper-funcs/openat_pre_check.c +++ b/libsandbox/wrapper-funcs/openat_pre_check.c @@ -19,9 +19,8 @@ bool sb_openat_pre_check(const char *func, const char *pathname, int dirfd, int char dirfd_path[SB_PATH_MAX]; switch (resolve_dirfd_path(dirfd, pathname, dirfd_path, sizeof(dirfd_path))) { case -1: - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s) @ resolve_dirfd_path: %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s) @ resolve_dirfd_path: %s\n", + func, pathname, strerror(errno)); return false; case 0: pathname = dirfd_path; @@ -31,9 +30,8 @@ bool sb_openat_pre_check(const char *func, const char *pathname, int dirfd, int /* Doesn't exist -> skip permission checks */ struct stat st; if (-1 == stat(pathname, &st)) { - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s): %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s): %s\n", + func, pathname, strerror(errno)); return false; } diff --git a/libsandbox/wrapper-funcs/unlinkat_pre_check.c b/libsandbox/wrapper-funcs/unlinkat_pre_check.c index 1c4f7e3..9f5e7d7 100644 --- a/libsandbox/wrapper-funcs/unlinkat_pre_check.c +++ b/libsandbox/wrapper-funcs/unlinkat_pre_check.c @@ -15,9 +15,8 @@ bool sb_unlinkat_pre_check(const char *func, const char *pathname, int dirfd) /* Expand the dirfd path first */ switch (resolve_dirfd_path(dirfd, pathname, dirfd_path, sizeof(dirfd_path))) { case -1: - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s) @ resolve_dirfd_path: %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s) @ resolve_dirfd_path: %s\n", + func, pathname, strerror(errno)); return false; case 0: pathname = dirfd_path; @@ -28,9 +27,8 @@ bool sb_unlinkat_pre_check(const char *func, const char *pathname, int dirfd) if (-1 == canonicalize(pathname, canonic)) /* see comments in check_syscall() */ if (ENAMETOOLONG != errno) { - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s) @ canonicalize: %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s) @ canonicalize: %s\n", + func, pathname, strerror(errno)); return false; } @@ -40,9 +38,8 @@ bool sb_unlinkat_pre_check(const char *func, const char *pathname, int dirfd) 0 == strcmp(canonic, "/dev/zero")) { errno = EACCES; - if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s): %s\n", - func, pathname, strerror(errno)); + sb_debug_dyn("EARLY FAIL: %s(%s): %s\n", + func, pathname, strerror(errno)); return false; } diff --git a/libsbutil/Makefile.am b/libsbutil/Makefile.am index f1feca3..49a7d3b 100644 --- a/libsbutil/Makefile.am +++ b/libsbutil/Makefile.am @@ -20,11 +20,15 @@ libsbutil_la_SOURCES = \ get_tmp_dir.c \ is_env_on.c \ is_env_off.c \ + sb_backtrace.c \ + sb_efuncs.c \ sb_open.c \ sb_read.c \ sb_write.c \ + sb_write_fd.c \ sb_close.c \ sb_printf.c \ + sb_proc.c \ sb_memory.c \ include/rcscripts/rcutil.h \ include/rcscripts/util/str_list.h \ diff --git a/libsbutil/sb_backtrace.c b/libsbutil/sb_backtrace.c new file mode 100644 index 0000000..e3d1ed7 --- /dev/null +++ b/libsbutil/sb_backtrace.c @@ -0,0 +1,15 @@ +/* + * sb_backtrace.c + * + * Need to keep in a dedicated file so libsandbox can override. + * + * Copyright 1999-2012 Gentoo Foundation + * Licensed under the GPL-2 + */ + +#include "headers.h" +#include "sbutil.h" + +void __sb_dump_backtrace(void) +{ +} diff --git a/libsbutil/sb_efuncs.c b/libsbutil/sb_efuncs.c new file mode 100644 index 0000000..248c2bd --- /dev/null +++ b/libsbutil/sb_efuncs.c @@ -0,0 +1,190 @@ +/* + * sb_efuncs.c + * + * Helpers for doing pretty output. + * + * Copyright 1999-2012 Gentoo Foundation + * Licensed under the GPL-2 + */ + +#include "headers.h" +#include "sbutil.h" + +static bool nocolor, init_color = false; +void sb_efunc(const char *color, const char *hilight, const char *format, ...) +{ + save_errno(); + + int fd = STDERR_FILENO; + + if (!init_color) { + nocolor = is_env_on(ENV_NOCOLOR); + init_color = true; + } + + if (!nocolor) + sb_fdprintf(fd, "%s%s%s", color, hilight, COLOR_NORMAL); + else + sb_fdprintf(fd, "%s", hilight); + + va_list args; + va_start(args, format); + sb_vfdprintf(fd, format, args); + va_end(args); + + restore_errno(); +} + +const char *colors[] = { + "\033[0m", + "\033[32;01m", + "\033[33;01m", + "\033[31;01m", +}; +__attribute__((constructor)) +static void sbio_init(void) +{ + if (is_env_on(ENV_NOCOLOR)) + memset(colors, 0, sizeof(colors)); +} + +static bool try_portage_helpers = false; + +/* + * First try to use the helper programs from portage so that it can sanely + * log things itself, and so the output doesn't get consumed by something + * else #278761. If that fails, fall back to writing to /dev/tty. While + * this might annoy some people, using stderr will break tests that try to + * validate output #261957. + */ +static void sb_vefunc(const char *prog, const char *color, const char *format, va_list args) +{ + char shellcode[128]; + FILE *fp; + sighandler_t oldsig; + bool is_pipe = false; + + if (try_portage_helpers) { + /* If popen() fails, then writes to it will trigger SIGPIPE */ + /* XXX: convert this to sigaction */ + oldsig = signal(SIGPIPE, SIG_IGN); + + sprintf(shellcode, "xargs %s 2>/dev/null", prog); + fp = sbio_popen(shellcode, "we"); + is_pipe = true; + } else + fp = NULL; + + if (!fp) { + do_tty: + is_pipe = false; + int fd = sbio_open(sbio_fallback_path, O_WRONLY|O_CLOEXEC, 0); + if (fd >= 0) + fp = fdopen(fd, "ae"); + if (!fp) + fp = stderr; + } + + sb_fprintf(fp, " %s*%s ", color, COLOR_NORMAL); + sb_vfprintf(fp, format, args); + + if (is_pipe) { + int status = pclose(fp); + if (WEXITSTATUS(status)) + goto do_tty; + } else if (fp != stderr) + fclose(fp); + + if (try_portage_helpers) + signal(SIGPIPE, oldsig); +} + +void sb_einfo(const char *format, ...) +{ + va_list args; + va_start(args, format); + sb_vefunc("einfo", COLOR_GREEN, format, args); + va_end(args); +} + +void sb_debug_dyn(const char *format, ...) +{ + if (!is_env_on(ENV_SANDBOX_DEBUG)) + return; + + va_list args; + va_start(args, format); + sb_vefunc("einfo", COLOR_GREEN, format, args); + va_end(args); +} + +void sb_ewarn(const char *format, ...) +{ + va_list args; + va_start(args, format); + sb_vefunc("ewarn", COLOR_YELLOW, format, args); + va_end(args); +} + +void sb_eerror(const char *format, ...) +{ + va_list args; + va_start(args, format); + sb_vefunc("eerror", COLOR_RED, format, args); + va_end(args); +} + +void sb_eqawarn(const char *format, ...) +{ + va_list args; + va_start(args, format); + sb_vefunc("eqawarn", COLOR_YELLOW, format, args); + va_end(args); +} + +void sb_dump_backtrace(void) +{ +#ifdef HAVE_BACKTRACE + void *funcs[10]; + int num_funcs; + num_funcs = backtrace(funcs, ARRAY_SIZE(funcs)); + backtrace_symbols_fd(funcs, num_funcs, STDERR_FILENO); +#endif + __sb_dump_backtrace(); +} + +void __sb_ebort(const char *file, const char *func, size_t line_num, const char *format, ...) +{ + va_list args; + + sb_eerror("%s:%s():%zu: failure (%s):\n", file, func, line_num, strerror(errno)); + + va_start(args, format); + sb_vefunc("eerror", COLOR_RED, format, args); + va_end(args); + + sb_dump_backtrace(); + +#ifndef NDEBUG + if (is_env_on("SANDBOX_GDB")) { + sb_einfo("attempting to autolaunch gdb; please wait ...\n\n"); + pid_t crashed_pid = getpid(); + switch (fork()) { + case -1: break; + case 0: { + char pid[10]; + snprintf(pid, sizeof(pid), "%i", crashed_pid); + unsetenv(ENV_LD_PRELOAD); + /*sb_unwrapped_*/execlp("gdb", "gdb", "--quiet", "--pid", pid, "-ex", "bt full", NULL); + break; + } + default: { + int status; + wait(&status); + } + } + } +#endif + + abort(); +} diff --git a/libsbutil/sb_memory.c b/libsbutil/sb_memory.c index 40a4762..bdc054f 100644 --- a/libsbutil/sb_memory.c +++ b/libsbutil/sb_memory.c @@ -1,5 +1,5 @@ /* - * debug.c + * sb_memory.c * * Simle debugging/logging macro's and functions. * @@ -16,11 +16,8 @@ __xcalloc(size_t nmemb, size_t size, const char *file, const char *func, size_t { void *ret = calloc(nmemb, size); - if (ret == NULL) { - SB_EERROR("calloc()", " %s:%s():%zu: calloc(%zu, %zu) failed: %s\n", - file, func, line, nmemb, size, strerror(errno)); - abort(); - } + if (ret == NULL) + __sb_ebort(file, func, line, "calloc(%zu, %zu)\n", nmemb, size); return ret; } @@ -30,11 +27,8 @@ __xmalloc(size_t size, const char *file, const char *func, size_t line) { void *ret = malloc(size); - if (ret == NULL) { - SB_EERROR("malloc()", " %s:%s():%zu: malloc(%zu) failed: %s\n", - file, func, line, size, strerror(errno)); - abort(); - } + if (ret == NULL) + __sb_ebort(file, func, line, "malloc(%zu)\n", size); return ret; } @@ -50,11 +44,8 @@ __xrealloc(void *ptr, size_t size, const char *file, const char *func, size_t li { void *ret = realloc(ptr, size); - if (ret == NULL) { - SB_EERROR("realloc()", " %s:%s():%zu: realloc(%p, %zu) failed: %s\n", - file, func, line, ptr, size, strerror(errno)); - abort(); - } + if (ret == NULL) + __sb_ebort(file, func, line, "realloc(%p, %zu)\n", ptr, size); return ret; } @@ -64,11 +55,8 @@ __xstrdup(const char *str, const char *file, const char *func, size_t line) { char *ret = strdup(str); - if (ret == NULL) { - SB_EERROR("strdup()", " %s:%s():%zu: strdup(%p) failed: %s\n", - file, func, line, str, strerror(errno)); - abort(); - } + if (ret == NULL) + __sb_ebort(file, func, line, "strdup(%p)\n", str); return ret; } @@ -94,11 +82,8 @@ __xstrndup(const char *str, size_t size, const char *file, const char *func, siz { char *ret = strndup(str, size); - if (ret == NULL) { - SB_EERROR("strndup()", " %s:%s():%zu: strndup(%p, %zu) failed: %s\n", - file, func, line, str, size, strerror(errno)); - abort(); - } + if (ret == NULL) + __sb_ebort(file, func, line, "strndup(%p, %zu)\n", str, size); return ret; } diff --git a/libsbutil/sb_printf.c b/libsbutil/sb_printf.c index d3a27df..1ad9e23 100644 --- a/libsbutil/sb_printf.c +++ b/libsbutil/sb_printf.c @@ -187,28 +187,3 @@ void sb_printf(const char *format, ...) sb_vfdprintf(STDERR_FILENO, format, args); va_end(args); } - -static bool nocolor, init_color = false; -void sb_efunc(const char *color, const char *hilight, const char *format, ...) -{ - save_errno(); - - int fd = STDERR_FILENO; - - if (!init_color) { - nocolor = is_env_on(ENV_NOCOLOR); - init_color = true; - } - - if (!nocolor) - sb_fdprintf(fd, "%s%s%s", color, hilight, COLOR_NORMAL); - else - sb_fdprintf(fd, "%s", hilight); - - va_list args; - va_start(args, format); - sb_vfdprintf(fd, format, args); - va_end(args); - - restore_errno(); -} diff --git a/libsbutil/sb_proc.c b/libsbutil/sb_proc.c new file mode 100644 index 0000000..c583d95 --- /dev/null +++ b/libsbutil/sb_proc.c @@ -0,0 +1,31 @@ +/* + * funcs for poking around /proc + * + * Copyright 1999-2012 Gentoo Foundation + * Licensed under the GPL-2 + */ + +#include "headers.h" +#include "sbutil.h" + +const char sb_fd_dir[] = +#if defined(SANDBOX_PROC_SELF_FD) + "/proc/self/fd" +#elif defined(SANDBOX_DEV_FD) + "/dev/fd" +#else +# error "how do i access a proc's fd/ tree ?" +#endif +; + +const char *sb_get_cmdline(pid_t pid) +{ +#if !defined(SANDBOX_PROC_1_CMDLINE) && !defined(SANDBOX_PROC_SELF_CMDLINE) && !defined(SANDBOX_PROC_dd_CMDLINE) +# error "how do i access a proc's cmdline ?" +#endif + static char path[256]; + if (!pid) + pid = getpid(); + sprintf(path, "/proc/%i/cmdline", pid); + return path; +} diff --git a/libsbutil/sb_write_fd.c b/libsbutil/sb_write_fd.c new file mode 100644 index 0000000..f19d7de --- /dev/null +++ b/libsbutil/sb_write_fd.c @@ -0,0 +1,42 @@ +/* + * helper for sucking up a file and writing it to a fd. + * good for copying the contents of small status files + * into a log file. + * + * Copyright 1999-2012 Gentoo Foundation + * Licensed under the GPL-2 + */ + +#include "headers.h" +#include "sbutil.h" + +int sb_copy_file_to_fd(const char *file, int ofd) +{ + int ret = -1; + + int ifd = sb_open(file, O_RDONLY|O_CLOEXEC, 0); + if (ifd == -1) + return ret; + + size_t pagesz = getpagesize(); + char *buf = xmalloc(pagesz); + while (1) { + size_t len = sb_read(ifd, buf, pagesz); + if (len == -1) + goto error; + else if (!len) + break; + size_t i; + for (i = 0; i < len; ++i) + if (!buf[i]) + buf[i] = ' '; + if (sb_write(ofd, buf, len) != len) + goto error; + } + + ret = 0; + error: + sb_close(ifd); + free(buf); + return ret; +} diff --git a/libsbutil/sbutil.h b/libsbutil/sbutil.h index f45402e..f275514 100644 --- a/libsbutil/sbutil.h +++ b/libsbutil/sbutil.h @@ -42,8 +42,7 @@ #define ENV_SANDBOX_VERBOSE "SANDBOX_VERBOSE" #define ENV_SANDBOX_DEBUG "SANDBOX_DEBUG" -extern const char env_sandbox_testing[]; -#define ENV_SANDBOX_TESTING env_sandbox_testing +#define ENV_SANDBOX_TESTING "__SANDBOX_TESTING" #define ENV_SANDBOX_LIB "SANDBOX_LIB" #define ENV_SANDBOX_BASHRC "SANDBOX_BASHRC" @@ -67,15 +66,11 @@ extern const char env_sandbox_testing[]; #define SB_BUF_LEN 2048 -#define COLOR_NORMAL "\033[0m" -#define COLOR_GREEN "\033[32;01m" -#define COLOR_YELLOW "\033[33;01m" -#define COLOR_RED "\033[31;01m" - -/* Gentoo style e* printing macro's */ -#define SB_EINFO(_hilight, _args...) sb_efunc(COLOR_GREEN, _hilight, _args) -#define SB_EWARN(_hilight, _args...) sb_efunc(COLOR_YELLOW, _hilight, _args) -#define SB_EERROR(_hilight, _args...) sb_efunc(COLOR_RED, _hilight, _args) +extern const char *colors[]; +#define COLOR_NORMAL colors[0] +#define COLOR_GREEN colors[1] +#define COLOR_YELLOW colors[2] +#define COLOR_RED colors[3] char *get_sandbox_conf(void); char *get_sandbox_confd(char *path); @@ -87,19 +82,41 @@ int get_tmp_dir(char *path); bool is_env_on (const char *); bool is_env_off (const char *); +/* proc helpers */ +extern const char sb_fd_dir[]; +#define sb_get_fd_dir() sb_fd_dir +const char *sb_get_cmdline(pid_t pid); + /* libsandbox need to use a wrapper for open */ attribute_hidden extern int (*sbio_open)(const char *, int, mode_t); +attribute_hidden extern FILE *(*sbio_popen)(const char *, const char *); +extern const char sbio_fallback_path[]; /* Convenience functions to reliably open, read and write to a file */ int sb_open(const char *path, int flags, mode_t mode); size_t sb_read(int fd, void *buf, size_t count); size_t sb_write(int fd, const void *buf, size_t count); int sb_close(int fd); +int sb_copy_file_to_fd(const char *file, int ofd); /* Reliable output */ __printf(1, 2) void sb_printf(const char *format, ...); __printf(2, 3) void sb_fdprintf(int fd, const char *format, ...); __printf(2, 0) void sb_vfdprintf(int fd, const char *format, va_list args); __printf(3, 4) void sb_efunc(const char *color, const char *hilight, const char *format, ...); +__printf(1, 2) void sb_einfo(const char *format, ...); +__printf(1, 2) void sb_ewarn(const char *format, ...); +__printf(1, 2) void sb_eerror(const char *format, ...); +__printf(1, 2) void sb_eqawarn(const char *format, ...); +__printf(1, 2) void sb_debug_dyn(const char *format, ...); +__printf(4, 5) void __sb_ebort(const char *file, const char *func, size_t line_num, const char *format, ...) __noreturn; +#define sb_ebort(format, ...) __sb_ebort(__FILE__, __func__, __LINE__, format, ## __VA_ARGS__) +void sb_dump_backtrace(void); +void __sb_dump_backtrace(void); +#define sb_assert(cond) \ + do { \ + if (!(cond)) \ + sb_ebort("assertion failure !(%s)\n", #cond); \ + } while (0) #define sb_fprintf(fp, ...) sb_fdprintf(fileno(fp), __VA_ARGS__) #define sb_vfprintf(fp, ...) sb_vfdprintf(fileno(fp), __VA_ARGS__) diff --git a/src/Makefile.am b/src/Makefile.am index 3e7e31c..c3c1f45 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,9 +13,3 @@ sandbox_SOURCES = \ environ.c \ sandbox.h \ sandbox.c - -install-exec-hook: - sed -i.tmp \ - 's:__SANDBOX_TESTING:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:' \ - $(DESTDIR)$(bindir)/sandbox - rm -f $(DESTDIR)$(bindir)/sandbox.tmp diff --git a/src/sandbox.c b/src/sandbox.c index 69ab18e..54fbb98 100644 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -19,14 +19,14 @@ static int print_debug = 0; #define dprintf(fmt, args...) do { if (print_debug) printf(fmt, ## args); } while (0) #define dputs(str) do { if (print_debug) puts(str); } while (0) int (*sbio_open)(const char *, int, mode_t) = (void *)open; +FILE *(*sbio_popen)(const char *, const char *) = popen; volatile static int stop_called = 0; volatile static pid_t child_pid = 0; static const char sandbox_banner[] = "============================= Gentoo path sandbox =============================="; static const char sandbox_footer[] = "--------------------------------------------------------------------------------"; - -const char env_sandbox_testing[] = "__SANDBOX_TESTING"; +const char sbio_fallback_path[] = "/dev/stderr"; static int setup_sandbox(struct sandbox_info_t *sandbox_info, bool interactive) { @@ -87,7 +87,7 @@ static void print_sandbox_log(char *sandbox_log) { int sandbox_log_file; size_t len; - char buffer[1024]; + char buffer[8192]; sandbox_log_file = sb_open(sandbox_log, O_RDONLY, 0); if (-1 == sandbox_log_file) { @@ -95,8 +95,8 @@ static void print_sandbox_log(char *sandbox_log) return; } - SB_EERROR("--------------------------- ACCESS VIOLATION SUMMARY ---------------------------", "\n"); - SB_EERROR("LOG FILE", " \"%s\"\n\n", sandbox_log); + sb_eerror("--------------------------- ACCESS VIOLATION SUMMARY ---------------------------\n"); + sb_eerror("LOG FILE: \"%s\"\n", sandbox_log); while (1) { len = sb_read(sandbox_log_file, buffer, sizeof(buffer)); @@ -105,14 +105,11 @@ static void print_sandbox_log(char *sandbox_log) break; } else if (!len) break; - if (sb_write(STDERR_FILENO, buffer, len) != len) { - sb_pwarn("sb_write(logfile) failed"); - break; - } + sb_eerror("\n%s", buffer); } sb_close(sandbox_log_file); - SB_EERROR("--------------------------------------------------------------------------------", "\n"); + sb_eerror("--------------------------------------------------------------------------------\n"); } static void stop(int signum) diff --git a/tests/sb_printf_tst.c b/tests/sb_printf_tst.c index 443c2c2..1db7c33 100644 --- a/tests/sb_printf_tst.c +++ b/tests/sb_printf_tst.c @@ -8,6 +8,10 @@ _T(sb_printf, fmt, ## args); \ } while (0) +int (*sbio_open)(const char *, int, mode_t) = (void *)open; +FILE *(*sbio_popen)(const char *, const char *) = popen; +const char sbio_fallback_path[] = "/dev/stderr"; + int main(int argc, char *argv[]) { /* sandbox outputs to stderr, so unify it */ |