aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2012-06-22 14:19:14 -0700
committerMike Frysinger <vapier@gentoo.org>2012-06-23 18:02:43 -0400
commit40abb498ca4a24495fe34e133379382ce8c3eaca (patch)
treea8779b17558a4c96eb2d5c56e82cee4743d408aa
parentuse m4_flatten to make multiline lists easier to handle (diff)
downloadsandbox-40abb498ca4a24495fe34e133379382ce8c3eaca.tar.gz
sandbox-40abb498ca4a24495fe34e133379382ce8c3eaca.tar.bz2
sandbox-40abb498ca4a24495fe34e133379382ce8c3eaca.zip
significantly overhaul output helpers
There are a few major points we want to hit here: - have all output from libsandbox go through portage helpers when we are in the portage environment so that output is properly logged - convert SB_E{info,warn,error} to sb_e{info,warn,error} to match style of other functions and cut down on confusion - move all abort/output helpers to libsbutil so it can be used in all source trees and not just by libsandbox - migrate all abort points to the centralized sb_ebort helper Unfortunately, it's not terribly easy to untangle these into separate patches, but hopefully this shouldn't be too messy as much of it is mechanical: move funcs between files, and change the name of funcs that get called. URL: http://bugs.gentoo.org/278761 Reported-by: Mounir Lamouri <volkmar@gentoo.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--Makefile.am9
-rw-r--r--libsandbox/Makefile.am1
-rw-r--r--libsandbox/canonicalize.c3
-rw-r--r--libsandbox/eqawarn.c49
-rw-r--r--libsandbox/libsandbox.c139
-rw-r--r--libsandbox/libsandbox.h4
-rw-r--r--libsandbox/memory.c6
-rw-r--r--libsandbox/trace.c62
-rw-r--r--libsandbox/trace/linux/x86_64.c2
-rw-r--r--libsandbox/wrapper-funcs/fopen_pre_check.c5
-rw-r--r--libsandbox/wrapper-funcs/mkdirat_pre_check.c15
-rw-r--r--libsandbox/wrapper-funcs/openat_pre_check.c10
-rw-r--r--libsandbox/wrapper-funcs/unlinkat_pre_check.c15
-rw-r--r--libsbutil/Makefile.am4
-rw-r--r--libsbutil/sb_backtrace.c15
-rw-r--r--libsbutil/sb_efuncs.c190
-rw-r--r--libsbutil/sb_memory.c37
-rw-r--r--libsbutil/sb_printf.c25
-rw-r--r--libsbutil/sb_proc.c31
-rw-r--r--libsbutil/sb_write_fd.c42
-rw-r--r--libsbutil/sbutil.h39
-rw-r--r--src/Makefile.am6
-rw-r--r--src/sandbox.c17
-rw-r--r--tests/sb_printf_tst.c4
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(&regs);
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, &regs)) {
- 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(&regs, -1);
fake_syscall_ret = true;
}
@@ -456,9 +453,9 @@ static void trace_loop(void)
} else
ret = trace_result(&regs, &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 */