@@ -, +, @@ --- libsandbox/wrapper-funcs/mkdirat_pre_check.c | 36 +++++++++++++++++++++---- 1 files changed, 30 insertions(+), 6 deletions(-) --- a/libsandbox/wrapper-funcs/mkdirat_pre_check.c +++ a/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 --