commit:     45a8321f5015b19e706b8a3a1e2203bba900f24d
Author:     Michael Orlitzky <michael <AT> orlitzky <DOT> com>
AuthorDate: Tue Jun 20 21:58:57 2023 +0000
Commit:     Mike Gilbert <floppym <AT> gentoo <DOT> org>
CommitDate: Thu Jun 22 13:55:26 2023 +0000
URL:        https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=45a8321f

libsandbox: add support for fchown/fchmod on linux

The fchown/fchmod functions use a file descriptor obtained from
open(), and the sandbox relies on its open() wrapper for safety. But
it turns out that fchown/fchmod can operate on a descriptor opened
O_RDONLY, which the open() wrapper is happy to give you. Oops. This is
bug 599706.

There's no POSIX way to map the descriptor to a path once you've got
it, but on linux you can use the magic path "/proc/self/fd/%i" which
should be a symlink pointing to the path passed to open(). Once we
have that path, we can use the existing "is this path safe" machinery
in the sandbox. There is precedent for this approach in sandbox, and
the SANDBOX_PROC_SELF_FD macro already exists to indicate that the
feature is available.

Bug: https://bugs.gentoo.org/599706
Signed-off-by: Michael Orlitzky <mjo <AT> gentoo.org>
Signed-off-by: Mike Gilbert <floppym <AT> gentoo.org>

 libsandbox/libsandbox.c           | 17 +++++++++++++++++
 libsandbox/libsandbox.h           |  7 +++++++
 libsandbox/symbols.h.in           |  2 ++
 libsandbox/trace.c                | 14 ++++++++++++++
 libsandbox/wrapper-funcs/fchmod.c | 11 +++++++++++
 libsandbox/wrapper-funcs/fchown.c | 11 +++++++++++
 6 files changed, 62 insertions(+)

diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c
index b9ef52e..847b4e2 100644
--- a/libsandbox/libsandbox.c
+++ b/libsandbox/libsandbox.c
@@ -766,7 +766,9 @@ static int check_access(sbcontext_t *sbcontext, int sb_nr, 
const char *func,
            sb_nr == SB_NR_CHOWN       ||
            sb_nr == SB_NR_CREAT       ||
            sb_nr == SB_NR_CREAT64     ||
+           sb_nr == SB_NR_FCHMOD      ||
            sb_nr == SB_NR_FCHMODAT    ||
+           sb_nr == SB_NR_FCHOWN      ||
            sb_nr == SB_NR_FCHOWNAT    ||
          /*sb_nr == SB_NR_FTRUNCATE   ||
            sb_nr == SB_NR_FTRUNCATE64 ||*/
@@ -1102,6 +1104,21 @@ bool before_syscall_open_int(int dirfd, int sb_nr, const 
char *func, const char
        return before_syscall(dirfd, sb_nr, ext_func, file, flags);
 }
 
+bool before_syscall_fd(int sb_nr, const char *func, int fd) {
+#ifdef SANDBOX_PROC_SELF_FD
+       /* We only know how to handle e.g. fchmod() and fchown() on
+        * linux, where it's possible to (eventually) get a path out
+        * of the given file descriptor. The "64" below accounts for
+        * the length of an integer string, and is probably
+        * overkill. */
+       char path[sizeof("/proc/self/fd/") + 64];
+       snprintf(path, sizeof("/proc/self/fd/") + 64, "/proc/self/fd/%i", fd);
+       return before_syscall(AT_FDCWD, sb_nr, func, path, 0);
+#else
+       return true;
+#endif
+}
+
 bool before_syscall_open_char(int dirfd, int sb_nr, const char *func, const 
char *file, const char *mode)
 {
        if (NULL == mode)

diff --git a/libsandbox/libsandbox.h b/libsandbox/libsandbox.h
index 206c506..01a4c6c 100644
--- a/libsandbox/libsandbox.h
+++ b/libsandbox/libsandbox.h
@@ -46,6 +46,11 @@
 #define  SB_SAFE_OPEN_CHAR(_path, _mode) \
          SB_SAFE_OPEN_CHAR_AT(AT_FDCWD, _path, _mode)
 
+#define _SB_SAFE_FD(_nr, _name, _fd) \
+        __SB_SAFE(before_syscall_fd(_nr, _name, fd))
+#define  SB_SAFE_FD(_fd) \
+         _SB_SAFE_FD(WRAPPER_NR, STRING_NAME, _fd)
+
 /* Symbols that don't exist in the C library will be <= this value. */
 #define SB_NR_UNDEF -99999
 #define SB_NR_IS_DEFINED(nr) (nr > SB_NR_UNDEF)
@@ -55,6 +60,8 @@ bool before_syscall(int, int, const char *, const char *, 
int);
 bool before_syscall_access(int, int, const char *, const char *, 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);
+
 enum sandbox_method_t get_sandbox_method(void);
 
 void *get_dlsym(const char *symname, const char *symver);

diff --git a/libsandbox/symbols.h.in b/libsandbox/symbols.h.in
index ecf141c..297c13a 100644
--- a/libsandbox/symbols.h.in
+++ b/libsandbox/symbols.h.in
@@ -7,8 +7,10 @@
 #     before 'creat()' as 'creat()' uses 'open()' ...
 
 chmod
+fchmod
 fchmodat
 chown
+fchown
 fchownat
 open
 __open_2

diff --git a/libsandbox/trace.c b/libsandbox/trace.c
index 4ae58aa..7ac4b5d 100644
--- a/libsandbox/trace.c
+++ b/libsandbox/trace.c
@@ -390,8 +390,22 @@ static bool trace_check_syscall(const struct syscall_entry 
*se, void *regs)
                        ret = 1;
                free(path);
                return ret;
+
+       } else if (nr == SB_NR_FCHMOD) {
+               int fd = trace_arg(regs, 1);
+               mode_t mode = trace_arg(regs, 2);
+               __sb_debug("(%i, %o)", fd, mode);
+               return _SB_SAFE_FD(nr, name, fd);
+
+       } else if (nr == SB_NR_FCHOWN) {
+               int fd = trace_arg(regs, 1);
+               uid_t uid = trace_arg(regs, 2);
+               gid_t gid = trace_arg(regs, 3);
+               __sb_debug("(%i, %i, %i)", fd, uid, gid);
+               return _SB_SAFE_FD(nr, name, fd);
        }
 
+
  done:
        __sb_debug("(...)");
        return ret;

diff --git a/libsandbox/wrapper-funcs/fchmod.c 
b/libsandbox/wrapper-funcs/fchmod.c
new file mode 100644
index 0000000..04bfcea
--- /dev/null
+++ b/libsandbox/wrapper-funcs/fchmod.c
@@ -0,0 +1,11 @@
+/*
+ * fchmod() wrapper.
+ *
+ * Copyright 1999-2018 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#define WRAPPER_ARGS_PROTO int fd, mode_t mode
+#define WRAPPER_ARGS fd, mode
+#define WRAPPER_SAFE() SB_SAFE_FD(fd)
+#include "__wrapper_simple.c"

diff --git a/libsandbox/wrapper-funcs/fchown.c 
b/libsandbox/wrapper-funcs/fchown.c
new file mode 100644
index 0000000..ab79d5c
--- /dev/null
+++ b/libsandbox/wrapper-funcs/fchown.c
@@ -0,0 +1,11 @@
+/*
+ * fchown() wrapper.
+ *
+ * Copyright 1999-2018 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#define WRAPPER_ARGS_PROTO int fd, uid_t owner, gid_t group
+#define WRAPPER_ARGS fd, owner, group
+#define WRAPPER_SAFE() SB_SAFE_FD(fd)
+#include "__wrapper_simple.c"

Reply via email to