aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-06-04 02:35:58 -0400
committerMike Frysinger <vapier@gentoo.org>2009-06-04 02:35:58 -0400
commit5f07adbe3c923448c5ee7b33022bc91ae04b17a8 (patch)
tree7a02489b1a9e43b5d17aef0f781002a387d35a0b /libsandbox
parentlibsandbox: ignore core dumps (diff)
downloadsandbox-5f07adbe3c923448c5ee7b33022bc91ae04b17a8.tar.gz
sandbox-5f07adbe3c923448c5ee7b33022bc91ae04b17a8.tar.bz2
sandbox-5f07adbe3c923448c5ee7b33022bc91ae04b17a8.zip
libsandbox: handle utimensat with NULL paths
The utimensat() function can operate on file fd's directly when the path is NULL, not just relative directory fd's. So tackle that use case. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'libsandbox')
-rw-r--r--libsandbox/libsandbox.c21
-rw-r--r--libsandbox/trace.c5
2 files changed, 18 insertions, 8 deletions
diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c
index 03a2069..c9b8fcd 100644
--- a/libsandbox/libsandbox.c
+++ b/libsandbox/libsandbox.c
@@ -962,10 +962,18 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in
static sbcontext_t sbcontext;
char at_file_buf[SB_PATH_MAX];
+ /* Some funcs operate on a fd directly and so filename is NULL, but
+ * the rest should get rejected as "file/directory does not exist".
+ */
if (file == NULL || file[0] == '\0') {
- /* The file/directory does not exist */
- errno = ENOENT;
- return false;
+ if (file == NULL && dirfd != AT_FDCWD &&
+ (sb_nr == SB_NR_UTIMENSAT))
+ {
+ /* let it slide */
+ } else {
+ errno = ENOENT;
+ return false;
+ }
}
save_errno();
@@ -977,8 +985,8 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in
* Since maintaining fd state based on open's is real messy, we'll
* just rely on the kernel doing it for us with /proc/<pid>/fd/ ...
*/
- if (dirfd != AT_FDCWD && file[0] != '/') {
- size_t at_len = sizeof(at_file_buf) - 1 - 1 - strlen(file);
+ if (dirfd != AT_FDCWD && (!file || file[0] != '/')) {
+ size_t at_len = sizeof(at_file_buf) - 1 - 1 - (file ? strlen(file) : 0);
sprintf(at_file_buf, "/proc/%i/fd/%i", trace_pid ? : getpid(), dirfd);
ssize_t ret = readlink(at_file_buf, at_file_buf, at_len);
if (ret == -1) {
@@ -997,7 +1005,8 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in
}
at_file_buf[ret] = '/';
at_file_buf[ret + 1] = '\0';
- strcat(at_file_buf, file);
+ if (file)
+ strcat(at_file_buf, file);
file = at_file_buf;
}
diff --git a/libsandbox/trace.c b/libsandbox/trace.c
index e4c241a..3f67758 100644
--- a/libsandbox/trace.c
+++ b/libsandbox/trace.c
@@ -328,7 +328,7 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs)
else if (nr == SB_NR_UNLINKAT) return trace_check_syscall_DCF(&state);
else if (nr == SB_NR_UTIME) return trace_check_syscall_C (&state);
else if (nr == SB_NR_UTIMES) return trace_check_syscall_C (&state);
- else if (nr == SB_NR_UTIMENSAT) return trace_check_syscall_DCF(&state);
+ else if (nr == SB_NR_UTIMENSAT) return _trace_check_syscall_DCF(&state, 2);
else if (nr == SB_NR_ACCESS) {
char *path = do_peekstr(trace_arg(regs, 1));
@@ -418,7 +418,8 @@ static void trace_loop(void)
_SB_DEBUG("%s:%i", se ? se->name : "IDK", nr);
if (!trace_check_syscall(se, &regs)) {
if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("trace_loop", " destroying\n");
+ SB_EINFO("trace_loop", " destroying after %s\n",
+ se->name);
do_ptrace(PTRACE_KILL, NULL, NULL);
exit(1);
}