diff options
-rw-r--r-- | man/systemd.exec.xml | 41 | ||||
-rw-r--r-- | src/shared/seccomp-util.c | 129 | ||||
-rw-r--r-- | src/test/test-seccomp.c | 33 |
3 files changed, 145 insertions, 58 deletions
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index d3a19c505d..11029ca186 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1396,28 +1396,25 @@ <varlistentry> <term><varname>SystemCallArchitectures=</varname></term> - <listitem><para>Takes a space-separated list of architecture - identifiers to include in the system call filter. The known - architecture identifiers are <constant>x86</constant>, - <constant>x86-64</constant>, <constant>x32</constant>, - <constant>arm</constant>, <constant>s390</constant>, - <constant>s390x</constant> as well as the special identifier - <constant>native</constant>. Only system calls of the - specified architectures will be permitted to processes of this - unit. This is an effective way to disable compatibility with - non-native architectures for processes, for example to - prohibit execution of 32-bit x86 binaries on 64-bit x86-64 - systems. The special <constant>native</constant> identifier - implicitly maps to the native architecture of the system (or - more strictly: to the architecture the system manager is - compiled for). If running in user mode, or in system mode, - but without the <constant>CAP_SYS_ADMIN</constant> - capability (e.g. setting <varname>User=nobody</varname>), - <varname>NoNewPrivileges=yes</varname> is implied. Note - that setting this option to a non-empty list implies that - <constant>native</constant> is included too. By default, this - option is set to the empty list, i.e. no architecture system - call filtering is applied.</para></listitem> + <listitem><para>Takes a space-separated list of architecture identifiers to + include in the system call filter. The known architecture identifiers are the same + as for <varname>ConditionArchitecture=</varname> described in + <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>, + as well as <constant>x32</constant>, <constant>mips64-n32</constant>, + <constant>mips64-le-n32</constant>, and the special identifier + <constant>native</constant>. Only system calls of the specified architectures will + be permitted to processes of this unit. This is an effective way to disable + compatibility with non-native architectures for processes, for example to prohibit + execution of 32-bit x86 binaries on 64-bit x86-64 systems. The special + <constant>native</constant> identifier implicitly maps to the native architecture + of the system (or more strictly: to the architecture the system manager is + compiled for). If running in user mode, or in system mode, but without the + <constant>CAP_SYS_ADMIN</constant> capability (e.g. setting + <varname>User=nobody</varname>), <varname>NoNewPrivileges=yes</varname> is + implied. Note that setting this option to a non-empty list implies that + <constant>native</constant> is included too. By default, this option is set to the + empty list, i.e. no architecture system call filtering is applied. + </para></listitem> </varlistentry> <varlistentry> diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 6252cd16a6..1cbbb9d757 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -29,23 +29,49 @@ #include "util.h" const char* seccomp_arch_to_string(uint32_t c) { + /* Maintain order used in <seccomp.h>. + * + * Names used here should be the same as those used for ConditionArchitecture=, + * except for "subarchitectures" like x32. */ - if (c == SCMP_ARCH_NATIVE) + switch(c) { + case SCMP_ARCH_NATIVE: return "native"; - if (c == SCMP_ARCH_X86) + case SCMP_ARCH_X86: return "x86"; - if (c == SCMP_ARCH_X86_64) + case SCMP_ARCH_X86_64: return "x86-64"; - if (c == SCMP_ARCH_X32) + case SCMP_ARCH_X32: return "x32"; - if (c == SCMP_ARCH_ARM) + case SCMP_ARCH_ARM: return "arm"; - if (c == SCMP_ARCH_S390) + case SCMP_ARCH_AARCH64: + return "arm64"; + case SCMP_ARCH_MIPS: + return "mips"; + case SCMP_ARCH_MIPS64: + return "mips64"; + case SCMP_ARCH_MIPS64N32: + return "mips64-n32"; + case SCMP_ARCH_MIPSEL: + return "mips-le"; + case SCMP_ARCH_MIPSEL64: + return "mips64-le"; + case SCMP_ARCH_MIPSEL64N32: + return "mips64-le-n32"; + case SCMP_ARCH_PPC: + return "ppc"; + case SCMP_ARCH_PPC64: + return "ppc64"; + case SCMP_ARCH_PPC64LE: + return "ppc64-le"; + case SCMP_ARCH_S390: return "s390"; - if (c == SCMP_ARCH_S390X) + case SCMP_ARCH_S390X: return "s390x"; - - return NULL; + default: + return NULL; + } } int seccomp_arch_from_string(const char *n, uint32_t *ret) { @@ -64,6 +90,26 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) { *ret = SCMP_ARCH_X32; else if (streq(n, "arm")) *ret = SCMP_ARCH_ARM; + else if (streq(n, "arm64")) + *ret = SCMP_ARCH_AARCH64; + else if (streq(n, "mips")) + *ret = SCMP_ARCH_MIPS; + else if (streq(n, "mips64")) + *ret = SCMP_ARCH_MIPS64; + else if (streq(n, "mips64-n32")) + *ret = SCMP_ARCH_MIPS64N32; + else if (streq(n, "mips-le")) + *ret = SCMP_ARCH_MIPSEL; + else if (streq(n, "mips64-le")) + *ret = SCMP_ARCH_MIPSEL64; + else if (streq(n, "mips64-le-n32")) + *ret = SCMP_ARCH_MIPSEL64N32; + else if (streq(n, "ppc")) + *ret = SCMP_ARCH_PPC; + else if (streq(n, "ppc64")) + *ret = SCMP_ARCH_PPC64; + else if (streq(n, "ppc64-le")) + *ret = SCMP_ARCH_PPC64LE; else if (streq(n, "s390")) *ret = SCMP_ARCH_S390; else if (streq(n, "s390x")) @@ -101,41 +147,52 @@ finish: return r; } -int seccomp_add_secondary_archs(scmp_filter_ctx c) { - -#if defined(__i386__) || defined(__x86_64__) - int r; +int seccomp_add_secondary_archs(scmp_filter_ctx ctx) { /* Add in all possible secondary archs we are aware of that * this kernel might support. */ - r = seccomp_arch_add(c, SCMP_ARCH_X86); - if (r < 0 && r != -EEXIST) - return r; - - r = seccomp_arch_add(c, SCMP_ARCH_X86_64); - if (r < 0 && r != -EEXIST) - return r; - - r = seccomp_arch_add(c, SCMP_ARCH_X32); - if (r < 0 && r != -EEXIST) - return r; + static const int seccomp_arches[] = { +#if defined(__i386__) || defined(__x86_64__) + SCMP_ARCH_X86, + SCMP_ARCH_X86_64, + SCMP_ARCH_X32, + +#elif defined(__arm__) || defined(__aarch64__) + SCMP_ARCH_ARM, + SCMP_ARCH_AARCH64, + +#elif defined(__arm__) || defined(__aarch64__) + SCMP_ARCH_ARM, + SCMP_ARCH_AARCH64, + +#elif defined(__mips__) || defined(__mips64__) + SCMP_ARCH_MIPS, + SCMP_ARCH_MIPS64, + SCMP_ARCH_MIPS64N32, + SCMP_ARCH_MIPSEL, + SCMP_ARCH_MIPSEL64, + SCMP_ARCH_MIPSEL64N32, + +#elif defined(__powerpc__) || defined(__powerpc64__) + SCMP_ARCH_PPC, + SCMP_ARCH_PPC64, + SCMP_ARCH_PPC64LE, #elif defined(__s390__) || defined(__s390x__) - int r; - - /* Add in all possible secondary archs we are aware of that - * this kernel might support. */ - - r = seccomp_arch_add(c, SCMP_ARCH_S390); - if (r < 0 && r != -EEXIST) - return r; + SCMP_ARCH_S390, + SCMP_ARCH_S390X, +#endif + }; - r = seccomp_arch_add(c, SCMP_ARCH_S390X); - if (r < 0 && r != -EEXIST) - return r; + unsigned i; + int r; -#endif + for (i = 0; i < ELEMENTSOF(seccomp_arches); i++) { + r = seccomp_arch_add(ctx, seccomp_arches[i]); + if (r < 0 && r != -EEXIST) + return r; + } return 0; } diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index 0060ecdf02..43d1567288 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -25,6 +25,8 @@ #include "macro.h" #include "process-util.h" #include "seccomp-util.h" +#include "string-util.h" +#include "util.h" static void test_seccomp_arch_to_string(void) { uint32_t a, b; @@ -38,6 +40,36 @@ static void test_seccomp_arch_to_string(void) { assert_se(a == b); } +static void test_architecture_table(void) { + const char *n, *n2; + + NULSTR_FOREACH(n, + "native\0" + "x86\0" + "x86-64\0" + "x32\0" + "arm\0" + "arm64\0" + "mips\0" + "mips64\0" + "mips64-n32\0" + "mips-le\0" + "mips64-le\0" + "mips64-le-n32\0" + "ppc\0" + "ppc64\0" + "ppc64-le\0" + "s390\0" + "s390x\0") { + uint32_t c; + + assert_se(seccomp_arch_from_string(n, &c) >= 0); + n2 = seccomp_arch_to_string(c); + log_info("seccomp-arch: %s → 0x%"PRIx32" → %s", n, c, n2); + assert_se(streq_ptr(n, n2)); + } +} + static void test_syscall_filter_set_find(void) { assert_se(!syscall_filter_set_find(NULL)); assert_se(!syscall_filter_set_find("")); @@ -96,6 +128,7 @@ static void test_filter_sets(void) { int main(int argc, char *argv[]) { test_seccomp_arch_to_string(); + test_architecture_table(); test_syscall_filter_set_find(); test_filter_sets(); |