aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-04-05 00:56:30 -0400
committerMike Frysinger <vapier@gentoo.org>2009-04-05 03:54:05 -0400
commit4f5ba92246606723806c0585393f21244d44036c (patch)
tree8faf05e0b33f28068c3cafff95694446a3b504a6 /libsandbox
parenttests: add some tracing tests (diff)
downloadsandbox-4f5ba92246606723806c0585393f21244d44036c.tar.gz
sandbox-4f5ba92246606723806c0585393f21244d44036c.tar.bz2
sandbox-4f5ba92246606723806c0585393f21244d44036c.zip
libsandbox: force lock sanity across forks
Classic example of forks being used in multithreaded applications and causing havoc with shared state (locks in this case). Make sure that threads grabbing the sandbox lock don't screw up threads that do a fork and then exec. URL: http://bugs.gentoo.org/263657 Signed-off-by: Mike Frysinger <vapier@gentoo.org> Reported-by: Ryan Hope <rmh3093@gmail.com>
Diffstat (limited to 'libsandbox')
-rw-r--r--libsandbox/Makefile.am1
-rw-r--r--libsandbox/libsandbox.c19
-rw-r--r--libsandbox/libsandbox.h3
-rw-r--r--libsandbox/lock.c41
-rw-r--r--libsandbox/symbols.h.in1
-rw-r--r--libsandbox/wrapper-funcs/fork.c24
6 files changed, 79 insertions, 10 deletions
diff --git a/libsandbox/Makefile.am b/libsandbox/Makefile.am
index 36393f0..eb9f0f2 100644
--- a/libsandbox/Makefile.am
+++ b/libsandbox/Makefile.am
@@ -30,6 +30,7 @@ libsandbox_la_SOURCES = \
eqawarn.c \
libsandbox.h \
libsandbox.c \
+ lock.c \
memory.c \
trace.c \
wrappers.h \
diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c
index 06f2bc6..4c4f643 100644
--- a/libsandbox/libsandbox.c
+++ b/libsandbox/libsandbox.c
@@ -58,7 +58,6 @@ typedef struct {
#define MAX_DYN_PREFIXES 4 /* the first 4 are dynamic */
} sbcontext_t;
-static sbcontext_t sbcontext;
static char *cached_env_vars[MAX_DYN_PREFIXES];
bool sandbox_on = true;
static bool sb_init = false;
@@ -73,10 +72,11 @@ static void init_env_entries(char ***, int *, const char *, const char *, int);
/*
* Initialize the shabang
*/
-
+#if 0
__attribute__((destructor))
void libsb_fini(void)
{
+ /* let the kernel reap our resources -- it's faster anyways */
int x;
sb_init = false;
@@ -92,11 +92,12 @@ void libsb_fini(void)
clean_env_entries(&(sbcontext.prefixes[x]),
&(sbcontext.num_prefixes[x]));
}
+#endif
__attribute__((constructor))
void libsb_init(void)
{
- int old_errno = errno;
+ save_errno();
#ifdef SB_MEM_DEBUG
mtrace();
@@ -109,7 +110,7 @@ void libsb_init(void)
// sb_init = true;
- errno = old_errno;
+ restore_errno();
}
static const char *sb_get_fd_dir(void)
@@ -954,13 +955,10 @@ bool is_sandbox_on(void)
return result;
}
-/* Need to protect the global sbcontext structure */
-static pthread_mutex_t sb_syscall_lock = PTHREAD_MUTEX_INITIALIZER;
-
bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, int flags)
{
int result;
-// static sbcontext_t sbcontext;
+ static sbcontext_t sbcontext;
char at_file_buf[SB_PATH_MAX];
if (file == NULL || file[0] == '\0') {
@@ -1002,7 +1000,8 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in
file = at_file_buf;
}
- pthread_mutex_lock(&sb_syscall_lock);
+ /* Need to protect the global sbcontext structure */
+ sb_lock();
if (!sb_init) {
init_context(&sbcontext);
@@ -1044,7 +1043,7 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in
result = check_syscall(&sbcontext, sb_nr, func, file, flags);
- pthread_mutex_unlock(&sb_syscall_lock);
+ sb_unlock();
if (0 == result) {
if ((NULL != getenv(ENV_SANDBOX_PID)) && (is_env_on(ENV_SANDBOX_ABORT)))
diff --git a/libsandbox/libsandbox.h b/libsandbox/libsandbox.h
index d20b81f..281ebf5 100644
--- a/libsandbox/libsandbox.h
+++ b/libsandbox/libsandbox.h
@@ -59,6 +59,9 @@ extern char sandbox_lib[SB_PATH_MAX];
extern bool sandbox_on;
extern pid_t trace_pid;
+extern void sb_lock(void);
+extern void sb_unlock(void);
+
void trace_main(const char *filename, char *const argv[]);
__attribute__((__format__(__printf__, 1, 2))) void sb_eqawarn(const char *format, ...);
diff --git a/libsandbox/lock.c b/libsandbox/lock.c
new file mode 100644
index 0000000..df5c6f9
--- /dev/null
+++ b/libsandbox/lock.c
@@ -0,0 +1,41 @@
+/* lock.c - providing locking mechanisms
+ *
+ * Copyright 2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#include "headers.h"
+#include "libsandbox.h"
+
+#if defined(HAVE_PTHREAD_H)
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+void sb_lock(void)
+{
+ pthread_mutex_lock(&lock);
+}
+
+void sb_unlock(void)
+{
+ pthread_mutex_unlock(&lock);
+}
+
+#elif defined(HAVE___SYNC_LOCK_TEST_AND_SET)
+
+static int lock = 0;
+
+void sb_lock(void)
+{
+ while (__sync_lock_test_and_set(&lock, 1))
+ continue;
+}
+
+void sb_unlock(void)
+{
+ __sync_lock_release(&lock);
+}
+
+#else
+# error no locking mech
+#endif
diff --git a/libsandbox/symbols.h.in b/libsandbox/symbols.h.in
index 4317e13..b674b5e 100644
--- a/libsandbox/symbols.h.in
+++ b/libsandbox/symbols.h.in
@@ -61,3 +61,4 @@ utimes
utimensat
futimesat
lutimes
+fork
diff --git a/libsandbox/wrapper-funcs/fork.c b/libsandbox/wrapper-funcs/fork.c
new file mode 100644
index 0000000..c250018
--- /dev/null
+++ b/libsandbox/wrapper-funcs/fork.c
@@ -0,0 +1,24 @@
+/*
+ * fork() wrapper.
+ *
+ * Copyright 1999-2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+/* We're only wrapping fork() as a poor man's pthread_atfork(). That would
+ * require dedicated linkage against libpthread. So here we force the locks
+ * to a consistent state before forking. #263657
+ */
+
+#define WRAPPER_ARGS_PROTO
+#define WRAPPER_ARGS
+#define WRAPPER_SAFE() 0
+#define WRAPPER_PRE_CHECKS() \
+({ \
+ /* pthread_atfork(sb_lock, sb_unlock, sb_unlock); */ \
+ sb_lock(); \
+ result = SB_HIDDEN_FUNC(WRAPPER_NAME)(WRAPPER_ARGS_FULL); \
+ sb_unlock(); \
+ false; \
+})
+#include "__wrapper_simple.c"