From c21566d90b691e966f6dce9161031198d4888ad3 Mon Sep 17 00:00:00 2001 From: Arseny Maslennikov Date: Fri, 20 Oct 2023 14:22:50 +0300 Subject: [PATCH] basic/missing_syscall: add missing_fchmodat2() Follow-up for 8b45281daa3a87b4b7a3248263cd0ba929d15596 and preparation for later commits. Since libcs are more interested in the POSIX `fchmodat(3)`, they are unlikely to provide a direct wrapper for this syscall. Thus, the headers we examine to set `HAVE_*` are picked somewhat arbitrarily. Also, hook up `try_fchmodat2()` in `test-seccomp.c`. (Also, correct that function's prototype, despite the fact that mistake would not matter in practice) Co-authored-by: Mike Yuan --- meson.build | 2 ++ src/basic/missing_syscall.h | 15 +++++++++++++++ src/test/test-seccomp.c | 23 ++++++++++++----------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/meson.build b/meson.build index 7f5d465783b..4f50b32cdf6 100644 --- a/meson.build +++ b/meson.build @@ -568,6 +568,8 @@ foreach ident : [ ['memfd_create', '''#include '''], ['gettid', '''#include #include '''], + ['fchmodat2', '''#include + #include '''], # no known header declares fchmodat2 ['pivot_root', '''#include #include '''], # no known header declares pivot_root ['ioprio_get', '''#include '''], # no known header declares ioprio_get diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index 83ec137fa59..d795efd8f28 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -32,6 +32,21 @@ /* ======================================================================= */ +#if !HAVE_FCHMODAT2 +static inline int missing_fchmodat2(int dirfd, const char *path, mode_t mode, int flags) { +# ifdef __NR_fchmodat2 + return syscall(__NR_fchmodat2, dirfd, path, mode, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define fchmodat2 missing_fchmodat2 +#endif + +/* ======================================================================= */ + #if !HAVE_PIVOT_ROOT static inline int missing_pivot_root(const char *new_root, const char *put_old) { return syscall(__NR_pivot_root, new_root, put_old); diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index 56c4b3fd872..279a155cb0a 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -21,7 +21,7 @@ #include "macro.h" #include "memory-util.h" #include "missing_sched.h" -#include "missing_syscall_def.h" +#include "missing_syscall.h" #include "nsflags.h" #include "nulstr-util.h" #include "process-util.h" @@ -1007,21 +1007,22 @@ static int real_open(const char *path, int flags, mode_t mode) { #endif } -static int try_fchmodat2(int dirfd, const char *path, int flags, mode_t mode) { +static int try_fchmodat2(int dirfd, const char *path, mode_t mode, int flags) { + int r; + /* glibc does not provide a direct wrapper for fchmodat2(). Let's hence define our own wrapper for * testing purposes that calls the real syscall, on architectures and in environments where * SYS_fchmodat2 is defined. Otherwise, let's just fall back to the glibc fchmodat() call. */ -#if defined __NR_fchmodat2 && __NR_fchmodat2 >= 0 - int r; - r = (int) syscall(__NR_fchmodat2, dirfd, path, flags, mode); + /* Not supported by fchmodat() */ + assert_se(!FLAGS_SET(flags, AT_EMPTY_PATH)); + + r = RET_NERRNO(fchmodat2(dirfd, path, mode, flags)); + if (r != -ENOSYS) + return r; + /* The syscall might still be unsupported by kernel or libseccomp. */ - if (r < 0 && errno == ENOSYS) - return fchmodat(dirfd, path, flags, mode); - return r; -#else - return fchmodat(dirfd, path, flags, mode); -#endif + return RET_NERRNO(fchmodat(dirfd, path, mode, flags)); } TEST(restrict_suid_sgid) {