aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ali Polatel <alip@exherbo.org> 2021-02-27 09:13:31 +0100
committerAvatar Ali Polatel <alip@exherbo.org> 2021-02-27 15:55:36 +0100
commitd445b411c1c1f946a79cc84fb22554dbbe91a113 (patch)
tree19d74a73b34306bc5d86f90f9d86a43a65164a23
parenta0c9fceedb390cff892327d18372cb2823cfbb7d (diff)
downloadsydbox-1-d445b411c1c1f946a79cc84fb22554dbbe91a113.tar.gz
sydbox-1-d445b411c1c1f946a79cc84fb22554dbbe91a113.tar.xz
initial support for openat2
Signed-off-by: Ali Polatel <alip@exherbo.org>
-rw-r--r--configure.ac2
-rw-r--r--src/sydbox.h2
-rw-r--r--src/syscall-file.c120
-rw-r--r--src/syscall.c5
4 files changed, 113 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac
index 18fc8da..32c1718 100644
--- a/configure.ac
+++ b/configure.ac
@@ -190,6 +190,7 @@ AC_CHECK_HEADERS_ONCE(m4_flatten([
sys/wait.h
asm/ptrace.h
linux/ptrace.h
+ linux/openat2.h
]))
dnl check for types
@@ -203,6 +204,7 @@ AC_CHECK_TYPES([ptrdiff_t])
AC_CHECK_TYPES([struct pt_all_user_regs, struct ia64_fpreg, struct ptrace_peeksiginfo_args],,,[#include <sys/ptrace.h>])
AC_CHECK_TYPES([sig_atomic_t], [], AC_MSG_ERROR([I need sigatomic_t]), [#include <signal.h>])
AC_CHECK_TYPES([sighandler_t, sig_t, __sighandler_t],,,[#include <signal.h>])
+AC_CHECK_TYPES([struct open_how],,,[#include <linux/openat2.h>])
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="-I$srcdir/t $CPPFLAGS"
diff --git a/src/sydbox.h b/src/sydbox.h
index 8c8da80..a75d0e5 100644
--- a/src/sydbox.h
+++ b/src/sydbox.h
@@ -875,6 +875,7 @@ int sys_fallback_mmap(syd_process_t *current);
int sys_access(syd_process_t *current);
int sys_faccessat(syd_process_t *current);
+int sys_faccessat2(syd_process_t *current);
int sys_chmod(syd_process_t *current);
int sys_fchmodat(syd_process_t *current);
@@ -883,6 +884,7 @@ int sys_lchown(syd_process_t *current);
int sys_fchownat(syd_process_t *current);
int sys_open(syd_process_t *current);
int sys_openat(syd_process_t *current);
+int sys_openat2(syd_process_t *current);
int sys_creat(syd_process_t *current);
int sys_close(syd_process_t *current);
int sysx_close(syd_process_t *current);
diff --git a/src/syscall-file.c b/src/syscall-file.c
index e54f338..a735a16 100644
--- a/src/syscall-file.c
+++ b/src/syscall-file.c
@@ -20,6 +20,19 @@
#include "bsd-compat.h"
#include "sockmap.h"
+#if defined(HAVE_LINUX_OPENAT2_H) && defined(HAVE_STRUCT_OPEN_HOW)
+# include <linux/openat2.h>
+#else
+struct open_how {
+ unsigned long flags;
+ unsigned long mode;
+ unsigned long resolve;
+};
+#define RESOLVE_NO_MAGICLINKS 0x02
+#define RESOLVE_NO_SYMLINKS 0x04
+#define RESOLVE_BENEATH 0x08
+#endif
+
struct open_info {
bool may_read;
bool may_write;
@@ -151,14 +164,16 @@ int sys_faccessat2(syd_process_t *current)
}
/* TODO: Do we need to care about O_PATH? */
-static void init_open_info(syd_process_t *current, int flags, struct open_info *info)
+static void init_open_info(syd_process_t *current,
+ const struct open_how *how,
+ struct open_info *info)
{
assert(current);
assert(info);
- info->rmode = flags & O_CREAT ? RPATH_NOLAST : RPATH_EXIST;
+ info->rmode = how->flags & O_CREAT ? RPATH_NOLAST : RPATH_EXIST;
info->syd_mode = 0;
- if (flags & O_EXCL) {
+ if (how->flags & O_EXCL) {
if (info->rmode == RPATH_EXIST) {
/* Quoting open(2):
* In general, the behavior of O_EXCL is undefined if
@@ -182,20 +197,29 @@ static void init_open_info(syd_process_t *current, int flags, struct open_info *
}
}
- if (flags & O_DIRECTORY)
+ if (how->flags & O_DIRECTORY)
info->syd_mode |= SYD_STAT_ISDIR;
- if (flags & O_NOFOLLOW)
+ if (how->flags & O_NOFOLLOW)
info->syd_mode |= SYD_STAT_NOFOLLOW;
+ /*
+ * TODO: We treat these three flags as identical for simplicity, however
+ * this is not exactly compliant with the way the syscall functions.
+ */
+ if ((how->resolve & RESOLVE_BENEATH) ||
+ (how->resolve & RESOLVE_NO_SYMLINKS) ||
+ (how->resolve & RESOLVE_NO_MAGICLINKS))
+ info->rmode |= RPATH_NOFOLLOW;
+ /* TODO: Do we want to support RESOLVE_NO_XDEV and RESOLVE_IN_ROOT? */
/* `unsafe' flag combinations:
* - O_RDONLY | O_CREAT
* - O_WRONLY
* - O_RDWR
*/
- switch (flags & O_ACCMODE) {
+ switch (how->flags & O_ACCMODE) {
case O_RDONLY:
info->may_read = true;
- if (flags & O_CREAT) {
+ if (how->flags & O_CREAT) {
/* file creation is `write' */
info->may_write = true;
} else {
@@ -253,7 +277,7 @@ out:
return r;
}
-static int restrict_open_flags(syd_process_t *current, int flags)
+static int restrict_open_flags(syd_process_t *current, unsigned long flags)
{
if (!sydbox->config.use_seccomp &&
sydbox->config.restrict_file_control &&
@@ -265,7 +289,8 @@ static int restrict_open_flags(syd_process_t *current, int flags)
int sys_open(syd_process_t *current)
{
bool strict;
- int r, flags;
+ int r;
+ struct open_how how;
sysinfo_t info;
struct open_info open_info;
@@ -276,15 +301,17 @@ int sys_open(syd_process_t *current)
return 0;
/* check flags first */
- if ((r = syd_read_argument_int(current, 1, &flags)) < 0)
+ if ((r = syd_read_argument(current, 1, (long *)&how.flags)) < 0)
return r;
- if ((r = restrict_open_flags(current, flags)) < 0)
+ if ((r = restrict_open_flags(current, how.flags)) < 0)
return r;
if (sandbox_off_read(current) && sandbox_off_write(current))
return 0;
- init_open_info(current, flags, &open_info);
+ how.mode = 0;
+ how.resolve = 0;
+ init_open_info(current, &how, &open_info);
init_sysinfo(&info);
info.rmode = open_info.rmode;
info.syd_mode = open_info.syd_mode;
@@ -295,7 +322,8 @@ int sys_open(syd_process_t *current)
int sys_openat(syd_process_t *current)
{
bool strict;
- int r, flags;
+ int r;
+ struct open_how how;
sysinfo_t info;
struct open_info open_info;
@@ -306,15 +334,17 @@ int sys_openat(syd_process_t *current)
return 0;
/* check flags first */
- if ((r = syd_read_argument_int(current, 2, &flags)) < 0)
+ if ((r = syd_read_argument(current, 2, (long *)&how.flags)) < 0)
return r;
- if ((r = restrict_open_flags(current, flags)) < 0)
+ if ((r = restrict_open_flags(current, how.flags)) < 0)
return r;
if (sandbox_off_read(current) && sandbox_off_write(current))
return 0;
- init_open_info(current, flags, &open_info);
+ how.mode = 0;
+ how.resolve = 0;
+ init_open_info(current, &how, &open_info);
init_sysinfo(&info);
info.at_func = true;
info.arg_index = 1;
@@ -324,6 +354,64 @@ int sys_openat(syd_process_t *current)
return check_open(current, &info, &open_info);
}
+#if defined(HAVE_LINUX_OPENAT2_H) && defined(HAVE_STRUCT_OPEN_HOW)
+int sys_openat2(syd_process_t *current)
+{
+ bool strict;
+ int r;
+ sysinfo_t info;
+ struct open_info open_info;
+
+ strict = !sydbox->config.use_seccomp &&
+ sydbox->config.restrict_file_control;
+
+ if (!strict && sandbox_off_read(current) && sandbox_off_write(current))
+ return 0;
+
+ enum { OPEN_HOW_MIN_SIZE = 24 };
+ struct open_how how;
+ long addr, size;
+
+ if ((r = syd_read_argument(current, 2, &addr)) < 0 ||
+ (r = syd_read_argument(current, 3, &size)) < 0)
+ return r;
+
+ if (size < OPEN_HOW_MIN_SIZE) {
+ how.flags = 0;
+ how.mode = 0;
+ how.resolve = 0;
+ } else if ((r = pink_read_vm_data(current->pid, current->regset,
+ addr, (char *)&how, size)) < 0) {
+ return r;
+ } else if ((r = restrict_open_flags(current, how.flags)) < 0) {
+ return r;
+ }
+
+ if (sandbox_off_read(current) && sandbox_off_write(current))
+ return 0;
+
+ init_open_info(current, &how, &open_info);
+ init_sysinfo(&info);
+ info.at_func = true;
+ info.arg_index = 1;
+ info.rmode = open_info.rmode;
+ info.syd_mode = open_info.syd_mode;
+
+ return check_open(current, &info, &open_info);
+}
+#else
+int sys_openat2(syd_process_t *current)
+{
+ /*
+ * This can happen if buildhost did not have support for openat2.
+ */
+#warning "No support for openat2(), sydbox will deny the system call unconditionally."
+#warning "This won't be an issue unless you run sydbox on a system running a Linux kernel 5.6 or newer."
+#warning "If this is the case, please update your kernel and kernel headers as necessary and rebuild sydbox."
+ return deny(current, ENOTSUP);
+}
+#endif
+
int sys_chmod(syd_process_t *current)
{
sysinfo_t info;
diff --git a/src/syscall.c b/src/syscall.c
index 8c6aefe..caa6279 100644
--- a/src/syscall.c
+++ b/src/syscall.c
@@ -94,6 +94,11 @@ static const sysentry_t syscall_entries[] = {
.enter = sys_openat,
},
{
+ .name = "openat2",
+ .enter = sys_openat2,
+ },
+
+ {
.name = "creat",
.enter = sys_creat,
},