From 8c521d4f15072c16a6e41b474eaad174a2372e57 Mon Sep 17 00:00:00 2001 From: Peter Hjalmarsson Date: Thu, 28 Oct 2010 09:50:04 +0200 Subject: [PATCH] Patch that makes mkdirat_pre_check resolv the dirfd if dirfd != AT_FDCWD This patch makes sandbox handle mkdirat() if dirfd != AT_FDCWD canonicalize resolvs from CWD, and since you cannot resolv anything from /proc for AT_FSCWD we keep the canonicalize for those cases, and in every other case resolv dirfd from /proc, and does our tests on that path. --- libsandbox/wrapper-funcs/mkdirat_pre_check.c | 36 +++++++++++++++++++++---- 1 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libsandbox/wrapper-funcs/mkdirat_pre_check.c b/libsandbox/wrapper-funcs/mkdirat_pre_check.c index c999e46..538a607 100644 --- a/libsandbox/wrapper-funcs/mkdirat_pre_check.c +++ b/libsandbox/wrapper-funcs/mkdirat_pre_check.c @@ -11,15 +11,39 @@ bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) save_errno(); - /* XXX: need to check pathname with dirfd */ - if (-1 == canonicalize(pathname, canonic)) - /* see comments in check_syscall() */ - if (ENAMETOOLONG != errno) { + if (dirfd == AT_FDCWD) + { + /* dirfd points to CWD, so we reasolv from there */ + 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; + } + } + else + { + /* dirfd does not point to cwd, so we need to resolv it using /proc */ + /* more or less copy-paste from libsandbox.c::before_syscall() */ + + size_t at_len = sizeof(canonic) - 1 - 1 - (pathname ? strlen(pathname) : 0); + sprintf(canonic, "/proc/%i/fd/%i", trace_pid ? : getpid(), dirfd); + ssize_t ret = readlink(canonic, canonic, at_len); + if (ret == -1) { if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("EARLY FAIL", " %s(%s) @ canonicalize: %s\n", - func, pathname, strerror(errno)); + SB_EINFO("EARLY FAIL", " %s(%s) @ sb_mkdirat_pre_check,FD_LOOKUP: %s\n", + func, canonic, strerror(errno)); + /* If the fd isn't found, some guys (glibc) expect errno */ + if (errno == ENOENT) + errno = EBADF; return false; } + canonic[ret] = '/'; + canonic[ret + 1] = '\0'; + strcat(canonic,pathname); + } /* XXX: Hack to prevent errors if the directory exist, and are * not writable - we rather return EEXIST than fail. This can -- 1.7.3.2