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);

Reply via email to