diff options
Diffstat (limited to 'libsandbox')
-rw-r--r-- | libsandbox/Makefile.am | 2 | ||||
-rwxr-xr-x | libsandbox/moo/usr/lib/libsandbox.so | bin | 0 -> 192531 bytes | |||
-rw-r--r-- | libsandbox/trace.c | 145 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/__64_post.h | 1 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/__64_pre.h | 1 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/__openat_2.c | 38 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/fopen.c | 28 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/fopen64.c | 6 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/fopen64_pre_check.c | 12 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/fopen_pre_check.c | 26 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/mkdir.c | 4 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/mkdirat.c | 42 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/mkdirat_pre_check.c | 42 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/openat.c | 40 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/openat64_pre_check.c | 12 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/openat_pre_check.c | 28 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/unlink.c | 4 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/unlinkat.c | 38 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/unlinkat_pre_check.c | 38 | ||||
-rw-r--r-- | libsandbox/wrappers.h | 9 |
20 files changed, 297 insertions, 219 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 Binary files differnew file mode 100755 index 0000000..2641d01 --- /dev/null +++ b/libsandbox/moo/usr/lib/libsandbox.so 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, ®s)) { + 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 |