]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
seccomp: Implement MIPS seccomp handling
authorJames Cowgill <james410@cowgill.org.uk>
Mon, 15 Aug 2016 16:09:44 +0000 (16:09 +0000)
committerStéphane Graber <stgraber@ubuntu.com>
Thu, 17 Nov 2016 23:31:44 +0000 (18:31 -0500)
MIPS processors implement 3 ABIs: o32, n64 and n32 (similar to x32). The kernel
treats each ABI separately so syscalls disallowed on "all" arches should be
added to all three seccomp sets. This is implemented by expanding compat_arch
and compat_ctx to accept two compat architectures.

After this, the MIPS hostarch detection code and config section code is added.

Signed-off-by: James Cowgill <james410@cowgill.org.uk>
src/lxc/seccomp.c

index 451e31572ff8ce9b7df01cc61744e54906b6b778..0374eca05a857130c8500e40b12ad6d3e6b5f3bc 100644 (file)
@@ -125,9 +125,23 @@ enum lxc_hostarch_t {
        lxc_seccomp_arch_ppc64,
        lxc_seccomp_arch_ppc64le,
        lxc_seccomp_arch_ppc,
+       lxc_seccomp_arch_mips,
+       lxc_seccomp_arch_mips64,
+       lxc_seccomp_arch_mips64n32,
+       lxc_seccomp_arch_mipsel,
+       lxc_seccomp_arch_mipsel64,
+       lxc_seccomp_arch_mipsel64n32,
        lxc_seccomp_arch_unknown = 999,
 };
 
+#ifdef __MIPSEL__
+# define MIPS_ARCH_O32 lxc_seccomp_arch_mipsel
+# define MIPS_ARCH_N64 lxc_seccomp_arch_mipsel64
+#else
+# define MIPS_ARCH_O32 lxc_seccomp_arch_mips
+# define MIPS_ARCH_N64 lxc_seccomp_arch_mips64
+#endif
+
 int get_hostarch(void)
 {
        struct utsname uts;
@@ -149,6 +163,10 @@ int get_hostarch(void)
                return lxc_seccomp_arch_ppc64;
        else if (strncmp(uts.machine, "ppc", 3) == 0)
                return lxc_seccomp_arch_ppc;
+       else if (strncmp(uts.machine, "mips64", 6) == 0)
+               return MIPS_ARCH_N64;
+       else if (strncmp(uts.machine, "mips", 4) == 0)
+               return MIPS_ARCH_O32;
        return lxc_seccomp_arch_unknown;
 }
 
@@ -173,6 +191,14 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_
 #endif
 #ifdef SCMP_ARCH_PPC
        case lxc_seccomp_arch_ppc: arch = SCMP_ARCH_PPC; break;
+#endif
+#ifdef SCMP_ARCH_MIPS
+       case lxc_seccomp_arch_mips: arch = SCMP_ARCH_MIPS; break;
+       case lxc_seccomp_arch_mips64: arch = SCMP_ARCH_MIPS64; break;
+       case lxc_seccomp_arch_mips64n32: arch = SCMP_ARCH_MIPS64N32; break;
+       case lxc_seccomp_arch_mipsel: arch = SCMP_ARCH_MIPSEL; break;
+       case lxc_seccomp_arch_mipsel64: arch = SCMP_ARCH_MIPSEL64; break;
+       case lxc_seccomp_arch_mipsel64n32: arch = SCMP_ARCH_MIPSEL64N32; break;
 #endif
        default: return NULL;
        }
@@ -260,12 +286,12 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 {
        char *p;
        int ret;
-       scmp_filter_ctx compat_ctx = NULL;
+       scmp_filter_ctx compat_ctx[2] = { NULL, NULL };
        bool blacklist = false;
        uint32_t default_policy_action = -1, default_rule_action = -1, action;
        enum lxc_hostarch_t native_arch = get_hostarch(),
                            cur_rule_arch = native_arch;
-       uint32_t compat_arch = SCMP_ARCH_NATIVE;
+       uint32_t compat_arch[2] = { SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE };
 
        if (strncmp(line, "blacklist", 9) == 0)
                blacklist = true;
@@ -295,27 +321,49 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 
        if (native_arch == lxc_seccomp_arch_amd64) {
                cur_rule_arch = lxc_seccomp_arch_all;
-               compat_arch = SCMP_ARCH_X86;
-               compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
+               compat_arch[0] = SCMP_ARCH_X86;
+               compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_i386,
                                default_policy_action);
-               if (!compat_ctx)
+               if (!compat_ctx[0])
                        goto bad;
 #ifdef SCMP_ARCH_PPC
        } else if (native_arch == lxc_seccomp_arch_ppc64) {
                cur_rule_arch = lxc_seccomp_arch_all;
-               compat_arch = SCMP_ARCH_PPC;
-               compat_ctx = get_new_ctx(lxc_seccomp_arch_ppc,
+               compat_arch[0] = SCMP_ARCH_PPC;
+               compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_ppc,
                                default_policy_action);
-               if (!compat_ctx)
+               if (!compat_ctx[0])
                        goto bad;
 #endif
 #ifdef SCMP_ARCH_ARM
        } else if (native_arch == lxc_seccomp_arch_arm64) {
                cur_rule_arch = lxc_seccomp_arch_all;
-               compat_arch = SCMP_ARCH_ARM;
-               compat_ctx = get_new_ctx(lxc_seccomp_arch_arm,
+               compat_arch[0] = SCMP_ARCH_ARM;
+               compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_arm,
+                               default_policy_action);
+               if (!compat_ctx[0])
+                       goto bad;
+#endif
+#ifdef SCMP_ARCH_MIPS
+       } else if (native_arch == lxc_seccomp_arch_mips64) {
+               cur_rule_arch = lxc_seccomp_arch_all;
+               compat_arch[0] = SCMP_ARCH_MIPS;
+               compat_arch[1] = SCMP_ARCH_MIPS64N32;
+               compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_mips,
+                               default_policy_action);
+               compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_mips64n32,
+                               default_policy_action);
+               if (!compat_ctx[0] || !compat_ctx[1])
+                       goto bad;
+       } else if (native_arch == lxc_seccomp_arch_mipsel64) {
+               cur_rule_arch = lxc_seccomp_arch_all;
+               compat_arch[0] = SCMP_ARCH_MIPSEL;
+               compat_arch[1] = SCMP_ARCH_MIPSEL64N32;
+               compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_mipsel,
                                default_policy_action);
-               if (!compat_ctx)
+               compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32,
+                               default_policy_action);
+               if (!compat_ctx[0] || !compat_ctx[1])
                        goto bad;
 #endif
        }
@@ -412,6 +460,53 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
                                }
                                cur_rule_arch = lxc_seccomp_arch_ppc;
                        }
+#endif
+#ifdef SCMP_ARCH_MIPS
+                       else if (strcmp(line, "[mips64]") == 0 ||
+                                       strcmp(line, "[MIPS64]") == 0) {
+                               if (native_arch != lxc_seccomp_arch_mips64) {
+                                       cur_rule_arch = lxc_seccomp_arch_unknown;
+                                       continue;
+                               }
+                               cur_rule_arch = lxc_seccomp_arch_mips64;
+                       } else if (strcmp(line, "[mips64n32]") == 0 ||
+                                       strcmp(line, "[MIPS64N32]") == 0) {
+                               if (native_arch != lxc_seccomp_arch_mips64) {
+                                       cur_rule_arch = lxc_seccomp_arch_unknown;
+                                       continue;
+                               }
+                               cur_rule_arch = lxc_seccomp_arch_mips64n32;
+                       } else if (strcmp(line, "[mips]") == 0 ||
+                                       strcmp(line, "[MIPS]") == 0) {
+                               if (native_arch != lxc_seccomp_arch_mips &&
+                                               native_arch != lxc_seccomp_arch_mips64) {
+                                       cur_rule_arch = lxc_seccomp_arch_unknown;
+                                       continue;
+                               }
+                               cur_rule_arch = lxc_seccomp_arch_mips;
+                       } else if (strcmp(line, "[mipsel64]") == 0 ||
+                                       strcmp(line, "[MIPSEL64]") == 0) {
+                               if (native_arch != lxc_seccomp_arch_mipsel64) {
+                                       cur_rule_arch = lxc_seccomp_arch_unknown;
+                                       continue;
+                               }
+                               cur_rule_arch = lxc_seccomp_arch_mipsel64;
+                       } else if (strcmp(line, "[mipsel64n32]") == 0 ||
+                                       strcmp(line, "[MIPSEL64N32]") == 0) {
+                               if (native_arch != lxc_seccomp_arch_mipsel64) {
+                                       cur_rule_arch = lxc_seccomp_arch_unknown;
+                                       continue;
+                               }
+                               cur_rule_arch = lxc_seccomp_arch_mipsel64n32;
+                       } else if (strcmp(line, "[mipsel]") == 0 ||
+                                       strcmp(line, "[MIPSEL]") == 0) {
+                               if (native_arch != lxc_seccomp_arch_mipsel &&
+                                               native_arch != lxc_seccomp_arch_mipsel64) {
+                                       cur_rule_arch = lxc_seccomp_arch_unknown;
+                                       continue;
+                               }
+                               cur_rule_arch = lxc_seccomp_arch_mipsel;
+                       }
 #endif
                        else
                                goto bad_arch;
@@ -432,14 +527,18 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 
                if (cur_rule_arch == native_arch ||
                    cur_rule_arch == lxc_seccomp_arch_native ||
-                   compat_arch == SCMP_ARCH_NATIVE) {
+                   compat_arch[0] == SCMP_ARCH_NATIVE) {
                        INFO("Adding native rule for %s action %d", line, action);
                        if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
                                goto bad_rule;
                }
                else if (cur_rule_arch != lxc_seccomp_arch_all) {
+                       int arch_index =
+                               cur_rule_arch == lxc_seccomp_arch_mips64n32 ||
+                               cur_rule_arch == lxc_seccomp_arch_mipsel64n32 ? 1 : 0;
+
                        INFO("Adding compat-only rule for %s action %d", line, action);
-                       if (!do_resolve_add_rule(compat_arch, line, compat_ctx, action))
+                       if (!do_resolve_add_rule(compat_arch[arch_index], line, compat_ctx[arch_index], action))
                                goto bad_rule;
                }
                else {
@@ -447,14 +546,18 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
                        if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
                                goto bad_rule;
                        INFO("Adding compat rule for %s action %d", line, action);
-                       if (!do_resolve_add_rule(compat_arch, line, compat_ctx, action))
+                       if (!do_resolve_add_rule(compat_arch[0], line, compat_ctx[0], action))
+                               goto bad_rule;
+                       if (compat_arch[1] != SCMP_ARCH_NATIVE &&
+                               !do_resolve_add_rule(compat_arch[1], line, compat_ctx[1], action))
                                goto bad_rule;
                }
        }
 
-       if (compat_ctx) {
+       if (compat_ctx[0]) {
                INFO("Merging in the compat seccomp ctx into the main one");
-               if (seccomp_merge(conf->seccomp_ctx, compat_ctx) != 0) {
+               if (seccomp_merge(conf->seccomp_ctx, compat_ctx[0]) != 0 ||
+                       (compat_ctx[1] != NULL && seccomp_merge(conf->seccomp_ctx, compat_ctx[1]) != 0)) {
                        ERROR("Error merging compat seccomp contexts");
                        goto bad;
                }
@@ -466,8 +569,10 @@ bad_arch:
        ERROR("Unsupported arch: %s", line);
 bad_rule:
 bad:
-       if (compat_ctx)
-               seccomp_release(compat_ctx);
+       if (compat_ctx[0])
+               seccomp_release(compat_ctx[0]);
+       if (compat_ctx[1])
+               seccomp_release(compat_ctx[1]);
        return -1;
 }
 #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */