aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2010-11-15 05:42:11 -0500
committerMike Frysinger <vapier@gentoo.org>2010-11-15 05:42:11 -0500
commitc473c10a447a285f8c7b762f34c0650f587e1ff4 (patch)
tree6845a6a1dec1d2a9bab09e7071b3abe068d5ead9 /libsandbox/wrapper-funcs
parenttests: generalize flag parsing to handle AT_* flags better (diff)
downloadsandbox-c473c10a447a285f8c7b762f34c0650f587e1ff4.tar.gz
sandbox-c473c10a447a285f8c7b762f34c0650f587e1ff4.tar.bz2
sandbox-c473c10a447a285f8c7b762f34c0650f587e1ff4.zip
libsandbox: handle dirfd in mkdir/open/unlink *at prechecks
Ignoring the dirfd hasn't been a problem in the past as people weren't really using it, but now that core packages are (like tar), we need to handle things properly. URL: http://bugs.gentoo.org/342983 Reported-by: Xake <xake@rymdraket.net> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'libsandbox/wrapper-funcs')
-rw-r--r--libsandbox/wrapper-funcs/mkdirat_pre_check.c15
-rw-r--r--libsandbox/wrapper-funcs/openat_pre_check.c45
-rw-r--r--libsandbox/wrapper-funcs/unlinkat_pre_check.c34
3 files changed, 68 insertions, 26 deletions
diff --git a/libsandbox/wrapper-funcs/mkdirat_pre_check.c b/libsandbox/wrapper-funcs/mkdirat_pre_check.c
index c999e46..d037546 100644
--- a/libsandbox/wrapper-funcs/mkdirat_pre_check.c
+++ b/libsandbox/wrapper-funcs/mkdirat_pre_check.c
@@ -8,10 +8,23 @@
bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd)
{
char canonic[SB_PATH_MAX];
+ char dirfd_path[SB_PATH_MAX];
save_errno();
- /* XXX: need to check pathname with dirfd */
+ /* Expand the dirfd path first */
+ switch (resolve_dirfd_path(dirfd, pathname, dirfd_path)) {
+ case -1:
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s) @ resolve_dirfd_path: %s\n",
+ func, pathname, strerror(errno));
+ return false;
+ case 0:
+ pathname = dirfd_path;
+ break;
+ }
+
+ /* Then break down any relative/symlink paths */
if (-1 == canonicalize(pathname, canonic))
/* see comments in check_syscall() */
if (ENAMETOOLONG != errno) {
diff --git a/libsandbox/wrapper-funcs/openat_pre_check.c b/libsandbox/wrapper-funcs/openat_pre_check.c
index 7f5e823..4a63413 100644
--- a/libsandbox/wrapper-funcs/openat_pre_check.c
+++ b/libsandbox/wrapper-funcs/openat_pre_check.c
@@ -7,22 +7,37 @@
bool sb_openat_pre_check(const char *func, const char *pathname, int dirfd, int flags)
{
- if (!(flags & O_CREAT)) {
- /* If we're not trying to create, fail normally if
- * file does not stat
- */
- if (dirfd == AT_FDCWD || pathname[0] == '/') {
- struct stat st;
- save_errno();
- if (-1 == stat(pathname, &st)) {
- if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
- func, pathname, strerror(errno));
- return false;
- }
- restore_errno();
- }
+ /* If we're not trying to create, fail normally if
+ * file does not stat
+ */
+ if (flags & O_CREAT)
+ return true;
+
+ save_errno();
+
+ /* Expand the dirfd path first */
+ char dirfd_path[SB_PATH_MAX];
+ switch (resolve_dirfd_path(dirfd, pathname, dirfd_path)) {
+ case -1:
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s) @ resolve_dirfd_path: %s\n",
+ func, pathname, strerror(errno));
+ return false;
+ case 0:
+ pathname = dirfd_path;
+ break;
}
+ /* Doesn't exist -> skip permission checks */
+ struct stat st;
+ if (-1 == stat(pathname, &st)) {
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
+ func, pathname, strerror(errno));
+ return false;
+ }
+
+ restore_errno();
+
return true;
}
diff --git a/libsandbox/wrapper-funcs/unlinkat_pre_check.c b/libsandbox/wrapper-funcs/unlinkat_pre_check.c
index 961c31f..4e4a38d 100644
--- a/libsandbox/wrapper-funcs/unlinkat_pre_check.c
+++ b/libsandbox/wrapper-funcs/unlinkat_pre_check.c
@@ -8,14 +8,31 @@
bool sb_unlinkat_pre_check(const char *func, const char *pathname, int dirfd)
{
char canonic[SB_PATH_MAX];
+ char dirfd_path[SB_PATH_MAX];
save_errno();
- /* XXX: need to check pathname with dirfd */
+ /* Expand the dirfd path first */
+ switch (resolve_dirfd_path(dirfd, pathname, dirfd_path)) {
+ case -1:
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s) @ resolve_dirfd_path: %s\n",
+ func, pathname, strerror(errno));
+ return false;
+ case 0:
+ pathname = dirfd_path;
+ break;
+ }
+
+ /* Then break down any relative/symlink paths */
if (-1 == canonicalize(pathname, canonic))
/* see comments in check_syscall() */
- if (ENAMETOOLONG != errno)
- goto error;
+ 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;
+ }
/* XXX: Hack to make sure sandboxed process cannot remove
* a device node, bug #79836. */
@@ -23,16 +40,13 @@ bool sb_unlinkat_pre_check(const char *func, const char *pathname, int dirfd)
0 == strcmp(canonic, "/dev/zero"))
{
errno = EACCES;
- goto error;
+ if (is_env_on(ENV_SANDBOX_DEBUG))
+ SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
+ func, pathname, strerror(errno));
+ return false;
}
restore_errno();
return true;
-
- error:
- if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("EARLY FAIL", " %s(%s): %s\n",
- func, pathname, strerror(errno));
- return false;
}