From d648e178f1b3fa9f261b890157d2ee6e9e5e14fa Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 15 Apr 2018 22:12:51 +0200 Subject: [PATCH 1/5] seccomp: cleanup compat architecture handling Signed-off-by: Christian Brauner --- src/lxc/seccomp.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index 60118852d..6a4f474c8 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -789,24 +789,36 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) } } + INFO("Merging compat seccomp contexts into main context"); if (compat_ctx[0]) { - INFO("Merging compat seccomp contexts into main context"); - if (compat_arch[0] != native_arch && compat_arch[0] != seccomp_arch_native()) { + if ((compat_arch[0] != native_arch) && + (compat_arch[0] != seccomp_arch_native())) { ret = seccomp_merge(conf->seccomp_ctx, compat_ctx[0]); if (ret < 0) { - ERROR("Failed to merge first compat seccomp context into main context"); + ERROR("Failed to merge first compat seccomp " + "context into main context"); goto bad; } TRACE("Merged first compat seccomp context into main context"); + } else { + seccomp_release(compat_ctx[0]); + compat_ctx[0] = NULL; } + } - if (compat_arch[1] && compat_arch[1] != native_arch && compat_arch[1] != seccomp_arch_native()) { + if (compat_ctx[1]) { + if ((compat_arch[1] != native_arch) && + (compat_arch[1] != seccomp_arch_native())) { ret = seccomp_merge(conf->seccomp_ctx, compat_ctx[1]); if (ret < 0) { - ERROR("Failed to merge first compat seccomp context into main context"); + ERROR("Failed to merge first compat seccomp " + "context into main context"); goto bad; } TRACE("Merged second compat seccomp context into main context"); + } else { + seccomp_release(compat_ctx[1]); + compat_ctx[1] = NULL; } } From 94d56054143a8634852989819acee06bf4aaf9f9 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 15 Apr 2018 22:39:07 +0200 Subject: [PATCH 2/5] seccomp: improve logging Signed-off-by: Christian Brauner --- src/lxc/seccomp.c | 48 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index 6a4f474c8..084419772 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -759,33 +759,45 @@ 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[0] == SCMP_ARCH_NATIVE) { - INFO("Adding native rule for %s action %d(%s)", line, rule.action, - get_action_name(rule.action)); if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, &rule)) 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(%s)", line, rule.action, + INFO("Added native rule for arch %d for %s action %d(%s)", + SCMP_ARCH_NATIVE, line, rule.action, get_action_name(rule.action)); + } else if (cur_rule_arch != lxc_seccomp_arch_all) { + int arch_index = 0; + + if ((cur_rule_arch == lxc_seccomp_arch_mips64n32) || + (cur_rule_arch == lxc_seccomp_arch_mipsel64n32)) + arch_index = 1; + if (!do_resolve_add_rule(compat_arch[arch_index], line, compat_ctx[arch_index], &rule)) goto bad_rule; - } - else { - INFO("Adding native rule for %s action %d(%s)", line, rule.action, + INFO("Added compat-only rule for arch %d for %s action %d(%s)", + compat_arch[arch_index], line, rule.action, get_action_name(rule.action)); + } else { if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, &rule)) goto bad_rule; - INFO("Adding compat rule for %s action %d(%s)", line, rule.action, + INFO("Added native rule for arch %d for %s action %d(%s)", + SCMP_ARCH_NATIVE, line, rule.action, get_action_name(rule.action)); - if (!do_resolve_add_rule(compat_arch[0], line, compat_ctx[0], &rule)) - goto bad_rule; - if (compat_arch[1] != SCMP_ARCH_NATIVE && - !do_resolve_add_rule(compat_arch[1], line, compat_ctx[1], &rule)) - goto bad_rule; + + if (compat_arch[0] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(compat_arch[0], line, compat_ctx[0], &rule)) + goto bad_rule; + INFO("Added compat rule for arch %d for %s " + "action %d(%s)", compat_arch[0], line, + rule.action, get_action_name(rule.action)); + } + + if (compat_arch[1] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(compat_arch[1], line, compat_ctx[1], &rule)) + goto bad_rule; + INFO("Added compat rule for arch %d for %s " + "action %d(%s)", compat_arch[1], line, + rule.action, get_action_name(rule.action)); + } } } From 4160ef02e5bbabbf4f3d0ab002aa8afba4f680a1 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 15 Apr 2018 22:42:43 +0200 Subject: [PATCH 3/5] tools: document -d/--daemonize for lxc-execute Closes #2280. Signed-off-by: Christian Brauner --- doc/lxc-execute.sgml.in | 15 +++++++++++++++ src/lxc/tools/lxc_execute.c | 1 + 2 files changed, 16 insertions(+) diff --git a/doc/lxc-execute.sgml.in b/doc/lxc-execute.sgml.in index 4ec7c1b94..20814348d 100644 --- a/doc/lxc-execute.sgml.in +++ b/doc/lxc-execute.sgml.in @@ -50,6 +50,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA lxc-execute -n name + -d -f config_file -s KEY=VAL -- command @@ -124,6 +125,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + + + + + + Run the container as a daemon. As the container has no + more tty, if an error occurs nothing will be displayed, + the log file can be used to check the error. + + + + diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c index 5291dd7a3..5c03b498b 100644 --- a/src/lxc/tools/lxc_execute.c +++ b/src/lxc/tools/lxc_execute.c @@ -104,6 +104,7 @@ and execs COMMAND into this container.\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ + -d, --daemon Daemonize the container\n\ -f, --rcfile=FILE Load configuration file FILE\n\ -s, --define KEY=VAL Assign VAL to configuration variable KEY\n\ -u, --uid=UID Execute COMMAND with UID inside the container\n\ From 7e84441ec3f973609bc2462528d55888ab1a084f Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 18 Apr 2018 14:40:49 +0200 Subject: [PATCH 4/5] seccomp: non-functional changes Rename "compat_ctx" to "contexts" and "compat_arch" to "architectures". Signed-off-by: Christian Brauner --- src/lxc/seccomp.c | 139 +++++++++++++++++++++-------------------- src/tests/api_reboot.c | 1 - 2 files changed, 72 insertions(+), 68 deletions(-) diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index 084419772..40922a1b9 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -490,12 +490,12 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) { char *p; int ret; - scmp_filter_ctx compat_ctx[2] = {NULL, NULL}; + scmp_filter_ctx contexts[3] = {NULL, NULL}; bool blacklist = false; uint32_t default_policy_action = -1, default_rule_action = -1; enum lxc_hostarch_t native_arch = get_hostarch(), cur_rule_arch = native_arch; - uint32_t compat_arch[2] = {SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE}; + uint32_t architectures[2] = {SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE}; struct seccomp_v2_rule rule; if (strncmp(line, "blacklist", 9) == 0) @@ -526,52 +526,52 @@ 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[0] = SCMP_ARCH_X86; - compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_i386, - default_policy_action); - compat_arch[1] = SCMP_ARCH_X32; - compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_x32, - default_policy_action); - if (!compat_ctx[0] || !compat_ctx[1]) + architectures[0] = SCMP_ARCH_X86; + contexts[0] = get_new_ctx(lxc_seccomp_arch_i386, + default_policy_action); + architectures[1] = SCMP_ARCH_X32; + contexts[1] = get_new_ctx(lxc_seccomp_arch_x32, + default_policy_action); + if (!contexts[0] || !contexts[1]) goto bad; #ifdef SCMP_ARCH_PPC } else if (native_arch == lxc_seccomp_arch_ppc64) { cur_rule_arch = lxc_seccomp_arch_all; - compat_arch[0] = SCMP_ARCH_PPC; - compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_ppc, - default_policy_action); - if (!compat_ctx[0]) + architectures[0] = SCMP_ARCH_PPC; + contexts[0] = get_new_ctx(lxc_seccomp_arch_ppc, + default_policy_action); + if (!contexts[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[0] = SCMP_ARCH_ARM; - compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_arm, - default_policy_action); - if (!compat_ctx[0]) + architectures[0] = SCMP_ARCH_ARM; + contexts[0] = get_new_ctx(lxc_seccomp_arch_arm, + default_policy_action); + if (!contexts[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]) + architectures[0] = SCMP_ARCH_MIPS; + architectures[1] = SCMP_ARCH_MIPS64N32; + contexts[0] = get_new_ctx(lxc_seccomp_arch_mips, + default_policy_action); + contexts[1] = get_new_ctx(lxc_seccomp_arch_mips64n32, + default_policy_action); + if (!contexts[0] || !contexts[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); - compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, - default_policy_action); - if (!compat_ctx[0] || !compat_ctx[1]) + architectures[0] = SCMP_ARCH_MIPSEL; + architectures[1] = SCMP_ARCH_MIPSEL64N32; + contexts[0] = get_new_ctx(lxc_seccomp_arch_mipsel, + default_policy_action); + contexts[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, + default_policy_action); + if (!contexts[0] || !contexts[1]) goto bad; #endif } @@ -606,7 +606,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) if (strcmp(line, "[x86]") == 0 || strcmp(line, "[X86]") == 0) { if (native_arch != lxc_seccomp_arch_i386 && - native_arch != lxc_seccomp_arch_amd64) { + native_arch != lxc_seccomp_arch_amd64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } @@ -633,7 +633,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) else if (strcmp(line, "[arm]") == 0 || strcmp(line, "[ARM]") == 0) { if (native_arch != lxc_seccomp_arch_arm && - native_arch != lxc_seccomp_arch_arm64) { + native_arch != lxc_seccomp_arch_arm64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } @@ -674,7 +674,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) else if (strcmp(line, "[ppc]") == 0 || strcmp(line, "[PPC]") == 0) { if (native_arch != lxc_seccomp_arch_ppc && - native_arch != lxc_seccomp_arch_ppc64) { + native_arch != lxc_seccomp_arch_ppc64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } @@ -699,7 +699,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) } else if (strcmp(line, "[mips]") == 0 || strcmp(line, "[MIPS]") == 0) { if (native_arch != lxc_seccomp_arch_mips && - native_arch != lxc_seccomp_arch_mips64) { + native_arch != lxc_seccomp_arch_mips64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } @@ -721,7 +721,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) } else if (strcmp(line, "[mipsel]") == 0 || strcmp(line, "[MIPSEL]") == 0) { if (native_arch != lxc_seccomp_arch_mipsel && - native_arch != lxc_seccomp_arch_mipsel64) { + native_arch != lxc_seccomp_arch_mipsel64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } @@ -758,8 +758,9 @@ 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[0] == SCMP_ARCH_NATIVE) { - if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, &rule)) + architectures[0] == SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, + conf->seccomp_ctx, &rule)) goto bad_rule; INFO("Added native rule for arch %d for %s action %d(%s)", SCMP_ARCH_NATIVE, line, rule.action, @@ -771,41 +772,45 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) (cur_rule_arch == lxc_seccomp_arch_mipsel64n32)) arch_index = 1; - if (!do_resolve_add_rule(compat_arch[arch_index], line, compat_ctx[arch_index], &rule)) + if (!do_resolve_add_rule(architectures[arch_index], line, + contexts[arch_index], &rule)) goto bad_rule; INFO("Added compat-only rule for arch %d for %s action %d(%s)", - compat_arch[arch_index], line, rule.action, + architectures[arch_index], line, rule.action, get_action_name(rule.action)); } else { - if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, &rule)) + if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, + conf->seccomp_ctx, &rule)) goto bad_rule; INFO("Added native rule for arch %d for %s action %d(%s)", SCMP_ARCH_NATIVE, line, rule.action, get_action_name(rule.action)); - if (compat_arch[0] != SCMP_ARCH_NATIVE) { - if (!do_resolve_add_rule(compat_arch[0], line, compat_ctx[0], &rule)) + if (architectures[0] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(architectures[0], line, + contexts[0], &rule)) goto bad_rule; - INFO("Added compat rule for arch %d for %s " - "action %d(%s)", compat_arch[0], line, - rule.action, get_action_name(rule.action)); + INFO("Added compat rule for arch %d for %s action %d(%s)", + architectures[0], line, rule.action, + get_action_name(rule.action)); } - if (compat_arch[1] != SCMP_ARCH_NATIVE) { - if (!do_resolve_add_rule(compat_arch[1], line, compat_ctx[1], &rule)) + if (architectures[1] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(architectures[1], line, + contexts[1], &rule)) goto bad_rule; - INFO("Added compat rule for arch %d for %s " - "action %d(%s)", compat_arch[1], line, - rule.action, get_action_name(rule.action)); + INFO("Added compat rule for arch %d for %s action %d(%s)", + architectures[1], line, rule.action, + get_action_name(rule.action)); } } } INFO("Merging compat seccomp contexts into main context"); - if (compat_ctx[0]) { - if ((compat_arch[0] != native_arch) && - (compat_arch[0] != seccomp_arch_native())) { - ret = seccomp_merge(conf->seccomp_ctx, compat_ctx[0]); + if (contexts[0]) { + if ((architectures[0] != native_arch) && + (architectures[0] != seccomp_arch_native())) { + ret = seccomp_merge(conf->seccomp_ctx, contexts[0]); if (ret < 0) { ERROR("Failed to merge first compat seccomp " "context into main context"); @@ -813,15 +818,15 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) } TRACE("Merged first compat seccomp context into main context"); } else { - seccomp_release(compat_ctx[0]); - compat_ctx[0] = NULL; + seccomp_release(contexts[0]); + contexts[0] = NULL; } } - if (compat_ctx[1]) { - if ((compat_arch[1] != native_arch) && - (compat_arch[1] != seccomp_arch_native())) { - ret = seccomp_merge(conf->seccomp_ctx, compat_ctx[1]); + if (contexts[1]) { + if ((architectures[1] != native_arch) && + (architectures[1] != seccomp_arch_native())) { + ret = seccomp_merge(conf->seccomp_ctx, contexts[1]); if (ret < 0) { ERROR("Failed to merge first compat seccomp " "context into main context"); @@ -829,8 +834,8 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) } TRACE("Merged second compat seccomp context into main context"); } else { - seccomp_release(compat_ctx[1]); - compat_ctx[1] = NULL; + seccomp_release(contexts[1]); + contexts[1] = NULL; } } @@ -840,10 +845,10 @@ bad_arch: ERROR("Unsupported arch: %s.", line); bad_rule: bad: - if (compat_ctx[0]) - seccomp_release(compat_ctx[0]); - if (compat_ctx[1]) - seccomp_release(compat_ctx[1]); + if (contexts[0]) + seccomp_release(contexts[0]); + if (contexts[1]) + seccomp_release(contexts[1]); return -1; } #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */ diff --git a/src/tests/api_reboot.c b/src/tests/api_reboot.c index d609a3339..d169510b5 100644 --- a/src/tests/api_reboot.c +++ b/src/tests/api_reboot.c @@ -59,7 +59,6 @@ int main(int argc, char *argv[]) lxc_error("%s\n", "Container \"reboot\" is not defined"); goto on_error_put; } - c->clear_config(c); if (!c->load_config(c, NULL)) { From eca6736eb019f33a6243fc20a61c658da0662827 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 18 Apr 2018 15:20:21 +0200 Subject: [PATCH 5/5] seccomp: handle arch inversion II LXC generates and loads the seccomp-bpf filter in the host/container which spawn the new container. In other words, userspace N is responsible for generating and loading the seccomp-bpf filter which restricts userspace N + 1. Assume 64bit kernel and 32bit userspace running a 64bit container. In this case the 32-bit x86 userspace is used to create a seccomp-bpf filter for a 64-bit userspace. Unless one explicitly adds the 64-bit ABI to the libseccomp filter, or adjusts the default behavior for "BAD_ARCH", *all* 64-bit x86 syscalls will be blocked. Signed-off-by: Christian Brauner Suggested-by: Paul Moore --- src/lxc/seccomp.c | 252 +++++++++++++++++++++++++++++----------------- 1 file changed, 160 insertions(+), 92 deletions(-) diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index 40922a1b9..ad1366589 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -319,7 +319,7 @@ int get_hostarch(void) return lxc_seccomp_arch_unknown; } -scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_action) +scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_action, bool *needs_merge) { scmp_filter_ctx ctx; int ret; @@ -397,7 +397,10 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_ return NULL; } TRACE("Removed native arch from main seccomp context"); + + *needs_merge = true; } else { + *needs_merge = false; TRACE("Arch %d already present in main seccomp context", (int)n_arch); } @@ -490,13 +493,16 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) { char *p; int ret; - scmp_filter_ctx contexts[3] = {NULL, NULL}; bool blacklist = false; uint32_t default_policy_action = -1, default_rule_action = -1; enum lxc_hostarch_t native_arch = get_hostarch(), cur_rule_arch = native_arch; - uint32_t architectures[2] = {SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE}; struct seccomp_v2_rule rule; + struct scmp_ctx_info { + uint32_t architectures[3]; + scmp_filter_ctx contexts[3]; + bool needs_merge[3]; + } ctx; if (strncmp(line, "blacklist", 9) == 0) blacklist = true; @@ -524,54 +530,115 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) default_rule_action = SCMP_ACT_ALLOW; } + memset(&ctx, 0, sizeof(ctx)); + ctx.architectures[0] = SCMP_ARCH_NATIVE; + ctx.architectures[1] = SCMP_ARCH_NATIVE; + ctx.architectures[2] = SCMP_ARCH_NATIVE; if (native_arch == lxc_seccomp_arch_amd64) { cur_rule_arch = lxc_seccomp_arch_all; - architectures[0] = SCMP_ARCH_X86; - contexts[0] = get_new_ctx(lxc_seccomp_arch_i386, - default_policy_action); - architectures[1] = SCMP_ARCH_X32; - contexts[1] = get_new_ctx(lxc_seccomp_arch_x32, - default_policy_action); - if (!contexts[0] || !contexts[1]) + + ctx.architectures[0] = SCMP_ARCH_X86; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_i386, + default_policy_action, + &ctx.needs_merge[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[1] = SCMP_ARCH_X32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_x32, + default_policy_action, + &ctx.needs_merge[1]); + if (!ctx.contexts[1]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_X86_64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_amd64, + default_policy_action, + &ctx.needs_merge[2]); + if (!ctx.contexts[2]) goto bad; #ifdef SCMP_ARCH_PPC } else if (native_arch == lxc_seccomp_arch_ppc64) { cur_rule_arch = lxc_seccomp_arch_all; - architectures[0] = SCMP_ARCH_PPC; - contexts[0] = get_new_ctx(lxc_seccomp_arch_ppc, - default_policy_action); - if (!contexts[0]) + + ctx.architectures[0] = SCMP_ARCH_PPC; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_ppc, + default_policy_action, + &ctx.needs_merge[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_PPC64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_ppc64, + default_policy_action, + &ctx.needs_merge[2]); + if (!ctx.contexts[2]) goto bad; #endif #ifdef SCMP_ARCH_ARM } else if (native_arch == lxc_seccomp_arch_arm64) { cur_rule_arch = lxc_seccomp_arch_all; - architectures[0] = SCMP_ARCH_ARM; - contexts[0] = get_new_ctx(lxc_seccomp_arch_arm, - default_policy_action); - if (!contexts[0]) + + ctx.architectures[0] = SCMP_ARCH_ARM; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_arm, + default_policy_action, + &ctx.needs_merge[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_AARCH64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_arm64, + default_policy_action, + &ctx.needs_merge[2]); + if (!ctx.contexts[2]) goto bad; #endif #ifdef SCMP_ARCH_MIPS } else if (native_arch == lxc_seccomp_arch_mips64) { cur_rule_arch = lxc_seccomp_arch_all; - architectures[0] = SCMP_ARCH_MIPS; - architectures[1] = SCMP_ARCH_MIPS64N32; - contexts[0] = get_new_ctx(lxc_seccomp_arch_mips, - default_policy_action); - contexts[1] = get_new_ctx(lxc_seccomp_arch_mips64n32, - default_policy_action); - if (!contexts[0] || !contexts[1]) + + ctx.architectures[0] = SCMP_ARCH_MIPS; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mips, + default_policy_action, + &ctx.needs_merge[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[1] = SCMP_ARCH_MIPS64N32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mips64n32, + default_policy_action, + &ctx.needs_merge[1]); + if (!ctx.contexts[1]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_MIPS64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mips64, + default_policy_action, + &ctx.needs_merge[2]); + if (!ctx.contexts[2]) goto bad; } else if (native_arch == lxc_seccomp_arch_mipsel64) { cur_rule_arch = lxc_seccomp_arch_all; - architectures[0] = SCMP_ARCH_MIPSEL; - architectures[1] = SCMP_ARCH_MIPSEL64N32; - contexts[0] = get_new_ctx(lxc_seccomp_arch_mipsel, - default_policy_action); - contexts[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, - default_policy_action); - if (!contexts[0] || !contexts[1]) + + ctx.architectures[0] = SCMP_ARCH_MIPSEL; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mipsel, + default_policy_action, + &ctx.needs_merge[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.architectures[1] = SCMP_ARCH_MIPSEL64N32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, + default_policy_action, + &ctx.needs_merge[1]); + if (!ctx.contexts[1]) + goto bad; + + ctx.architectures[2] = SCMP_ARCH_MIPSEL64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mipsel64, + default_policy_action, + &ctx.needs_merge[2]); + if (!ctx.contexts[2]) goto bad; #endif } @@ -756,61 +823,45 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) goto bad_rule; } - if (cur_rule_arch == native_arch || - cur_rule_arch == lxc_seccomp_arch_native || - architectures[0] == SCMP_ARCH_NATIVE) { - if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, - conf->seccomp_ctx, &rule)) + if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, + conf->seccomp_ctx, &rule)) + goto bad_rule; + INFO("Added native rule for arch %d for %s action %d(%s)", + SCMP_ARCH_NATIVE, line, rule.action, + get_action_name(rule.action)); + + if (ctx.architectures[0] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[0], line, + ctx.contexts[0], &rule)) + goto bad_rule; + INFO("Added compat rule for arch %d for %s action %d(%s)", + ctx.architectures[0], line, rule.action, + get_action_name(rule.action)); + } + + if (ctx.architectures[1] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[1], line, + ctx.contexts[1], &rule)) + goto bad_rule; + INFO("Added compat rule for arch %d for %s action %d(%s)", + ctx.architectures[1], line, rule.action, + get_action_name(rule.action)); + } + + if (ctx.architectures[2] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[2], line, + ctx.contexts[2], &rule)) goto bad_rule; INFO("Added native rule for arch %d for %s action %d(%s)", - SCMP_ARCH_NATIVE, line, rule.action, + ctx.architectures[2], line, rule.action, get_action_name(rule.action)); - } else if (cur_rule_arch != lxc_seccomp_arch_all) { - int arch_index = 0; - - if ((cur_rule_arch == lxc_seccomp_arch_mips64n32) || - (cur_rule_arch == lxc_seccomp_arch_mipsel64n32)) - arch_index = 1; - - if (!do_resolve_add_rule(architectures[arch_index], line, - contexts[arch_index], &rule)) - goto bad_rule; - INFO("Added compat-only rule for arch %d for %s action %d(%s)", - architectures[arch_index], line, rule.action, - get_action_name(rule.action)); - } else { - if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, - conf->seccomp_ctx, &rule)) - goto bad_rule; - INFO("Added native rule for arch %d for %s action %d(%s)", - SCMP_ARCH_NATIVE, line, rule.action, - get_action_name(rule.action)); - - if (architectures[0] != SCMP_ARCH_NATIVE) { - if (!do_resolve_add_rule(architectures[0], line, - contexts[0], &rule)) - goto bad_rule; - INFO("Added compat rule for arch %d for %s action %d(%s)", - architectures[0], line, rule.action, - get_action_name(rule.action)); - } - - if (architectures[1] != SCMP_ARCH_NATIVE) { - if (!do_resolve_add_rule(architectures[1], line, - contexts[1], &rule)) - goto bad_rule; - INFO("Added compat rule for arch %d for %s action %d(%s)", - architectures[1], line, rule.action, - get_action_name(rule.action)); - } } } INFO("Merging compat seccomp contexts into main context"); - if (contexts[0]) { - if ((architectures[0] != native_arch) && - (architectures[0] != seccomp_arch_native())) { - ret = seccomp_merge(conf->seccomp_ctx, contexts[0]); + if (ctx.contexts[0]) { + if (ctx.needs_merge[0]) { + ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[0]); if (ret < 0) { ERROR("Failed to merge first compat seccomp " "context into main context"); @@ -818,15 +869,14 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) } TRACE("Merged first compat seccomp context into main context"); } else { - seccomp_release(contexts[0]); - contexts[0] = NULL; + seccomp_release(ctx.contexts[0]); + ctx.contexts[0] = NULL; } } - if (contexts[1]) { - if ((architectures[1] != native_arch) && - (architectures[1] != seccomp_arch_native())) { - ret = seccomp_merge(conf->seccomp_ctx, contexts[1]); + if (ctx.contexts[1]) { + if (ctx.needs_merge[1]) { + ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[1]); if (ret < 0) { ERROR("Failed to merge first compat seccomp " "context into main context"); @@ -834,8 +884,23 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) } TRACE("Merged second compat seccomp context into main context"); } else { - seccomp_release(contexts[1]); - contexts[1] = NULL; + seccomp_release(ctx.contexts[1]); + ctx.contexts[1] = NULL; + } + } + + if (ctx.contexts[2]) { + if (ctx.needs_merge[2]) { + ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[2]); + if (ret < 0) { + ERROR("Failed to merge third compat seccomp " + "context into main context"); + goto bad; + } + TRACE("Merged third compat seccomp context into main context"); + } else { + seccomp_release(ctx.contexts[2]); + ctx.contexts[2] = NULL; } } @@ -845,10 +910,13 @@ bad_arch: ERROR("Unsupported arch: %s.", line); bad_rule: bad: - if (contexts[0]) - seccomp_release(contexts[0]); - if (contexts[1]) - seccomp_release(contexts[1]); + if (ctx.contexts[0]) + seccomp_release(ctx.contexts[0]); + if (ctx.contexts[1]) + seccomp_release(ctx.contexts[1]); + if (ctx.contexts[2]) + seccomp_release(ctx.contexts[2]); + return -1; } #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */