Merge pull request #12202 from keszybz/seccomp-arm64
Fixes for S[GU]ID filter on arm64
This commit is contained in:
commit
3b4ce4b08c
|
@ -1803,9 +1803,139 @@ int seccomp_protect_hostname(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
* → open() + creat() + openat()
|
||||||
|
* → mkdir() + mkdirat()
|
||||||
|
* → mknod() + mknodat()
|
||||||
|
*
|
||||||
|
* Returns error if *everything* failed, and 0 otherwise.
|
||||||
|
*/
|
||||||
|
int r = 0;
|
||||||
|
bool any = false;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(chmod),
|
||||||
|
1,
|
||||||
|
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for chmod: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(fchmod),
|
||||||
|
1,
|
||||||
|
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for fchmod: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(fchmodat),
|
||||||
|
1,
|
||||||
|
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for fchmodat: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(mkdir),
|
||||||
|
1,
|
||||||
|
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for mkdir: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(mkdirat),
|
||||||
|
1,
|
||||||
|
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for mkdirat: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(mknod),
|
||||||
|
1,
|
||||||
|
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for mknod: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(mknodat),
|
||||||
|
1,
|
||||||
|
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for mknodat: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
#if SCMP_SYS(open) > 0
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(open),
|
||||||
|
2,
|
||||||
|
SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||||
|
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for open: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(openat),
|
||||||
|
2,
|
||||||
|
SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||||
|
SCMP_A3(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for openat: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
r = seccomp_rule_add_exact(
|
||||||
|
seccomp,
|
||||||
|
SCMP_ACT_ERRNO(EPERM),
|
||||||
|
SCMP_SYS(creat),
|
||||||
|
1,
|
||||||
|
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||||
|
if (r < 0)
|
||||||
|
log_debug_errno(r, "Failed to add filter for creat: %m");
|
||||||
|
else
|
||||||
|
any = true;
|
||||||
|
|
||||||
|
return any ? 0 : r;
|
||||||
|
}
|
||||||
|
|
||||||
int seccomp_restrict_suid_sgid(void) {
|
int seccomp_restrict_suid_sgid(void) {
|
||||||
uint32_t arch;
|
uint32_t arch;
|
||||||
int r;
|
int r, k;
|
||||||
|
|
||||||
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
|
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
|
||||||
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
|
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
|
||||||
|
@ -1814,114 +1944,16 @@ int seccomp_restrict_suid_sgid(void) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Checks the mode_t parameter of the following system calls:
|
r = seccomp_restrict_sxid(seccomp, S_ISUID);
|
||||||
*
|
if (r < 0)
|
||||||
* → chmod() + fchmod() + fchmodat()
|
log_debug_errno(r, "Failed to add suid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch));
|
||||||
* → open() + creat() + openat()
|
|
||||||
* → mkdir() + mkdirat()
|
|
||||||
* → mknod() + mknodat()
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (unsigned bit = 0; bit < 2; bit ++) {
|
k = seccomp_restrict_sxid(seccomp, S_ISGID);
|
||||||
/* Block S_ISUID in the first iteration, S_ISGID in the second */
|
if (k < 0)
|
||||||
mode_t m = bit == 0 ? S_ISUID : S_ISGID;
|
log_debug_errno(r, "Failed to add sgid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch));
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
if (r < 0 && k < 0)
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(chmod),
|
|
||||||
1,
|
|
||||||
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(fchmod),
|
|
||||||
1,
|
|
||||||
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(fchmodat),
|
|
||||||
1,
|
|
||||||
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(mkdir),
|
|
||||||
1,
|
|
||||||
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(mkdirat),
|
|
||||||
1,
|
|
||||||
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(mknod),
|
|
||||||
1,
|
|
||||||
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(mknodat),
|
|
||||||
1,
|
|
||||||
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(open),
|
|
||||||
2,
|
|
||||||
SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
|
||||||
SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(openat),
|
|
||||||
2,
|
|
||||||
SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
|
||||||
SCMP_A3(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = seccomp_rule_add_exact(
|
|
||||||
seccomp,
|
|
||||||
SCMP_ACT_ERRNO(EPERM),
|
|
||||||
SCMP_SYS(creat),
|
|
||||||
1,
|
|
||||||
SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
|
||||||
if (r < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (r < 0) {
|
|
||||||
log_debug_errno(r, "Failed to add suid/sgid rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
r = seccomp_load(seccomp);
|
r = seccomp_load(seccomp);
|
||||||
if (IN_SET(r, -EPERM, -EACCES))
|
if (IN_SET(r, -EPERM, -EACCES))
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/personality.h>
|
#include <sys/personality.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -763,9 +764,14 @@ static void test_lock_personality(void) {
|
||||||
|
|
||||||
static int real_open(const char *path, int flags, mode_t mode) {
|
static int real_open(const char *path, int flags, mode_t mode) {
|
||||||
/* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for
|
/* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for
|
||||||
* testing purposes that calls the real syscall. */
|
* testing purposes that calls the real syscall, on architectures where SYS_open is defined. On
|
||||||
|
* other architectures, let's just fall back to the glibc call. */
|
||||||
|
|
||||||
|
#ifdef SYS_open
|
||||||
return (int) syscall(SYS_open, path, flags, mode);
|
return (int) syscall(SYS_open, path, flags, mode);
|
||||||
|
#else
|
||||||
|
return open(path, flags, mode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_restrict_suid_sgid(void) {
|
static void test_restrict_suid_sgid(void) {
|
||||||
|
|
Loading…
Reference in a new issue