diff options
author | 2010-08-16 22:10:45 -0400 | |
---|---|---|
committer | 2010-08-16 22:10:45 -0400 | |
commit | ef2d8c1f96a176eba0e5eb265d8163824311a2fe (patch) | |
tree | 3794d0a834cf26ee3e60fcd8f1aab3a44f975990 | |
parent | tests: check rmdir functionality (diff) | |
download | sandbox-2.3.tar.gz sandbox-2.3.tar.bz2 sandbox-2.3.zip |
libsandbox: tempish mkdir hack for broken symlinksv2.3
Some gnulib tests that are bundled with multiple GNU packages stress the
POSIX correctness of mkdir behavior across broken symlinks. While this
specific behavior under ssandbox doesn't really matter (as packages don't
create broken symlinks and then need this errno value), it isn't really
feasible to patch all the random packages. So add a smallish hack for
now to keep them happy until something better can be formulated.
URL: http://bugs.gentoo.org/297026
Reported-by: Diego E. Pettenò <flameeyes@gentoo.org>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-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; } |