mirror of
https://github.com/systemd/systemd.git
synced 2025-03-10 16:58:28 +03:00
seccomp: also check the mode parameter of fchmodat2(2)
If there is no libseccomp support, just ban the entire syscall instead so wrappers will fall back to older, supported syscalls. Also reflect all of this in `test-seccomp.c`.
This commit is contained in:
parent
6e10405aa2
commit
8b45281daa
@ -2081,7 +2081,7 @@ int seccomp_protect_hostname(void) {
|
||||
static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
|
||||
/* Checks the mode_t parameter of the following system calls:
|
||||
*
|
||||
* → chmod() + fchmod() + fchmodat()
|
||||
* → chmod() + fchmod() + fchmodat() + fchmodat2()
|
||||
* → open() + creat() + openat()
|
||||
* → mkdir() + mkdirat()
|
||||
* → mknod() + mknodat()
|
||||
@ -2124,6 +2124,28 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
|
||||
else
|
||||
any = true;
|
||||
|
||||
#if defined(__SNR_fchmodat2)
|
||||
r = seccomp_rule_add_exact(
|
||||
seccomp,
|
||||
SCMP_ACT_ERRNO(EPERM),
|
||||
SCMP_SYS(fchmodat2),
|
||||
1,
|
||||
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
#else
|
||||
/* It looks like this libseccomp does not know about fchmodat2().
|
||||
* Pretend the fchmodat2() system call is not supported at all,
|
||||
* regardless of the kernel version. */
|
||||
r = seccomp_rule_add_exact(
|
||||
seccomp,
|
||||
SCMP_ACT_ERRNO(ENOSYS),
|
||||
__NR_fchmodat2,
|
||||
0);
|
||||
#endif
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to add filter for fchmodat2: %m");
|
||||
else
|
||||
any = true;
|
||||
|
||||
r = seccomp_rule_add_exact(
|
||||
seccomp,
|
||||
SCMP_ACT_ERRNO(EPERM),
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "macro.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_sched.h"
|
||||
#include "missing_syscall_def.h"
|
||||
#include "nsflags.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "process-util.h"
|
||||
@ -1006,6 +1007,23 @@ 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) {
|
||||
/* 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);
|
||||
/* 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
|
||||
}
|
||||
|
||||
TEST(restrict_suid_sgid) {
|
||||
pid_t pid;
|
||||
|
||||
@ -1047,6 +1065,11 @@ TEST(restrict_suid_sgid) {
|
||||
assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0);
|
||||
assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
|
||||
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0);
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0);
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0);
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755, 0) >= 0);
|
||||
|
||||
k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID);
|
||||
k = safe_close(k);
|
||||
assert_se(unlink(z) >= 0);
|
||||
@ -1148,6 +1171,11 @@ TEST(restrict_suid_sgid) {
|
||||
assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM);
|
||||
assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0);
|
||||
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM);
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM);
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM);
|
||||
assert_se(try_fchmodat2(AT_FDCWD, path, 0755, 0) >= 0);
|
||||
|
||||
assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM);
|
||||
assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM);
|
||||
assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM);
|
||||
|
Loading…
x
Reference in New Issue
Block a user