aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-06-04 00:19:20 -0400
committerMike Frysinger <vapier@gentoo.org>2009-06-04 00:19:20 -0400
commit70f148095b7b9acd4e8329da0766aadc88b017d8 (patch)
treef9c69308721da245f85bf0f09dfffc6234d9ab61
parentlibsandbox: make sure fopen64 uses 64bit funcs (diff)
downloadsandbox-70f148095b7b9acd4e8329da0766aadc88b017d8.tar.gz
sandbox-70f148095b7b9acd4e8329da0766aadc88b017d8.tar.bz2
sandbox-70f148095b7b9acd4e8329da0766aadc88b017d8.zip
libsandbox: add pre checks to static tracing
The normal wrapped functions go through some "pre checks" where certain normal conditions are not flagged as problematic. The static tracing lacked those pre checks though. URL: http://bugs.gentoo.org/265885 Signed-off-by: Mike Frysinger <vapier@gentoo.org> Reported-by: Daniel Robbins <drobbins@funtoo.org>
-rw-r--r--libsandbox/Makefile.am2
-rwxr-xr-xlibsandbox/moo/usr/lib/libsandbox.sobin0 -> 192531 bytes
-rw-r--r--libsandbox/trace.c145
-rw-r--r--libsandbox/wrapper-funcs/__64_post.h1
-rw-r--r--libsandbox/wrapper-funcs/__64_pre.h1
-rw-r--r--libsandbox/wrapper-funcs/__openat_2.c38
-rw-r--r--libsandbox/wrapper-funcs/fopen.c28
-rw-r--r--libsandbox/wrapper-funcs/fopen64.c6
-rw-r--r--libsandbox/wrapper-funcs/fopen64_pre_check.c12
-rw-r--r--libsandbox/wrapper-funcs/fopen_pre_check.c26
-rw-r--r--libsandbox/wrapper-funcs/mkdir.c4
-rw-r--r--libsandbox/wrapper-funcs/mkdirat.c42
-rw-r--r--libsandbox/wrapper-funcs/mkdirat_pre_check.c42
-rw-r--r--libsandbox/wrapper-funcs/openat.c40
-rw-r--r--libsandbox/wrapper-funcs/openat64_pre_check.c12
-rw-r--r--libsandbox/wrapper-funcs/openat_pre_check.c28
-rw-r--r--libsandbox/wrapper-funcs/unlink.c4
-rw-r--r--libsandbox/wrapper-funcs/unlinkat.c38
-rw-r--r--libsandbox/wrapper-funcs/unlinkat_pre_check.c38
-rw-r--r--libsandbox/wrappers.h9
-rw-r--r--scripts/gen_symbol_header.awk5
-rwxr-xr-xtests/open_static-1.sh2
-rwxr-xr-xtests/openat_static-1.sh2
-rwxr-xr-xtests/openat_static-2.sh2
24 files changed, 305 insertions, 222 deletions
diff --git a/libsandbox/Makefile.am b/libsandbox/Makefile.am
index c470f2e..9e1b775 100644
--- a/libsandbox/Makefile.am
+++ b/libsandbox/Makefile.am
@@ -51,7 +51,7 @@ SYMBOLS_WRAPPERS = $(wildcard $(srcdir)/wrapper-funcs/*.[ch])
GEN_VERSION_MAP_SCRIPT = $(SCRIPT_DIR)/gen_symbol_version_map.awk
GEN_HEADER_SCRIPT = $(SCRIPT_DIR)/gen_symbol_header.awk
GEN_TRACE_SCRIPT = $(SCRIPT_DIR)/gen_trace_header.awk
-SB_AWK = LC_ALL=C $(AWK) -v SYMBOLS_LIST="$(SYMBOLS_LIST)" -f
+SB_AWK = LC_ALL=C $(AWK) -v SYMBOLS_LIST="$(SYMBOLS_LIST)" -v srcdir="$(srcdir)" -f
SB_V = $(SB_V_$(V))
SB_V_ = @echo " GEN" $@;
diff --git a/libsandbox/moo/usr/lib/libsandbox.so b/libsandbox/moo/usr/lib/libsandbox.so
new file mode 100755
index 0000000..2641d01
--- /dev/null
+++ b/libsandbox/moo/usr/lib/libsandbox.so
Binary files differ
diff --git a/libsandbox/trace.c b/libsandbox/trace.c
index 7c5ec17..acbda70 100644
--- a/libsandbox/trace.c
+++ b/libsandbox/trace.c
@@ -15,6 +15,10 @@ pid_t trace_pid;
#ifndef SB_NO_TRACE
+#ifdef HAVE_OPEN64
+# define sb_openat_pre_check sb_openat64_pre_check
+#endif
+
#ifdef DEBUG
# define SBDEBUG 1
#else
@@ -43,9 +47,10 @@ static long _do_ptrace(enum __ptrace_request request, const char *srequest, void
/* Child hasn't gotten to the next marker yet ? */
if (errno == ESRCH) {
int status;
- if (waitpid(trace_pid, &status, 0) == -1)
+ if (waitpid(trace_pid, &status, 0) == -1) {
/* nah, it's dead ... should we whine though ? */
trace_exit(0);
+ }
sched_yield();
goto try_again;
} else if (!errno)
@@ -194,49 +199,73 @@ static const struct syscall_entry *lookup_syscall(int nr)
return lookup_syscall_in_tbl(trace_check_personality(), nr);
}
-static bool _trace_check_syscall_C(void *regs, int sb_nr, const char *func, int ibase)
+struct syscall_state {
+ void *regs;
+ int nr;
+ const char *func;
+ bool (*pre_check)(const char *func, const char *pathname, int dirfd);
+};
+
+static bool _trace_check_syscall_C(struct syscall_state *state, int ibase)
{
- char *path = do_peekstr(trace_arg(regs, ibase));
+ char *path = do_peekstr(trace_arg(state->regs, ibase));
__SB_DEBUG("(\"%s\")", path);
- bool ret = _SB_SAFE(sb_nr, func, path);
+ bool pre_ret, ret;
+ if (state->pre_check)
+ pre_ret = state->pre_check(state->func, path, AT_FDCWD);
+ else
+ pre_ret = true;
+ if (pre_ret)
+ ret = _SB_SAFE(state->nr, state->func, path);
+ else
+ ret = true;
free(path);
return ret;
}
-static bool trace_check_syscall_C(void *regs, int sb_nr, const char *func)
+static bool trace_check_syscall_C(struct syscall_state *state)
{
- return _trace_check_syscall_C(regs, sb_nr, func, 1);
+ return _trace_check_syscall_C(state, 1);
}
-static bool __trace_check_syscall_DCF(void *regs, int sb_nr, const char *func, int ibase, int flags)
+static bool __trace_check_syscall_DCF(struct syscall_state *state, int ibase, int flags)
{
- int dirfd = trace_arg(regs, ibase);
- char *path = do_peekstr(trace_arg(regs, ibase + 1));
+ 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);
- bool ret = _SB_SAFE_AT(sb_nr, func, dirfd, path, flags);
+ bool pre_ret, ret;
+ if (state->pre_check)
+ pre_ret = state->pre_check(state->func, path, dirfd);
+ else
+ pre_ret = true;
+ if (pre_ret)
+ ret = _SB_SAFE_AT(state->nr, state->func, dirfd, path, flags);
+ else
+ ret = true;
free(path);
return ret;
}
-static bool _trace_check_syscall_DCF(void *regs, int sb_nr, const char *func, int ibase)
+static bool _trace_check_syscall_DCF(struct syscall_state *state, int ibase)
{
- int flags = trace_arg(regs, ibase + 2);
- return __trace_check_syscall_DCF(regs, sb_nr, func, ibase, flags);
+ int flags = trace_arg(state->regs, ibase + 2);
+ return __trace_check_syscall_DCF(state, ibase, flags);
}
-static bool trace_check_syscall_DCF(void *regs, int sb_nr, const char *func)
+static bool trace_check_syscall_DCF(struct syscall_state *state)
{
- return _trace_check_syscall_DCF(regs, sb_nr, func, 1);
+ return _trace_check_syscall_DCF(state, 1);
}
-static bool _trace_check_syscall_DC(void *regs, int sb_nr, const char *func, int ibase)
+static bool _trace_check_syscall_DC(struct syscall_state *state, int ibase)
{
- return __trace_check_syscall_DCF(regs, sb_nr, func, ibase, 0);
+ return __trace_check_syscall_DCF(state, ibase, 0);
}
-static bool trace_check_syscall_DC(void *regs, int sb_nr, const char *func)
+static bool trace_check_syscall_DC(struct syscall_state *state)
{
- return _trace_check_syscall_DC(regs, sb_nr, func, 1);
+ return _trace_check_syscall_DC(state, 1);
}
static bool trace_check_syscall(const struct syscall_entry *se, void *regs)
{
+ struct syscall_state state;
bool ret = true;
int nr;
const char *name;
@@ -256,37 +285,45 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs)
if (!se)
goto done;
- nr = se->sys;
- name = se->name;
+ state.regs = regs;
+ state.nr = nr = se->sys;
+ state.func = name = se->name;
+ if (nr == SB_NR_UNDEF) goto done;
+ else if (nr == SB_NR_MKDIR) state.pre_check = sb_mkdirat_pre_check;
+ else if (nr == SB_NR_MKDIRAT) state.pre_check = sb_mkdirat_pre_check;
+ else if (nr == SB_NR_UNLINK) state.pre_check = sb_unlinkat_pre_check;
+ else if (nr == SB_NR_UNLINKAT) state.pre_check = sb_unlinkat_pre_check;
+ else state.pre_check = NULL;
+
/* Hmm, add these functions to the syscall table and avoid this if() ? */
if (nr == SB_NR_UNDEF) goto done;
- else if (nr == SB_NR_CHMOD) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_CHOWN) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_CREAT) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_FCHMODAT) return trace_check_syscall_DCF(regs, nr, name);
- else if (nr == SB_NR_FCHOWNAT) return trace_check_syscall_DCF(regs, nr, name);
- else if (nr == SB_NR_FUTIMESAT) return trace_check_syscall_DC (regs, nr, name);
- else if (nr == SB_NR_LCHOWN) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_LINK) return _trace_check_syscall_C (regs, nr, name, 2);
- else if (nr == SB_NR_LINKAT) return _trace_check_syscall_DCF(regs, nr, name, 3);
- else if (nr == SB_NR_MKDIR) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_MKDIRAT) return trace_check_syscall_DC (regs, nr, name);
- else if (nr == SB_NR_MKNOD) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_MKNODAT) return trace_check_syscall_DC (regs, nr, name);
- else if (nr == SB_NR_RENAME) return trace_check_syscall_C (regs, nr, name) &&
- _trace_check_syscall_C (regs, nr, name, 2);
- else if (nr == SB_NR_RENAMEAT) return trace_check_syscall_DC (regs, nr, name) &&
- _trace_check_syscall_DC (regs, nr, name, 3);
- else if (nr == SB_NR_RMDIR) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_SYMLINK) return _trace_check_syscall_C (regs, nr, name, 2);
- else if (nr == SB_NR_SYMLINKAT) return _trace_check_syscall_DC (regs, nr, name, 2);
- else if (nr == SB_NR_TRUNCATE) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_TRUNCATE64)return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_UNLINK) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_UNLINKAT) return trace_check_syscall_DCF(regs, nr, name);
- else if (nr == SB_NR_UTIME) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_UTIMES) return trace_check_syscall_C (regs, nr, name);
- else if (nr == SB_NR_UTIMENSAT) return trace_check_syscall_DCF(regs, nr, name);
+ else if (nr == SB_NR_CHMOD) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_CHOWN) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_CREAT) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_FCHMODAT) return trace_check_syscall_DCF(&state);
+ else if (nr == SB_NR_FCHOWNAT) return trace_check_syscall_DCF(&state);
+ else if (nr == SB_NR_FUTIMESAT) return trace_check_syscall_DC (&state);
+ else if (nr == SB_NR_LCHOWN) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_LINK) return _trace_check_syscall_C (&state, 2);
+ else if (nr == SB_NR_LINKAT) return _trace_check_syscall_DCF(&state, 3);
+ else if (nr == SB_NR_MKDIR) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_MKDIRAT) return trace_check_syscall_DC (&state);
+ else if (nr == SB_NR_MKNOD) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_MKNODAT) return trace_check_syscall_DC (&state);
+ else if (nr == SB_NR_RENAME) return trace_check_syscall_C (&state) &&
+ _trace_check_syscall_C (&state, 2);
+ else if (nr == SB_NR_RENAMEAT) return trace_check_syscall_DC (&state) &&
+ _trace_check_syscall_DC (&state, 3);
+ else if (nr == SB_NR_RMDIR) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_SYMLINK) return _trace_check_syscall_C (&state, 2);
+ else if (nr == SB_NR_SYMLINKAT) return _trace_check_syscall_DC (&state, 2);
+ else if (nr == SB_NR_TRUNCATE) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_TRUNCATE64)return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_UNLINK) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_UNLINKAT) return trace_check_syscall_DCF(&state);
+ else if (nr == SB_NR_UTIME) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_UTIMES) return trace_check_syscall_C (&state);
+ else if (nr == SB_NR_UTIMENSAT) return trace_check_syscall_DCF(&state);
else if (nr == SB_NR_ACCESS) {
char *path = do_peekstr(trace_arg(regs, 1));
@@ -309,7 +346,10 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs)
char *path = do_peekstr(trace_arg(regs, 1));
int flags = trace_arg(regs, 2);
__SB_DEBUG("(\"%s\", %x)", path, flags);
- ret = _SB_SAFE_OPEN_INT(nr, name, path, flags);
+ if (sb_openat_pre_check(name, path, AT_FDCWD, flags))
+ ret = _SB_SAFE_OPEN_INT(nr, name, path, flags);
+ else
+ ret = 1;
free(path);
return ret;
@@ -318,7 +358,10 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs)
char *path = do_peekstr(trace_arg(regs, 2));
int flags = trace_arg(regs, 3);
__SB_DEBUG("(%i, \"%s\", %x)", dirfd, path, flags);
- ret = _SB_SAFE_OPEN_INT_AT(nr, name, dirfd, path, flags);
+ if (sb_openat_pre_check(name, path, dirfd, flags))
+ ret = _SB_SAFE_OPEN_INT_AT(nr, name, dirfd, path, flags);
+ else
+ ret = 1;
free(path);
return ret;
}
@@ -369,6 +412,8 @@ static void trace_loop(void)
if (before_syscall) {
_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", " destroying\n");
do_ptrace(PTRACE_KILL, NULL, NULL);
exit(1);
}
diff --git a/libsandbox/wrapper-funcs/__64_post.h b/libsandbox/wrapper-funcs/__64_post.h
index 33ea3b2..2fd2182 100644
--- a/libsandbox/wrapper-funcs/__64_post.h
+++ b/libsandbox/wrapper-funcs/__64_post.h
@@ -1,2 +1,3 @@
+#undef SB64
#undef stat
#undef off_t
diff --git a/libsandbox/wrapper-funcs/__64_pre.h b/libsandbox/wrapper-funcs/__64_pre.h
index 1e836f4..2132110 100644
--- a/libsandbox/wrapper-funcs/__64_pre.h
+++ b/libsandbox/wrapper-funcs/__64_pre.h
@@ -1,2 +1,3 @@
+#define SB64
#define stat stat64
#define off_t off64_t
diff --git a/libsandbox/wrapper-funcs/__openat_2.c b/libsandbox/wrapper-funcs/__openat_2.c
index b7a6e09..4549a23 100644
--- a/libsandbox/wrapper-funcs/__openat_2.c
+++ b/libsandbox/wrapper-funcs/__openat_2.c
@@ -9,40 +9,16 @@
# define WRAPPER_ARGS_PROTO int dirfd, const char *pathname, int flags
# define WRAPPER_ARGS dirfd, pathname, flags
# define WRAPPER_SAFE() SB_SAFE_OPEN_INT_AT(dirfd, pathname, flags)
-# define USE_AT 1
#else
-# define USE_AT 0
+# define dirfd AT_FDCWD
#endif
-#ifndef PRE_CHECK_FUNC
-# define _PRE_CHECK_FUNC(x) sb_##x##_pre_check
-# define PRE_CHECK_FUNC(x) _PRE_CHECK_FUNC(x)
-#endif
-static inline bool PRE_CHECK_FUNC(WRAPPER_NAME)(WRAPPER_ARGS_PROTO)
-{
- if (!(flags & O_CREAT)) {
- /* If we're not trying to create, fail normally if
- * file does not stat
- */
-#if USE_AT
- if (dirfd == AT_FDCWD || pathname[0] == '/')
+#ifdef SB64
+# define WRAPPER_PRE_CHECKS() sb_openat64_pre_check(STRING_NAME, pathname, dirfd, flags)
+#else
+# define WRAPPER_PRE_CHECKS() sb_openat_pre_check(STRING_NAME, pathname, dirfd, flags)
#endif
-#undef USE_AT
- {
- struct stat st;
- save_errno();
- if (-1 == stat(pathname, &st)) {
- if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
- STRING_NAME, pathname, strerror(errno));
- return false;
- }
- restore_errno();
- }
- }
-
- return true;
-}
-#define WRAPPER_PRE_CHECKS() PRE_CHECK_FUNC(WRAPPER_NAME)(WRAPPER_ARGS)
#include "__wrapper_simple.c"
+
+#undef dirfd
diff --git a/libsandbox/wrapper-funcs/fopen.c b/libsandbox/wrapper-funcs/fopen.c
index 57e7dba..ce2fdf3 100644
--- a/libsandbox/wrapper-funcs/fopen.c
+++ b/libsandbox/wrapper-funcs/fopen.c
@@ -11,30 +11,10 @@
#define WRAPPER_RET_TYPE FILE *
#define WRAPPER_RET_DEFAULT NULL
-#ifndef SB_FOPEN_PRE_CHECK
-#define SB_FOPEN_PRE_CHECK
-static inline bool sb_fopen_pre_check(WRAPPER_ARGS_PROTO)
-{
- if ((NULL != mode) && (mode[0] == 'r')) {
- save_errno();
-
- /* 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",
- STRING_NAME, pathname, strerror(errno));
- return false;
- }
-
- restore_errno();
- }
-
- return true;
-}
-#endif
-#ifndef WRAPPER_PRE_CHECKS
-# define WRAPPER_PRE_CHECKS() sb_fopen_pre_check(WRAPPER_ARGS)
+#ifdef SB64
+# define WRAPPER_PRE_CHECKS() sb_fopen64_pre_check(STRING_NAME, pathname, mode)
+#else
+# define WRAPPER_PRE_CHECKS() sb_fopen_pre_check(STRING_NAME, pathname, mode)
#endif
#include "__wrapper_simple.c"
diff --git a/libsandbox/wrapper-funcs/fopen64.c b/libsandbox/wrapper-funcs/fopen64.c
index 60116fe..8e0cdb0 100644
--- a/libsandbox/wrapper-funcs/fopen64.c
+++ b/libsandbox/wrapper-funcs/fopen64.c
@@ -1,14 +1,10 @@
/*
* fopen64() wrapper.
*
- * Copyright 1999-2008 Gentoo Foundation
+ * Copyright 1999-2009 Gentoo Foundation
* Licensed under the GPL-2
*/
#include "__64_pre.h"
-#undef SB_FOPEN_PRE_CHECK
-#define sb_fopen_pre_check sb_fopen64_pre_check
-#define WRAPPER_PRE_CHECKS() sb_fopen64_pre_check(WRAPPER_ARGS)
#include "fopen.c"
-#undef sb_fopen_pre_check
#include "__64_post.h"
diff --git a/libsandbox/wrapper-funcs/fopen64_pre_check.c b/libsandbox/wrapper-funcs/fopen64_pre_check.c
new file mode 100644
index 0000000..3f7a737
--- /dev/null
+++ b/libsandbox/wrapper-funcs/fopen64_pre_check.c
@@ -0,0 +1,12 @@
+/*
+ * fopen64() pre-check.
+ *
+ * Copyright 1999-2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#include "__64_pre.h"
+#define sb_fopen_pre_check sb_fopen64_pre_check
+#include "fopen_pre_check.c"
+#undef sb_fopen_pre_check
+#include "__64_post.h"
diff --git a/libsandbox/wrapper-funcs/fopen_pre_check.c b/libsandbox/wrapper-funcs/fopen_pre_check.c
new file mode 100644
index 0000000..9ee3b60
--- /dev/null
+++ b/libsandbox/wrapper-funcs/fopen_pre_check.c
@@ -0,0 +1,26 @@
+/*
+ * fopen() pre-check.
+ *
+ * Copyright 1999-2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+bool sb_fopen_pre_check(const char *func, const char *pathname, const char *mode)
+{
+ if ((NULL != mode) && (mode[0] == 'r')) {
+ save_errno();
+
+ /* 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));
+ return false;
+ }
+
+ restore_errno();
+ }
+
+ return true;
+}
diff --git a/libsandbox/wrapper-funcs/mkdir.c b/libsandbox/wrapper-funcs/mkdir.c
index cc4cbee..4962490 100644
--- a/libsandbox/wrapper-funcs/mkdir.c
+++ b/libsandbox/wrapper-funcs/mkdir.c
@@ -1,13 +1,11 @@
/*
* mkdir() wrapper.
*
- * Copyright 1999-2008 Gentoo Foundation
+ * Copyright 1999-2009 Gentoo Foundation
* Licensed under the GPL-2
*/
#define WRAPPER_ARGS_PROTO const char *pathname, mode_t mode
#define WRAPPER_ARGS pathname, mode
#define WRAPPER_SAFE() SB_SAFE(pathname)
-#define sb_mkdirat_pre_check sb_mkdir_pre_check
#include "mkdirat.c"
-#undef sb_mkdirat_pre_check
diff --git a/libsandbox/wrapper-funcs/mkdirat.c b/libsandbox/wrapper-funcs/mkdirat.c
index f809c9f..4445356 100644
--- a/libsandbox/wrapper-funcs/mkdirat.c
+++ b/libsandbox/wrapper-funcs/mkdirat.c
@@ -1,7 +1,7 @@
/*
* mkdirat() wrapper.
*
- * Copyright 1999-2008 Gentoo Foundation
+ * Copyright 1999-2009 Gentoo Foundation
* Licensed under the GPL-2
*/
@@ -9,42 +9,12 @@
# define WRAPPER_ARGS_PROTO int dirfd, const char *pathname, mode_t mode
# define WRAPPER_ARGS dirfd, pathname, mode
# define WRAPPER_SAFE() SB_SAFE_AT(dirfd, pathname, 0)
+#else
+# define dirfd AT_FDCWD
#endif
-static inline bool sb_mkdirat_pre_check(WRAPPER_ARGS_PROTO)
-{
- char canonic[SB_PATH_MAX];
-
- save_errno();
-
- 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",
- STRING_NAME, pathname, strerror(errno));
- return false;
- }
-
- /* XXX: Hack to prevent errors if the directory exist, and are
- * not writable - we rather return EEXIST than fail. This can
- * occur if doing something like `mkdir -p /`. We certainly do
- * not want to pass this attempt up to the higher levels as those
- * will trigger a sandbox violation.
- */
- struct stat st;
- if (0 == lstat(canonic, &st)) {
- if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("EARLY FAIL", " %s(%s) @ lstat: %s\n",
- STRING_NAME, pathname, strerror(errno));
- errno = EEXIST;
- return false;
- }
-
- restore_errno();
-
- return true;
-}
-#define WRAPPER_PRE_CHECKS() sb_mkdirat_pre_check(WRAPPER_ARGS)
+#define WRAPPER_PRE_CHECKS() sb_mkdirat_pre_check(STRING_NAME, pathname, dirfd)
#include "__wrapper_simple.c"
+
+#undef dirfd
diff --git a/libsandbox/wrapper-funcs/mkdirat_pre_check.c b/libsandbox/wrapper-funcs/mkdirat_pre_check.c
new file mode 100644
index 0000000..ea9ff9a
--- /dev/null
+++ b/libsandbox/wrapper-funcs/mkdirat_pre_check.c
@@ -0,0 +1,42 @@
+/*
+ * mkdir*() pre-check.
+ *
+ * Copyright 1999-2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd)
+{
+ char canonic[SB_PATH_MAX];
+
+ save_errno();
+
+ /* XXX: need to check pathname with 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));
+ return false;
+ }
+
+ /* XXX: Hack to prevent errors if the directory exist, and are
+ * not writable - we rather return EEXIST than fail. This can
+ * occur if doing something like `mkdir -p /`. We certainly do
+ * not want to pass this attempt up to the higher levels as those
+ * will trigger a sandbox violation.
+ */
+ struct stat st;
+ if (0 == lstat(canonic, &st)) {
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s[%s]) @ lstat: %s\n",
+ func, pathname, canonic, strerror(errno));
+ errno = EEXIST;
+ return false;
+ }
+
+ restore_errno();
+
+ return true;
+}
diff --git a/libsandbox/wrapper-funcs/openat.c b/libsandbox/wrapper-funcs/openat.c
index 123b7c2..3e46ad5 100644
--- a/libsandbox/wrapper-funcs/openat.c
+++ b/libsandbox/wrapper-funcs/openat.c
@@ -1,7 +1,7 @@
/*
* openat() wrapper.
*
- * Copyright 1999-2008 Gentoo Foundation
+ * Copyright 1999-2009 Gentoo Foundation
* Licensed under the GPL-2
*/
@@ -12,42 +12,15 @@
# define WRAPPER_ARGS dirfd, pathname, flags
# define WRAPPER_ARGS_FULL WRAPPER_ARGS, mode
# define WRAPPER_SAFE() SB_SAFE_OPEN_INT_AT(dirfd, pathname, flags)
-# define USE_AT 1
#else
-# define USE_AT 0
+# define dirfd AT_FDCWD
#endif
-#ifndef PRE_CHECK_FUNC
-# define _PRE_CHECK_FUNC(x) sb_##x##_pre_check
-# define PRE_CHECK_FUNC(x) _PRE_CHECK_FUNC(x)
-#endif
-
-static inline bool PRE_CHECK_FUNC(WRAPPER_NAME)(_WRAPPER_ARGS_PROTO)
-{
- if (!(flags & O_CREAT)) {
- /* If we're not trying to create, fail normally if
- * file does not stat
- */
-#if USE_AT
- if (dirfd == AT_FDCWD || pathname[0] == '/')
+#ifdef SB64
+# define WRAPPER_PRE_CHECKS() sb_openat64_pre_check(STRING_NAME, pathname, dirfd, flags)
+#else
+# define WRAPPER_PRE_CHECKS() sb_openat_pre_check(STRING_NAME, pathname, dirfd, flags)
#endif
-#undef USE_AT
- {
- struct stat st;
- save_errno();
- if (-1 == stat(pathname, &st)) {
- if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
- STRING_NAME, pathname, strerror(errno));
- return false;
- }
- restore_errno();
- }
- }
-
- return true;
-}
-#define WRAPPER_PRE_CHECKS() PRE_CHECK_FUNC(WRAPPER_NAME)(WRAPPER_ARGS)
#define WRAPPER_SAFE_POST_EXPAND \
int mode = 0; \
@@ -60,4 +33,5 @@ static inline bool PRE_CHECK_FUNC(WRAPPER_NAME)(_WRAPPER_ARGS_PROTO)
#include "__wrapper_simple.c"
+#undef dirfd
#undef _WRAPPER_ARGS_PROTO
diff --git a/libsandbox/wrapper-funcs/openat64_pre_check.c b/libsandbox/wrapper-funcs/openat64_pre_check.c
new file mode 100644
index 0000000..67dc0dc
--- /dev/null
+++ b/libsandbox/wrapper-funcs/openat64_pre_check.c
@@ -0,0 +1,12 @@
+/*
+ * open*64*() pre-check.
+ *
+ * Copyright 1999-2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#include "__64_pre.h"
+#define sb_openat_pre_check sb_openat64_pre_check
+#include "openat_pre_check.c"
+#undef sb_openat_pre_check
+#include "__64_post.h"
diff --git a/libsandbox/wrapper-funcs/openat_pre_check.c b/libsandbox/wrapper-funcs/openat_pre_check.c
new file mode 100644
index 0000000..7f5e823
--- /dev/null
+++ b/libsandbox/wrapper-funcs/openat_pre_check.c
@@ -0,0 +1,28 @@
+/*
+ * open*() pre-check.
+ *
+ * Copyright 1999-2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+bool sb_openat_pre_check(const char *func, const char *pathname, int dirfd, int flags)
+{
+ if (!(flags & O_CREAT)) {
+ /* If we're not trying to create, fail normally if
+ * file does not stat
+ */
+ if (dirfd == AT_FDCWD || pathname[0] == '/') {
+ struct stat st;
+ save_errno();
+ if (-1 == stat(pathname, &st)) {
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
+ func, pathname, strerror(errno));
+ return false;
+ }
+ restore_errno();
+ }
+ }
+
+ return true;
+}
diff --git a/libsandbox/wrapper-funcs/unlink.c b/libsandbox/wrapper-funcs/unlink.c
index 79cab10..4f26de1 100644
--- a/libsandbox/wrapper-funcs/unlink.c
+++ b/libsandbox/wrapper-funcs/unlink.c
@@ -1,13 +1,11 @@
/*
* unlink() wrapper.
*
- * Copyright 1999-2008 Gentoo Foundation
+ * Copyright 1999-2009 Gentoo Foundation
* Licensed under the GPL-2
*/
#define WRAPPER_ARGS_PROTO const char *pathname
#define WRAPPER_ARGS pathname
#define WRAPPER_SAFE() SB_SAFE(pathname)
-#define sb_unlinkat_pre_check sb_unlink_pre_check
#include "unlinkat.c"
-#undef sb_unlinkat_pre_check
diff --git a/libsandbox/wrapper-funcs/unlinkat.c b/libsandbox/wrapper-funcs/unlinkat.c
index 4ef4a3b..34bce72 100644
--- a/libsandbox/wrapper-funcs/unlinkat.c
+++ b/libsandbox/wrapper-funcs/unlinkat.c
@@ -1,7 +1,7 @@
/*
* unlinkat() wrapper.
*
- * Copyright 1999-2008 Gentoo Foundation
+ * Copyright 1999-2009 Gentoo Foundation
* Licensed under the GPL-2
*/
@@ -9,38 +9,12 @@
# define WRAPPER_ARGS_PROTO int dirfd, const char *pathname, int flags
# define WRAPPER_ARGS dirfd, pathname, flags
# define WRAPPER_SAFE() SB_SAFE_AT(dirfd, pathname, flags)
+#else
+# define dirfd AT_FDCWD
#endif
-static inline bool sb_unlinkat_pre_check(WRAPPER_ARGS_PROTO)
-{
- char canonic[SB_PATH_MAX];
-
- save_errno();
-
- if (-1 == canonicalize(pathname, canonic))
- /* see comments in check_syscall() */
- if (ENAMETOOLONG != errno)
- goto error;
-
- /* XXX: Hack to make sure sandboxed process cannot remove
- * a device node, bug #79836. */
- if (0 == strcmp(canonic, "/dev/null") ||
- 0 == strcmp(canonic, "/dev/zero"))
- {
- errno = EACCES;
- goto error;
- }
-
- restore_errno();
-
- return true;
-
- error:
- if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
- STRING_NAME, pathname, strerror(errno));
- return false;
-}
-#define WRAPPER_PRE_CHECKS() sb_unlinkat_pre_check(WRAPPER_ARGS)
+#define WRAPPER_PRE_CHECKS() sb_unlinkat_pre_check(STRING_NAME, pathname, dirfd)
#include "__wrapper_simple.c"
+
+#undef dirfd
diff --git a/libsandbox/wrapper-funcs/unlinkat_pre_check.c b/libsandbox/wrapper-funcs/unlinkat_pre_check.c
new file mode 100644
index 0000000..961c31f
--- /dev/null
+++ b/libsandbox/wrapper-funcs/unlinkat_pre_check.c
@@ -0,0 +1,38 @@
+/*
+ * unlink*() pre-check.
+ *
+ * Copyright 1999-2009 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+bool sb_unlinkat_pre_check(const char *func, const char *pathname, int dirfd)
+{
+ char canonic[SB_PATH_MAX];
+
+ save_errno();
+
+ /* XXX: need to check pathname with dirfd */
+ if (-1 == canonicalize(pathname, canonic))
+ /* see comments in check_syscall() */
+ if (ENAMETOOLONG != errno)
+ goto error;
+
+ /* XXX: Hack to make sure sandboxed process cannot remove
+ * a device node, bug #79836. */
+ if (0 == strcmp(canonic, "/dev/null") ||
+ 0 == strcmp(canonic, "/dev/zero"))
+ {
+ errno = EACCES;
+ goto error;
+ }
+
+ restore_errno();
+
+ return true;
+
+ error:
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
+ func, pathname, strerror(errno));
+ return false;
+}
diff --git a/libsandbox/wrappers.h b/libsandbox/wrappers.h
index fddbe1b..5b97787 100644
--- a/libsandbox/wrappers.h
+++ b/libsandbox/wrappers.h
@@ -3,7 +3,7 @@
*
* Function wrapping functions.
*
- * Copyright 1999-2008 Gentoo Foundation
+ * Copyright 1999-2009 Gentoo Foundation
* Licensed under the GPL-2
*/
@@ -22,4 +22,11 @@ attribute_hidden int sb_unwrapped_open (const char *, int, mode_t);
#define sb_unwrapped_popen sb_unwrapped_popen_DEFAULT
attribute_hidden FILE *sb_unwrapped_popen (const char *, const char *);
+attribute_hidden bool sb_fopen_pre_check (const char *func, const char *pathname, const char *mode);
+attribute_hidden bool sb_fopen64_pre_check (const char *func, const char *pathname, const char *mode);
+attribute_hidden bool sb_mkdirat_pre_check (const char *func, const char *pathname, int dirfd);
+attribute_hidden bool sb_openat_pre_check (const char *func, const char *pathname, int dirfd, int flags);
+attribute_hidden bool sb_openat64_pre_check (const char *func, const char *pathname, int dirfd, int flags);
+attribute_hidden bool sb_unlinkat_pre_check (const char *func, const char *pathname, int dirfd);
+
#endif
diff --git a/scripts/gen_symbol_header.awk b/scripts/gen_symbol_header.awk
index 49e4540..749dabc 100644
--- a/scripts/gen_symbol_header.awk
+++ b/scripts/gen_symbol_header.awk
@@ -109,8 +109,10 @@ END {
# that we know what the name is in libsandbox.c ...
# Also do this for non-versioned libc's ...
if (sym_full_names[x] ~ /@@/ || !symbol_array[2]) {
+ sym_is_default = 1;
sym_real_name = sym_index "_DEFAULT";
} else {
+ sym_is_default = 0;
sym_real_name = sym_full_names[x];
gsub(/@|\./, "_", sym_real_name);
}
@@ -134,6 +136,9 @@ END {
printf("#define SB_NR_%s %i\n", toupper(sym_index), i);
printf("#define WRAPPER_NR SB_NR_%s\n", toupper(sym_index));
printf("#include \"wrapper-funcs/%s.c\"\n", sym_index);
+ pre_check = "wrapper-funcs/" sym_index "_pre_check.c"
+ if (sym_is_default && system("test -e " srcdir "/" pre_check) == 0)
+ printf("#include \"%s\"\n", pre_check);
printf("#undef STRING_NAME\n");
printf("#undef EXTERN_NAME\n");
printf("#undef WRAPPER_NAME\n");
diff --git a/tests/open_static-1.sh b/tests/open_static-1.sh
index 99c24ec..0143402 100755
--- a/tests/open_static-1.sh
+++ b/tests/open_static-1.sh
@@ -9,5 +9,5 @@ open_static-0 3 ok O_RDONLY 0666 || exit 1
export SANDBOX_LOG=$PWD/sb.log
mkdir deny || exit 1
adddeny $PWD/deny
-open_static-0 -1 deny/not-ok O_WRONLY 0666
+open_static-0 -1 deny/not-ok "O_WRONLY|O_CREAT" 0666
test -e sb.log
diff --git a/tests/openat_static-1.sh b/tests/openat_static-1.sh
index 16e1013..a00b19c 100755
--- a/tests/openat_static-1.sh
+++ b/tests/openat_static-1.sh
@@ -9,5 +9,5 @@ openat_static-0 3 AT_FDCWD ok O_RDONLY 0666 || exit 1
export SANDBOX_LOG=$PWD/sb.log
mkdir deny || exit 1
adddeny $PWD/deny
-openat_static-0 -1 AT_FDCWD deny/not-ok O_WRONLY 0666
+openat_static-0 -1 AT_FDCWD deny/not-ok "O_WRONLY|O_CREAT" 0666
test -e sb.log
diff --git a/tests/openat_static-2.sh b/tests/openat_static-2.sh
index f2f4152..00a948e 100755
--- a/tests/openat_static-2.sh
+++ b/tests/openat_static-2.sh
@@ -9,5 +9,5 @@ openat_static-0 3 AT_FDCWD ok O_RDONLY 0666 || exit 1
export SANDBOX_LOG=$PWD/sb.log
mkdir deny || exit 1
adddeny $PWD/deny
-openat_static-0 -1 AT_FDCWD $PWD/deny/not-ok O_WRONLY 0666
+openat_static-0 -1 AT_FDCWD $PWD/deny/not-ok "O_WRONLY|O_CREAT" 0666
test -e sb.log