aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2013-02-22 21:18:07 -0500
committerMike Frysinger <vapier@gentoo.org>2013-02-24 23:15:44 -0500
commite12fee192ac8b0343a468e5a8f7811a7b029ff9a (patch)
tree252b2e528a3fb99f5cc32127a32ad4d785008a6f
parentlibsandbox: handle ENOSYS w/process_vm_readv (diff)
downloadsandbox-e12fee192ac8b0343a468e5a8f7811a7b029ff9a.tar.gz
sandbox-e12fee192ac8b0343a468e5a8f7811a7b029ff9a.tar.bz2
sandbox-e12fee192ac8b0343a468e5a8f7811a7b029ff9a.zip
add a new message env var
This is used whenever sandbox wants to display an informational message. For example, early notification of a path violation, or debugging output. We can't just pop open an fd and pass that around as apps consider that leakage and will often break assumptions in terms of free fds. Or apps that start up and cleanse all of their open fds. So instead, we just pass around an env var that holds the full path to the file we want will write to. Since these messages are infrequent (compared to overall runtime), opening/writing/closing the path every time is fine. This also avoids all the problems associated with using external portage helpers for writing messages. A follow up commit will take care of the situation where apps (such as scons) attempt to also cleanse the env before forking. URL: http://bugs.gentoo.org/278761 URL: http://bugs.gentoo.org/431638 Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--libsandbox/libsandbox.c4
-rw-r--r--libsbutil/get_sandbox_log.c5
-rw-r--r--libsbutil/sb_efuncs.c66
-rw-r--r--libsbutil/sbutil.h3
-rw-r--r--src/environ.c5
-rw-r--r--src/sandbox.c13
-rw-r--r--src/sandbox.h1
-rw-r--r--tests/sb_printf_tst.c1
8 files changed, 47 insertions, 51 deletions
diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c
index eaa5c7d..0ec5fe1 100644
--- a/libsandbox/libsandbox.c
+++ b/libsandbox/libsandbox.c
@@ -47,6 +47,7 @@ typedef struct {
static char *cached_env_vars[MAX_DYN_PREFIXES];
static char log_path[SB_PATH_MAX];
static char debug_log_path[SB_PATH_MAX];
+static char message_path[SB_PATH_MAX];
bool sandbox_on = true;
static bool sb_init = false;
int (*sbio_open)(const char *, int, mode_t) = sb_unwrapped_open;
@@ -58,6 +59,7 @@ 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_message_path;
const char sbio_fallback_path[] = "/dev/tty";
/* resolve_dirfd_path - get the path relative to a dirfd
@@ -940,6 +942,8 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in
get_sandbox_log(log_path, NULL);
get_sandbox_debug_log(debug_log_path, NULL);
+ get_sandbox_message_path(message_path);
+ sbio_message_path = message_path;
init_context(&sbcontext);
sb_init = true;
diff --git a/libsbutil/get_sandbox_log.c b/libsbutil/get_sandbox_log.c
index 947566a..a79b399 100644
--- a/libsbutil/get_sandbox_log.c
+++ b/libsbutil/get_sandbox_log.c
@@ -58,3 +58,8 @@ void get_sandbox_debug_log(char *path, const char *tmpdir)
{
_get_sb_log(path, tmpdir, ENV_SANDBOX_DEBUG_LOG, DEBUG_LOG_FILE_PREFIX);
}
+
+void get_sandbox_message_path(char *path)
+{
+ _get_sb_log(path, NULL, ENV_SANDBOX_MESSAGE_PATH, DEBUG_LOG_FILE_PREFIX);
+}
diff --git a/libsbutil/sb_efuncs.c b/libsbutil/sb_efuncs.c
index 484e8a0..80064c6 100644
--- a/libsbutil/sb_efuncs.c
+++ b/libsbutil/sb_efuncs.c
@@ -26,65 +26,33 @@ static void sbio_init(void)
}
}
-static bool try_portage_helpers = true;
-
/*
- * 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.
+ * First try to write to the known good message log location (which is
+ * normally tied to the initial sandbox's stderr). 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
+ * Other related bugs on the topic: #278761
*/
static void sb_vefunc(const char *prog, const char *color, const char *format, va_list args)
{
- char shellcode[128];
+ int fd;
FILE *fp;
- struct sigaction sa, old_sa;
- bool is_pipe = false;
- va_list retry_args;
-
- if (try_portage_helpers) {
- /* If popen() fails, then writes to it will trigger SIGPIPE */
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = SIG_IGN;
- sigaction(SIGCHLD, &sa, &old_sa);
-
- sprintf(shellcode, "xargs %s 2>/dev/null", prog);
- fp = sbio_popen(shellcode, "we");
- is_pipe = true;
- va_copy(retry_args, args);
- } 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;
- }
+
+ if (likely(sbio_message_path))
+ fd = sbio_open(sbio_message_path, O_WRONLY|O_APPEND|O_CLOEXEC, 0);
+ else
+ fd = -1;
+ if (fd == -1)
+ sbio_open(sbio_fallback_path, O_WRONLY|O_CLOEXEC, 0);
+ fp = fd == -1 ? NULL : 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)) {
- args = retry_args;
- goto do_tty;
- }
- } else if (fp != stderr)
+ if (fp != stderr)
fclose(fp);
-
- if (try_portage_helpers) {
- sigaction(SIGCHLD, &old_sa, NULL);
- va_end(retry_args);
- if (!is_pipe)
- /* If we failed once, we'll fail again */
- try_portage_helpers = false;
- }
}
void sb_einfo(const char *format, ...)
diff --git a/libsbutil/sbutil.h b/libsbutil/sbutil.h
index 90de815..993d7ad 100644
--- a/libsbutil/sbutil.h
+++ b/libsbutil/sbutil.h
@@ -46,6 +46,7 @@
#define ENV_SANDBOX_BASHRC "SANDBOX_BASHRC"
#define ENV_SANDBOX_LOG "SANDBOX_LOG"
#define ENV_SANDBOX_DEBUG_LOG "SANDBOX_DEBUG_LOG"
+#define ENV_SANDBOX_MESSAGE_PATH "SANDBOX_MESSAGE_PATH"
#define ENV_SANDBOX_WORKDIR "SANDBOX_WORKDIR"
#define ENV_SANDBOX_DENY "SANDBOX_DENY"
@@ -70,6 +71,7 @@ void get_sandbox_lib(char *path);
void get_sandbox_rc(char *path);
void get_sandbox_log(char *path, const char *tmpdir);
void get_sandbox_debug_log(char *path, const char *tmpdir);
+void get_sandbox_message_path(char *path);
int get_tmp_dir(char *path);
bool is_env_on(const char *);
bool is_env_off(const char *);
@@ -86,6 +88,7 @@ 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_message_path;
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);
diff --git a/src/environ.c b/src/environ.c
index 727f10b..5f22829 100644
--- a/src/environ.c
+++ b/src/environ.c
@@ -254,6 +254,7 @@ char **setup_environ(struct sandbox_info_t *sandbox_info)
unsetenv(ENV_SANDBOX_BASHRC);
unsetenv(ENV_SANDBOX_LOG);
unsetenv(ENV_SANDBOX_DEBUG_LOG);
+ unsetenv(ENV_SANDBOX_MESSAGE_PATH);
unsetenv(ENV_SANDBOX_WORKDIR);
unsetenv(ENV_SANDBOX_ACTIVE);
unsetenv(ENV_BASH_ENV);
@@ -285,8 +286,8 @@ char **setup_environ(struct sandbox_info_t *sandbox_info)
sb_setenv(&new_environ, ENV_SANDBOX_LIB, sandbox_info->sandbox_lib);
sb_setenv(&new_environ, ENV_SANDBOX_BASHRC, sandbox_info->sandbox_rc);
sb_setenv(&new_environ, ENV_SANDBOX_LOG, sandbox_info->sandbox_log);
- sb_setenv(&new_environ, ENV_SANDBOX_DEBUG_LOG,
- sandbox_info->sandbox_debug_log);
+ sb_setenv(&new_environ, ENV_SANDBOX_DEBUG_LOG, sandbox_info->sandbox_debug_log);
+ sb_setenv(&new_environ, ENV_SANDBOX_MESSAGE_PATH, sandbox_info->sandbox_message_path);
/* Just set the these if not already set so that is_env_on() work */
if (!getenv(ENV_SANDBOX_VERBOSE))
sb_setenv(&new_environ, ENV_SANDBOX_VERBOSE, "1");
diff --git a/src/sandbox.c b/src/sandbox.c
index aa957f6..51f2d95 100644
--- a/src/sandbox.c
+++ b/src/sandbox.c
@@ -26,6 +26,7 @@ volatile static pid_t child_pid = 0;
static const char sandbox_banner[] = "============================= Gentoo path sandbox ==============================";
static const char sandbox_footer[] = "--------------------------------------------------------------------------------";
+const char *sbio_message_path;
const char sbio_fallback_path[] = "/dev/stderr";
static int setup_sandbox(struct sandbox_info_t *sandbox_info, bool interactive)
@@ -80,6 +81,18 @@ static int setup_sandbox(struct sandbox_info_t *sandbox_info, bool interactive)
}
}
+ /* Generate sandbox message path -- this process's stderr */
+ char path[SB_PATH_MAX];
+ sprintf(path, "%s/2", sb_get_fd_dir());
+ if (realpath(path, sandbox_info->sandbox_message_path) == NULL) {
+ sb_pwarn("could not read stderr path: %s", path);
+ if (realpath(sbio_fallback_path, sandbox_info->sandbox_message_path)) {
+ sb_pwarn("could not read stderr path: %s", sbio_fallback_path);
+ /* fuck it */
+ strcpy(sandbox_info->sandbox_message_path, sbio_fallback_path);
+ }
+ }
+
return 0;
}
diff --git a/src/sandbox.h b/src/sandbox.h
index cc67753..c0c4315 100644
--- a/src/sandbox.h
+++ b/src/sandbox.h
@@ -16,6 +16,7 @@
struct sandbox_info_t {
char sandbox_log[SB_PATH_MAX];
char sandbox_debug_log[SB_PATH_MAX];
+ char sandbox_message_path[SB_PATH_MAX];
char sandbox_lib[SB_PATH_MAX];
char sandbox_rc[SB_PATH_MAX];
char work_dir[SB_PATH_MAX];
diff --git a/tests/sb_printf_tst.c b/tests/sb_printf_tst.c
index 867f782..1fe7566 100644
--- a/tests/sb_printf_tst.c
+++ b/tests/sb_printf_tst.c
@@ -11,6 +11,7 @@
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";
+const char *sbio_message_path = sbio_fallback_path;
int main(int argc, char *argv[])
{