commit: dacccb0b801a7a75267f674d219fb89393e862d3 Author: Mike Gilbert <floppym <AT> gentoo <DOT> org> AuthorDate: Sun Dec 22 02:54:20 2024 +0000 Commit: Mike Gilbert <floppym <AT> gentoo <DOT> org> CommitDate: Sun Dec 22 03:43:25 2024 +0000 URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=dacccb0b
Fix handling of faccessat with AT_EMPTY_PATH Bug: https://bugs.gentoo.org/946793 Signed-off-by: Mike Gilbert <floppym <AT> gentoo.org> (cherry picked from commit c8491074bb094dbceb773eb1803ddc5f499ea67b) libsandbox/libsandbox.c | 37 +++++++++++++++++------------------- libsandbox/libsandbox.h | 18 +++++++++--------- libsandbox/trace.c | 6 +++--- libsandbox/wrapper-funcs/faccessat.c | 2 +- tests/faccessat-1.sh | 7 +++++++ tests/faccessat.at | 1 + tests/test-skel-0.c | 3 ++- 7 files changed, 40 insertions(+), 34 deletions(-) diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c index c4bfac8..2843536 100644 --- a/libsandbox/libsandbox.c +++ b/libsandbox/libsandbox.c @@ -1061,21 +1061,14 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in int result; char *at_file_buf; - /* 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') { - if ((file == NULL || (flags & AT_EMPTY_PATH)) && - (sb_nr == SB_NR_UTIMENSAT || sb_nr == SB_NR_FUTIMESAT)) - { - /* let it slide -- the func is magic and changes behavior - * from "file relative to dirfd" to "dirfd is actually file - * fd" whenever file is NULL. - */ - } else { - errno = ENOENT; - return false; - } + if (file == NULL) { + /* futimesat treats dirfd as the target when file is NULL */ + if (sb_nr != SB_NR_FUTIMESAT) + return true; /* let the kernel reject this */ + } + else if (file[0] == '\0') { + if (!(flags & AT_EMPTY_PATH)) + return true; /* let the kernel reject this */ } switch (resolve_dirfd_path_alloc(dirfd, file, &at_file_buf)) { @@ -1117,13 +1110,17 @@ bool before_syscall(int dirfd, int sb_nr, const char *func, const char *file, in return result ? true : false; } -bool before_syscall_access(int dirfd, int sb_nr, const char *func, const char *file, int flags) +bool before_syscall_access(int dirfd, int sb_nr, const char *func, const char *file, int mode, int flags) { const char *ext_func; - if (flags & W_OK) - sb_nr = SB_NR_ACCESS_WR, ext_func = "access_wr"; - else if (flags & R_OK) - sb_nr = SB_NR_ACCESS_RD, ext_func = "access_rd"; + if (mode & W_OK) { + sb_nr = SB_NR_ACCESS_WR; + ext_func = "access_wr"; + } + else if (mode & R_OK) { + sb_nr = SB_NR_ACCESS_RD; + ext_func = "access_rd"; + } else /* Must be F_OK or X_OK; we do not need to check either. */ return true; diff --git a/libsandbox/libsandbox.h b/libsandbox/libsandbox.h index 01a4c6c..1bc79bb 100644 --- a/libsandbox/libsandbox.h +++ b/libsandbox/libsandbox.h @@ -23,14 +23,14 @@ #define SB_SAFE(_path) \ SB_SAFE_AT(AT_FDCWD, _path, 0) -#define _SB_SAFE_ACCESS_AT(_nr, _name, _dirfd, _path, _flags) \ - __SB_SAFE(before_syscall_access(_dirfd, _nr, _name, _path, _flags)) -#define SB_SAFE_ACCESS_AT(_dirfd, _path, _flags) \ - _SB_SAFE_ACCESS_AT(WRAPPER_NR, STRING_NAME, _dirfd, _path, _flags) -#define _SB_SAFE_ACCESS(_nr, _name, _path, _flags) \ - _SB_SAFE_ACCESS_AT(_nr, _name, AT_FDCWD, _path, _flags) -#define SB_SAFE_ACCESS(_path, _flags) \ - SB_SAFE_ACCESS_AT(AT_FDCWD, _path, _flags) +#define _SB_SAFE_ACCESS_AT(_nr, _name, _dirfd, _path, _mode, _flags) \ + __SB_SAFE(before_syscall_access(_dirfd, _nr, _name, _path, _mode, _flags)) +#define SB_SAFE_ACCESS_AT(_dirfd, _path, _mode, _flags) \ + _SB_SAFE_ACCESS_AT(WRAPPER_NR, STRING_NAME, _dirfd, _path, _mode, _flags) +#define _SB_SAFE_ACCESS(_nr, _name, _path, _mode) \ + _SB_SAFE_ACCESS_AT(_nr, _name, AT_FDCWD, _path, _mode, 0) +#define SB_SAFE_ACCESS(_path, _mode) \ + SB_SAFE_ACCESS_AT(AT_FDCWD, _path, _mode, 0) #define _SB_SAFE_OPEN_INT_AT(_nr, _name, _dirfd, _path, _flags) \ __SB_SAFE(before_syscall_open_int(_dirfd, _nr, _name, _path, _flags)) @@ -57,7 +57,7 @@ bool is_sandbox_on(void); bool before_syscall(int, int, const char *, const char *, int); -bool before_syscall_access(int, int, const char *, const char *, int); +bool before_syscall_access(int, int, const char *, const char *, int, int); bool before_syscall_open_int(int, int, const char *, const char *, int); bool before_syscall_open_char(int, int, const char *, const char *, const char *); bool before_syscall_fd(int, const char *, int); diff --git a/libsandbox/trace.c b/libsandbox/trace.c index 7ac4b5d..59449d9 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -362,9 +362,9 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) } else if (nr == SB_NR_FACCESSAT) { int dirfd = trace_arg(regs, 1); char *path = do_peekstr(trace_arg(regs, 2)); - int flags = trace_arg(regs, 3); - __sb_debug("(%i, \"%s\", %x)", dirfd, path, flags); - ret = _SB_SAFE_ACCESS_AT(nr, name, dirfd, path, flags); + int mode = trace_arg(regs, 3); + __sb_debug("(%i, \"%s\", %x)", dirfd, path, mode); + ret = _SB_SAFE_ACCESS_AT(nr, name, dirfd, path, mode, 0); free(path); return ret; diff --git a/libsandbox/wrapper-funcs/faccessat.c b/libsandbox/wrapper-funcs/faccessat.c index 722b313..056f5ee 100644 --- a/libsandbox/wrapper-funcs/faccessat.c +++ b/libsandbox/wrapper-funcs/faccessat.c @@ -7,5 +7,5 @@ #define WRAPPER_ARGS_PROTO int dirfd, const char *pathname, int mode, int flags #define WRAPPER_ARGS dirfd, pathname, mode, flags -#define WRAPPER_SAFE() SB_SAFE_ACCESS_AT(dirfd, pathname, mode) +#define WRAPPER_SAFE() SB_SAFE_ACCESS_AT(dirfd, pathname, mode, flags) #include "__wrapper_simple.c" diff --git a/tests/faccessat-1.sh b/tests/faccessat-1.sh new file mode 100644 index 0000000..66b5268 --- /dev/null +++ b/tests/faccessat-1.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e +addwrite "$PWD/file" +faccessat-0 0 'file:O_RDWR|O_CREAT:0666' '' rw AT_EMPTY_PATH +exec 9<file +adddeny "$PWD/file" +faccessat-0 -1,EACCES 9 '' rw AT_EMPTY_PATH diff --git a/tests/faccessat.at b/tests/faccessat.at new file mode 100644 index 0000000..081d7d2 --- /dev/null +++ b/tests/faccessat.at @@ -0,0 +1 @@ +SB_CHECK(1) diff --git a/tests/test-skel-0.c b/tests/test-skel-0.c index 91128d3..efc03f1 100644 --- a/tests/test-skel-0.c +++ b/tests/test-skel-0.c @@ -66,7 +66,7 @@ const char *f_get_file(const char *str_file) return str_file; } -#define V_ATFLAGS "0 | AT_SYMLINK_NOFOLLOW | AT_REMOVEDIR | AT_SYMLINK_FOLLOW | AT_EACCESS" +#define V_ATFLAGS "0 | AT_SYMLINK_NOFOLLOW | AT_REMOVEDIR | AT_SYMLINK_FOLLOW | AT_EACCESS | AT_EMPTY_PATH" int at_get_flags(const char *str_flags) { const value_pair flags[] = { @@ -74,6 +74,7 @@ int at_get_flags(const char *str_flags) PAIR(AT_REMOVEDIR) PAIR(AT_SYMLINK_FOLLOW) PAIR(AT_EACCESS) + PAIR(AT_EMPTY_PATH) { } }; return _get_flags(str_flags, flags);