diff options
-rw-r--r-- | libsandbox/wrapper-funcs/mkdirat_pre_check.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/libsandbox/wrapper-funcs/mkdirat_pre_check.c b/libsandbox/wrapper-funcs/mkdirat_pre_check.c index ea9ff9a..c999e46 100644 --- a/libsandbox/wrapper-funcs/mkdirat_pre_check.c +++ b/libsandbox/wrapper-funcs/mkdirat_pre_check.c @@ -29,10 +29,25 @@ bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) */ struct stat st; if (0 == lstat(canonic, &st)) { + int new_errno; if (is_env_on(ENV_SANDBOX_DEBUG)) SB_EINFO("EARLY FAIL", " %s(%s[%s]) @ lstat: %s\n", func, pathname, canonic, strerror(errno)); - errno = EEXIST; + + new_errno = EEXIST; + + /* Hmm, is this a broken symlink we're trying to extend ? */ + if (S_ISLNK(st.st_mode) && stat(pathname, &st) != 0) { + /* XXX: This awful hack should probably be turned into a + * common func that does a better job. For now, we have + * enough crap to catch gnulib tests #297026. + */ + char *parent = strrchr(pathname, '/'); + if (parent && (strcmp(parent, "/.") == 0 || strcmp(parent, "/..") == 0)) + new_errno = ENOENT; + } + + errno = new_errno; return false; } |