diff options
author | 2009-03-11 11:40:54 -0400 | |
---|---|---|
committer | 2009-03-11 11:41:00 -0400 | |
commit | f97f3d9a39e86b6de3fda3dc0f8470907bbb0ce8 (patch) | |
tree | d5cab4a48b7eee349ecaa1f9d551edcfbd53ee66 /tests | |
parent | libsandbox: add more exec wrappers (diff) | |
download | sandbox-f97f3d9a39e86b6de3fda3dc0f8470907bbb0ce8.tar.gz sandbox-f97f3d9a39e86b6de3fda3dc0f8470907bbb0ce8.tar.bz2 sandbox-f97f3d9a39e86b6de3fda3dc0f8470907bbb0ce8.zip |
libsandbox: do not restore errno in resolve_path() error path
If resolve_path() was unable to resolve things, then do not restore the
errno value as we use this to signal higher layers. This should make the
getcwd tests behave better.
URL: http://bugs.gentoo.org/261936
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Reported-by: Ryan Hill <dirtyepic@gentoo.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/getcwd-gnulib_tst.c | 119 | ||||
-rw-r--r-- | tests/script-5.sh | 10 | ||||
-rw-r--r-- | tests/script.at | 1 |
4 files changed, 133 insertions, 1 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 7fecbcb..12f0999 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -49,6 +49,7 @@ check_PROGRAMS = \ utimensat-0 \ utimes-0 \ \ + getcwd-gnulib_tst \ libsigsegv_tst \ sb_printf_tst @@ -65,7 +66,8 @@ dist_check_SCRIPTS = \ script-1.sh \ script-2.sh \ script-3.sh \ - script-4.sh + script-4.sh \ + script-5.sh sb_printf_tst_CFLAGS = -I$(top_srcdir)/libsbutil -I$(top_srcdir)/libsbutil/include sb_printf_tst_LDADD = $(top_builddir)/libsbutil/libsbutil.la diff --git a/tests/getcwd-gnulib_tst.c b/tests/getcwd-gnulib_tst.c new file mode 100644 index 0000000..416fa01 --- /dev/null +++ b/tests/getcwd-gnulib_tst.c @@ -0,0 +1,119 @@ +/* This comes from gnulib: gnulib/m4/getcwd-path-max.m4 + * On glibc systems, we currently exit(1). Sandbox should not get in the + * way of this, nor should it crash. + */ + +#include "tests.h" + +#ifndef S_IRWXU +# define S_IRWXU 0700 +#endif + +/* The length of this name must be 8. */ +#define DIR_NAME "confdir3" +#define DIR_NAME_LEN 8 +#define DIR_NAME_SIZE (DIR_NAME_LEN + 1) + +/* The length of "../". */ +#define DOTDOTSLASH_LEN 3 + +/* Leftover bytes in the buffer, to work around library or OS bugs. */ +#define BUF_SLOP 20 + +int +main () +{ + char buf[PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1) + + DIR_NAME_SIZE + BUF_SLOP]; + char *cwd = getcwd (buf, PATH_MAX); + size_t initial_cwd_len; + size_t cwd_len; + int fail = 0; + size_t n_chdirs = 0; + + if (cwd == NULL) + exit (1); + + cwd_len = initial_cwd_len = strlen (cwd); + + while (1) + { + size_t dotdot_max = PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN); + char *c = NULL; + + cwd_len += DIR_NAME_SIZE; + /* If mkdir or chdir fails, it could be that this system cannot create + any file with an absolute name longer than PATH_MAX, such as cygwin. + If so, leave fail as 0, because the current working directory can't + be too long for getcwd if it can't even be created. For other + errors, be pessimistic and consider that as a failure, too. */ + if (mkdir (DIR_NAME, S_IRWXU) < 0 || chdir (DIR_NAME) < 0) + { + if (! (errno == ERANGE || ENAMETOOLONG == errno)) + fail = 2; + break; + } + + if (PATH_MAX <= cwd_len && cwd_len < PATH_MAX + DIR_NAME_SIZE) + { + c = getcwd (buf, PATH_MAX); + if (!c && errno == ENOENT) + { + fail = 1; + break; + } + if (c || ! (errno == ERANGE || ENAMETOOLONG == errno)) + { + fail = 2; + break; + } + } + + if (dotdot_max <= cwd_len - initial_cwd_len) + { + if (dotdot_max + DIR_NAME_SIZE < cwd_len - initial_cwd_len) + break; + c = getcwd (buf, cwd_len + 1); + if (!c) + { + if (! (errno == ERANGE || errno == ENOENT + || ENAMETOOLONG == errno)) + { + fail = 2; + break; + } + if (AT_FDCWD || errno == ERANGE || errno == ENOENT) + { + fail = 1; + break; + } + } + } + + if (c && strlen (c) != cwd_len) + { + fail = 2; + break; + } + ++n_chdirs; + } + + /* Leaving behind such a deep directory is not polite. + So clean up here, right away, even though the driving + shell script would also clean up. */ + { + size_t i; + + /* Try rmdir first, in case the chdir failed. */ + rmdir (DIR_NAME); + for (i = 0; i <= n_chdirs; i++) + { + if (chdir ("..") < 0) + break; + if (rmdir (DIR_NAME) != 0) + break; + } + } + + exit (fail); +} diff --git a/tests/script-5.sh b/tests/script-5.sh new file mode 100644 index 0000000..96ea0a9 --- /dev/null +++ b/tests/script-5.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# make sure extra long paths don't cause sandbox to shit itself +# (actual exit status is irrelevant as it depends on host libc) + +addwrite $PWD +getcwd-gnulib_tst +case $? in + 0|1|2) exit 0;; # test may exit with these values + *) echo "someone get a diaper"; exit 1;; +esac diff --git a/tests/script.at b/tests/script.at index b344be9..2290505 100644 --- a/tests/script.at +++ b/tests/script.at @@ -3,3 +3,4 @@ SB_CHECK(1) SB_CHECK(2, [hi]) SB_CHECK(3, [OK]) SB_CHECK(4) +SB_CHECK(5) |