summaryrefslogtreecommitdiff
path: root/src/api.c
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2015-12-17 15:52:32 -0500
committerPaul Moore <paul@paul-moore.com>2016-02-09 08:32:15 -0500
commita4478ddcd4e3b34fcd9c526dcf54f0d79b33ac16 (patch)
treea5176dee025ce7d2432c4b367c21ad0ff8456cb8 /src/api.c
parentd32c3bfa4b07add90dcd04292eb4ba278dd103ba (diff)
downloadlibseccomp-a4478ddcd4e3b34fcd9c526dcf54f0d79b33ac16.tar.gz
db: make the individual db filter ops private
We really should operate only on filter collections so move all the individual DB filter operations out of api.c and into db.c. There are likely other changes that can now be done to further clean the code, but I'll leave that as future work. Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'src/api.c')
-rw-r--r--src/api.c251
1 files changed, 34 insertions, 217 deletions
diff --git a/src/api.c b/src/api.c
index 0cfa407..a4f9deb 100644
--- a/src/api.c
+++ b/src/api.c
@@ -69,51 +69,21 @@ static int _syscall_valid(int syscall)
/* NOTE - function header comment in include/seccomp.h */
API scmp_filter_ctx seccomp_init(uint32_t def_action)
{
- struct db_filter_col *col;
- struct db_filter *db;
-
if (db_action_valid(def_action) < 0)
return NULL;
- col = db_col_init(def_action);
- if (col == NULL)
- return NULL;
- db = db_init(arch_def_native);
- if (db == NULL)
- goto init_failure_col;
-
- if (db_col_db_add(col, db) < 0)
- goto init_failure_db;
-
- return col;
-
-init_failure_db:
- db_release(db);
-init_failure_col:
- db_col_release(col);
- return NULL;
+ return db_col_init(def_action);
}
/* NOTE - function header comment in include/seccomp.h */
API int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action)
{
- int rc;
struct db_filter_col *col = (struct db_filter_col *)ctx;
- struct db_filter *db;
if (ctx == NULL || db_action_valid(def_action) < 0)
return -EINVAL;
- db_col_reset(col, def_action);
-
- db = db_init(arch_def_native);
- if (db == NULL)
- return -ENOMEM;
- rc = db_col_db_add(col, db);
- if (rc < 0)
- db_release(db);
-
- return rc;
+ return db_col_reset(col, def_action);
}
/* NOTE - function header comment in include/seccomp.h */
@@ -180,9 +150,7 @@ API int seccomp_arch_exist(const scmp_filter_ctx ctx,
/* NOTE - function header comment in include/seccomp.h */
API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
{
- int rc;
const struct arch_def *arch;
- struct db_filter *db;
struct db_filter_col *col = (struct db_filter_col *)ctx;
if (arch_token == 0)
@@ -196,14 +164,7 @@ API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
arch = arch_def_lookup(arch_token);
if (arch == NULL)
return -EFAULT;
- db = db_init(arch);
- if (db == NULL)
- return -ENOMEM;
- rc = db_col_db_add(col, db);
- if (rc < 0)
- db_release(db);
-
- return rc;
+ return db_col_db_new(col, arch);
}
/* NOTE - function header comment in include/seccomp.h */
@@ -336,81 +297,25 @@ API int seccomp_syscall_resolve_name(const char *name)
API int seccomp_syscall_priority(scmp_filter_ctx ctx,
int syscall, uint8_t priority)
{
- int rc = 0, rc_tmp;
- unsigned int iter;
- int sc_tmp;
- struct db_filter_col *col;
- struct db_filter *filter;
+ struct db_filter_col *col = (struct db_filter_col *)ctx;
- if (_ctx_valid(ctx) || _syscall_valid(syscall))
+ if (db_col_valid(col) || _syscall_valid(syscall))
return -EINVAL;
- col = (struct db_filter_col *)ctx;
- for (iter = 0; iter < col->filter_cnt; iter++) {
- filter = col->filters[iter];
- sc_tmp = syscall;
-
- rc_tmp = arch_syscall_translate(filter->arch, &sc_tmp);
- if (rc_tmp < 0)
- goto syscall_priority_failure;
-
- /* if this is a pseudo syscall (syscall < 0) then we need to
- * rewrite the syscall for some arch specific reason */
- if (sc_tmp < 0) {
- /* we set this as a strict op - we don't really care
- * since priorities are a "best effort" thing - as we
- * want to catch the -EDOM error and bail on this
- * architecture */
- rc_tmp = arch_syscall_rewrite(filter->arch, &sc_tmp);
- if (rc_tmp == -EDOM)
- continue;
- if (rc_tmp < 0)
- goto syscall_priority_failure;
- }
-
- rc_tmp = db_syscall_priority(filter, sc_tmp, priority);
-
-syscall_priority_failure:
- if (rc == 0 && rc_tmp < 0)
- rc = rc_tmp;
- }
-
- return rc;
+ return db_col_syscall_priority(col, syscall, priority);
}
-/**
- * Add a new rule to the current filter
- * @param col the filter collection
- * @param strict the strict flag
- * @param action the filter action
- * @param syscall the syscall number
- * @param arg_cnt the number of argument filters in the argument filter chain
- * @param arg_array the argument filter chain, (uint, enum scmp_compare, ulong)
- *
- * This function adds a new argument/comparison/value to the seccomp filter for
- * a syscall; multiple arguments can be specified and they will be chained
- * together (essentially AND'd together) in the filter. When the strict flag
- * is true the function will fail if the exact rule can not be added to the
- * filter, if the strict flag is false the function will not fail if the
- * function needs to adjust the rule due to architecture specifics. Returns
- * zero on success, negative values on failure.
- *
- */
-static int _seccomp_rule_add(struct db_filter_col *col,
- bool strict, uint32_t action, int syscall,
- unsigned int arg_cnt,
- const struct scmp_arg_cmp *arg_array)
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_rule_add_array(scmp_filter_ctx ctx,
+ uint32_t action, int syscall,
+ unsigned int arg_cnt,
+ const struct scmp_arg_cmp *arg_array)
{
- int rc = 0, rc_tmp;
- int sc_tmp;
- unsigned int iter;
- unsigned int chain_len;
- unsigned int arg_num;
- size_t chain_size;
- struct db_filter *filter;
- struct db_api_arg *chain = NULL, *chain_tmp;
- struct scmp_arg_cmp arg_data;
+ int rc;
+ struct db_filter_col *col = (struct db_filter_col *)ctx;
+ if (arg_cnt > ARG_COUNT_MAX)
+ return -EINVAL;
if (arg_cnt > 0 && arg_array == NULL)
return -EINVAL;
@@ -423,110 +328,7 @@ static int _seccomp_rule_add(struct db_filter_col *col,
if (action == col->attr.act_default)
return -EPERM;
- if (strict && col->filter_cnt > 1)
- return -EOPNOTSUPP;
-
- /* collect the arguments for the filter rule */
- chain_len = ARG_COUNT_MAX;
- chain_size = sizeof(*chain) * chain_len;
- chain = malloc(chain_size);
- if (chain == NULL)
- return -ENOMEM;
- memset(chain, 0, chain_size);
- for (iter = 0; iter < arg_cnt; iter++) {
- arg_data = arg_array[iter];
- arg_num = arg_data.arg;
- if (arg_num < chain_len && chain[arg_num].valid == 0) {
- chain[arg_num].valid = 1;
- chain[arg_num].arg = arg_num;
- chain[arg_num].op = arg_data.op;
- /* XXX - we should check datum/mask size against the
- * arch definition, e.g. 64 bit datum on x86 */
- switch (chain[arg_num].op) {
- case SCMP_CMP_NE:
- case SCMP_CMP_LT:
- case SCMP_CMP_LE:
- case SCMP_CMP_EQ:
- case SCMP_CMP_GE:
- case SCMP_CMP_GT:
- chain[arg_num].mask = DATUM_MAX;
- chain[arg_num].datum = arg_data.datum_a;
- break;
- case SCMP_CMP_MASKED_EQ:
- chain[arg_num].mask = arg_data.datum_a;
- chain[arg_num].datum = arg_data.datum_b;
- break;
- default:
- rc = -EINVAL;
- goto rule_add_return;
- }
- } else {
- rc = -EINVAL;
- goto rule_add_return;
- }
- }
-
- for (iter = 0; iter < col->filter_cnt; iter++) {
- filter = col->filters[iter];
- sc_tmp = syscall;
-
- rc_tmp = arch_syscall_translate(filter->arch, &sc_tmp);
- if (rc_tmp < 0)
- 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 (sc_tmp < 0) {
- /* make a private copy of the chain */
- chain_tmp = malloc(chain_size);
- if (chain_tmp == NULL) {
- rc = -ENOMEM;
- goto rule_add_failure;
- }
- memcpy(chain_tmp, chain, chain_size);
-
- /* mangle the private chain copy */
- rc_tmp = arch_filter_rewrite(filter->arch, strict,
- &sc_tmp, chain_tmp);
- if ((rc_tmp == -EDOM) && (!strict)) {
- free(chain_tmp);
- continue;
- }
- if (rc_tmp < 0) {
- free(chain_tmp);
- goto rule_add_failure;
- }
-
- /* add the new rule to the existing filter */
- rc_tmp = db_rule_add(filter, action, sc_tmp, chain_tmp);
- free(chain_tmp);
- } else
- /* add the new rule to the existing filter */
- rc_tmp = db_rule_add(filter, action, sc_tmp, chain);
-
-rule_add_failure:
- if (rc == 0 && rc_tmp < 0)
- rc = rc_tmp;
- }
-
-rule_add_return:
- if (chain != NULL)
- free(chain);
- return rc;
-}
-
-/* NOTE - function header comment in include/seccomp.h */
-API int seccomp_rule_add_array(scmp_filter_ctx ctx,
- uint32_t action, int syscall,
- unsigned int arg_cnt,
- const struct scmp_arg_cmp *arg_array)
-{
- /* arg_cnt is unsigned, so no need to check the lower bound */
- if (arg_cnt > ARG_COUNT_MAX)
- return -EINVAL;
-
- return _seccomp_rule_add((struct db_filter_col *)ctx,
- 0, action, syscall, arg_cnt, arg_array);
+ return db_col_rule_add(col, 0, action, syscall, arg_cnt, arg_array);
}
/* NOTE - function header comment in include/seccomp.h */
@@ -558,12 +360,27 @@ API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
unsigned int arg_cnt,
const struct scmp_arg_cmp *arg_array)
{
- /* arg_cnt is unsigned, so no need to check the lower bound */
+ int rc;
+ struct db_filter_col *col = (struct db_filter_col *)ctx;
+
if (arg_cnt > ARG_COUNT_MAX)
return -EINVAL;
+ if (arg_cnt > 0 && arg_array == NULL)
+ return -EINVAL;
+
+ if (db_col_valid(col) || _syscall_valid(syscall))
+ return -EINVAL;
+
+ rc = db_action_valid(action);
+ if (rc < 0)
+ return rc;
+ if (action == col->attr.act_default)
+ return -EPERM;
+
+ if (col->filter_cnt > 1)
+ return -EOPNOTSUPP;
- return _seccomp_rule_add((struct db_filter_col *)ctx,
- 1, action, syscall, arg_cnt, arg_array);
+ return db_col_rule_add(col, 1, action, syscall, arg_cnt, arg_array);
}
/* NOTE - function header comment in include/seccomp.h */