From 5b42b8cfa25506fa260c8f46b4a063b5cfd09d1c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sat, 2 Jan 2016 22:24:29 -0500 Subject: arch: enable more involved arch/ABI specific rule creation Create the infrastructure for arch/ABI specific rule creation that allows us much more involved arch/ABI customization. Signed-off-by: Paul Moore --- src/arch-aarch64.c | 1 - src/arch-arm.c | 1 - src/arch-mips.c | 2 -- src/arch-mips64.c | 2 -- src/arch-mips64n32.c | 2 -- src/arch-ppc.c | 1 - src/arch-ppc64.c | 2 -- src/arch-s390.c | 1 - src/arch-s390x.c | 1 - src/arch-x32.c | 1 - src/arch-x86.c | 50 +++++++++++++++++++++---------------- src/arch-x86.h | 3 ++- src/arch-x86_64.c | 1 - src/arch.c | 69 +++++++--------------------------------------------- src/arch.h | 3 +-- 15 files changed, 41 insertions(+), 99 deletions(-) diff --git a/src/arch-aarch64.c b/src/arch-aarch64.c index 7b596db..188bc6f 100644 --- a/src/arch-aarch64.c +++ b/src/arch-aarch64.c @@ -34,6 +34,5 @@ const struct arch_def arch_def_aarch64 = { .syscall_resolve_name = aarch64_syscall_resolve_name, .syscall_resolve_num = aarch64_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-arm.c b/src/arch-arm.c index 713f393..b403d98 100644 --- a/src/arch-arm.c +++ b/src/arch-arm.c @@ -34,6 +34,5 @@ const struct arch_def arch_def_arm = { .syscall_resolve_name = arm_syscall_resolve_name, .syscall_resolve_num = arm_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-mips.c b/src/arch-mips.c index 3c3dd8d..1d1f4e2 100644 --- a/src/arch-mips.c +++ b/src/arch-mips.c @@ -35,7 +35,6 @@ const struct arch_def arch_def_mips = { .syscall_resolve_name = mips_syscall_resolve_name, .syscall_resolve_num = mips_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; @@ -47,6 +46,5 @@ const struct arch_def arch_def_mipsel = { .syscall_resolve_name = mips_syscall_resolve_name, .syscall_resolve_num = mips_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-mips64.c b/src/arch-mips64.c index 9327bb6..9cb34e2 100644 --- a/src/arch-mips64.c +++ b/src/arch-mips64.c @@ -33,7 +33,6 @@ const struct arch_def arch_def_mips64 = { .syscall_resolve_name = mips64_syscall_resolve_name, .syscall_resolve_num = mips64_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; @@ -45,6 +44,5 @@ const struct arch_def arch_def_mipsel64 = { .syscall_resolve_name = mips64_syscall_resolve_name, .syscall_resolve_num = mips64_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-mips64n32.c b/src/arch-mips64n32.c index 6831592..c798c89 100644 --- a/src/arch-mips64n32.c +++ b/src/arch-mips64n32.c @@ -35,7 +35,6 @@ const struct arch_def arch_def_mips64n32 = { .syscall_resolve_name = mips64n32_syscall_resolve_name, .syscall_resolve_num = mips64n32_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; @@ -47,6 +46,5 @@ const struct arch_def arch_def_mipsel64n32 = { .syscall_resolve_name = mips64n32_syscall_resolve_name, .syscall_resolve_num = mips64n32_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-ppc.c b/src/arch-ppc.c index 3586422..cb430a9 100644 --- a/src/arch-ppc.c +++ b/src/arch-ppc.c @@ -33,6 +33,5 @@ const struct arch_def arch_def_ppc = { .syscall_resolve_name = ppc_syscall_resolve_name, .syscall_resolve_num = ppc_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-ppc64.c b/src/arch-ppc64.c index 2da9970..b8de8e7 100644 --- a/src/arch-ppc64.c +++ b/src/arch-ppc64.c @@ -33,7 +33,6 @@ const struct arch_def arch_def_ppc64 = { .syscall_resolve_name = ppc64_syscall_resolve_name, .syscall_resolve_num = ppc64_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; @@ -45,6 +44,5 @@ const struct arch_def arch_def_ppc64le = { .syscall_resolve_name = ppc64_syscall_resolve_name, .syscall_resolve_num = ppc64_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-s390.c b/src/arch-s390.c index 494c0de..f509809 100644 --- a/src/arch-s390.c +++ b/src/arch-s390.c @@ -18,6 +18,5 @@ const struct arch_def arch_def_s390 = { .syscall_resolve_name = s390_syscall_resolve_name, .syscall_resolve_num = s390_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-s390x.c b/src/arch-s390x.c index 038622a..5471738 100644 --- a/src/arch-s390x.c +++ b/src/arch-s390x.c @@ -18,6 +18,5 @@ const struct arch_def arch_def_s390x = { .syscall_resolve_name = s390x_syscall_resolve_name, .syscall_resolve_num = s390x_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-x32.c b/src/arch-x32.c index 15ddb1d..a496d18 100644 --- a/src/arch-x32.c +++ b/src/arch-x32.c @@ -35,6 +35,5 @@ const struct arch_def arch_def_x32 = { .syscall_resolve_name = x32_syscall_resolve_name, .syscall_resolve_num = x32_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch-x86.c b/src/arch-x86.c index 00c3a97..b5fbbab 100644 --- a/src/arch-x86.c +++ b/src/arch-x86.c @@ -38,8 +38,7 @@ const struct arch_def arch_def_x86 = { .syscall_resolve_name = x86_syscall_resolve_name, .syscall_resolve_num = x86_syscall_resolve_num, .syscall_rewrite = x86_syscall_rewrite, - .filter_rewrite = x86_filter_rewrite, - .rule_add = NULL, + .rule_add = x86_rule_add, }; /** @@ -66,31 +65,31 @@ int x86_syscall_rewrite(int *syscall) } /** - * Rewrite a filter rule to match the architecture specifics - * @param arch the architecture definition - * @param strict strict flag + * add a new rule to the x86 seccomp filter + * @param db the seccomp filter db + * @param strict the strict flag * @param rule the filter rule * - * Syscalls can vary across different architectures so this function handles - * the necessary seccomp rule rewrites to ensure the right thing is done - * regardless of the rule or architecture. If @strict is true then the - * function will fail if the entire filter can not be preservered, however, - * if @strict is false the function will do a "best effort" rewrite and not - * fail. Returns zero on success, negative values on failure. + * This function adds a new syscall filter to the seccomp filter db, making any + * necessary adjustments for the x86 ABI. Returns zero on success, negative + * values on failure. * */ -int x86_filter_rewrite(bool strict, struct db_api_rule_list *rule) +int x86_rule_add(struct db_filter *db, bool strict, + struct db_api_rule_list *rule) { - int arg_max; + int rc; unsigned int iter; int sys = rule->syscall; - arg_max = ARG_COUNT_MAX; - if (arg_max < 0) - return arg_max; - - if (sys <= -100 && sys >= -117) { - for (iter = 0; iter < arg_max; iter++) { + if (sys >= 0) { + /* normal syscall processing */ + rc = db_rule_add(db, rule); + if (rc < 0) + return rc; + } else if (sys <= -100 && sys >= -117) { + /* multiplexed socket syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { if ((rule->args[iter].valid != 0) && (strict)) return -EINVAL; } @@ -100,8 +99,13 @@ int x86_filter_rewrite(bool strict, struct db_api_rule_list *rule) rule->args[0].datum = abs(sys) % 100; rule->args[0].valid = 1; rule->syscall = __x86_NR_socketcall; + + rc = db_rule_add(db, rule); + if (rc < 0) + return rc; } else if (sys <= -200 && sys >= -211) { - for (iter = 0; iter < arg_max; iter++) { + /* multiplexed ipc syscalls */ + for (iter = 0; iter < ARG_COUNT_MAX; iter++) { if ((rule->args[iter].valid != 0) && (strict)) return -EINVAL; } @@ -111,7 +115,11 @@ int x86_filter_rewrite(bool strict, struct db_api_rule_list *rule) rule->args[0].datum = abs(sys) % 200; rule->args[0].valid = 1; rule->syscall = __x86_NR_ipc; - } else if (sys < 0) + + rc = db_rule_add(db, rule); + if (rc < 0) + return rc; + } else if (strict) return -EDOM; return 0; diff --git a/src/arch-x86.h b/src/arch-x86.h index 4f895e0..793c480 100644 --- a/src/arch-x86.h +++ b/src/arch-x86.h @@ -37,6 +37,7 @@ const char *x86_syscall_iterate_name(unsigned int spot); int x86_syscall_rewrite(int *syscall); -int x86_filter_rewrite(bool strict, struct db_api_rule_list *rule); +int x86_rule_add(struct db_filter *db, bool strict, + struct db_api_rule_list *rule); #endif diff --git a/src/arch-x86_64.c b/src/arch-x86_64.c index 17beaea..ccbf1b1 100644 --- a/src/arch-x86_64.c +++ b/src/arch-x86_64.c @@ -34,6 +34,5 @@ const struct arch_def arch_def_x86_64 = { .syscall_resolve_name = x86_64_syscall_resolve_name, .syscall_resolve_num = x86_64_syscall_resolve_num, .syscall_rewrite = NULL, - .filter_rewrite = NULL, .rule_add = NULL, }; diff --git a/src/arch.c b/src/arch.c index 0fc0062..afe7ae9 100644 --- a/src/arch.c +++ b/src/arch.c @@ -380,49 +380,6 @@ int arch_syscall_rewrite(const struct arch_def *arch, int *syscall) return 0; } -/** - * Rewrite a filter rule to match the architecture specifics - * @param arch the architecture definition - * @param strict strict flag - * @param rule the filter rule - * - * Syscalls can vary across different architectures so this function handles - * the necessary seccomp rule rewrites to ensure the right thing is done - * regardless of the rule or architecture. If @strict is true then the - * function will fail if the entire filter can not be preservered, however, - * if @strict is false the function will do a "best effort" rewrite and not - * fail. Returns zero on success, -EDOM if the syscall is not defined for - * @arch, and negative values on failure. - * - */ -static int arch_filter_rewrite(const struct arch_def *arch, bool strict, - struct db_api_rule_list *rule) -{ - int rc; - int sys = rule->syscall; - - if (sys >= 0) { - /* we shouldn't be here - no rewrite needed */ - return 0; - } else if (sys < 0 && sys > -100) { - /* reserved values */ - return -EINVAL; - } else if (sys <= -100 && sys > -10000) { - /* rewritable syscalls */ - if (arch->filter_rewrite) { - rc = (*arch->filter_rewrite)(strict, rule); - /* we still want to catch invalid rewrites */ - if (rc == -EINVAL) - return -EINVAL; - } - } - - /* syscalls not defined on this architecture */ - if (rule->syscall < 0) - return -EDOM; - return 0; -} - /** * Add a new rule to the specified filter * @param db the seccomp filter db @@ -453,6 +410,11 @@ int arch_filter_rule_add(struct db_filter *db, bool strict, if (syscall < 0 && syscall > -100) return -EINVAL; + /* translate the syscall */ + rc = arch_syscall_translate(db->arch, &syscall); + if (rc < 0) + return rc; + /* copy of the chain for each filter in the collection */ rule = malloc(sizeof(*rule)); if (rule == NULL) @@ -471,27 +433,14 @@ int arch_filter_rule_add(struct db_filter *db, bool strict, /* add the new rule to the existing filter */ if (db->arch->rule_add == NULL) { - rc = arch_syscall_translate(db->arch, &rule->syscall); - if (rc < 0) + /* negative syscalls require a db->arch->rule_add() function */ + if (syscall < 0 && strict) { + rc = -EDOM; goto rule_add_failure; - - /* if this is a pseudo syscall (syscall < 0) then we need to - * rewrite the rule for some arch specific reason */ - if (rule->syscall < 0) { - /* mangle the private chain copy */ - rc = arch_filter_rewrite(db->arch, strict, rule); - if ((rc == -EDOM) && (!strict)) { - /* don't consider this a failure */ - rc = 0; - goto rule_add_failure; - } - if (rc < 0) - goto rule_add_failure; } - rc = db_rule_add(db, rule); } else - rc = (db->arch->rule_add)(db, rule); + rc = (db->arch->rule_add)(db, strict, rule); if (rc == 0) { /* insert the chain to the end of the filter's rule list */ rule_tail = rule; diff --git a/src/arch.h b/src/arch.h index 54380f7..580e521 100644 --- a/src/arch.h +++ b/src/arch.h @@ -53,8 +53,7 @@ struct arch_def { int (*syscall_resolve_name)(const char *name); const char *(*syscall_resolve_num)(int num); int (*syscall_rewrite)(int *syscall); - int (*filter_rewrite)(bool strict, struct db_api_rule_list *rule); - int (*rule_add)(struct db_filter *filter, + int (*rule_add)(struct db_filter *filter, bool strict, struct db_api_rule_list *rule); }; -- cgit v1.2.1