summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2016-01-02 15:25:57 -0500
committerPaul Moore <paul@paul-moore.com>2016-02-09 08:32:15 -0500
commit996e445a74823c735757413fda809e1ed0afc7d4 (patch)
treee53d3c9f2f35dbe77ee598ce35c4e668e0a88370
parent57df79c166b26d5044e7e27099e6e69671e727dd (diff)
downloadlibseccomp-996e445a74823c735757413fda809e1ed0afc7d4.tar.gz
arch: move the low level filter rule addition code into the arch layer
The arch specific filter rewrite code is going to need to become more complex so move the low level rule addition code directly into the arch layer instead of the db layer, but still keep the tree manipulation code in the db layer. This patch also creates a new arch specific rule_add() function table entry and allows for this function to create multiple rules from a single rule. Signed-off-by: Paul Moore <pmoore@redhat.com>
-rw-r--r--src/Makefile.am18
-rw-r--r--src/arch-aarch64.c1
-rw-r--r--src/arch-arm.c1
-rw-r--r--src/arch-mips.c2
-rw-r--r--src/arch-mips64.c2
-rw-r--r--src/arch-mips64n32.c2
-rw-r--r--src/arch-ppc.c1
-rw-r--r--src/arch-ppc64.c2
-rw-r--r--src/arch-s390.c1
-rw-r--r--src/arch-s390x.c1
-rw-r--r--src/arch-x32.c1
-rw-r--r--src/arch-x86.c1
-rw-r--r--src/arch-x86_64.c1
-rw-r--r--src/arch.c104
-rw-r--r--src/arch.h9
-rw-r--r--src/db.c71
-rw-r--r--src/db.h2
17 files changed, 140 insertions, 80 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ba9b9f4..2cd8a1e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,7 +21,11 @@ if ENABLE_PYTHON
SUBDIRS += python
endif
-SOURCES_ARCH = \
+SOURCES_ALL = \
+ api.c system.h system.c \
+ gen_pfc.h gen_pfc.c gen_bpf.h gen_bpf.c \
+ hash.h hash.c \
+ db.h db.c \
arch.c arch.h \
arch-x86.h arch-x86.c arch-x86-syscalls.c \
arch-x86_64.h arch-x86_64.c arch-x86_64-syscalls.c \
@@ -36,12 +40,6 @@ SOURCES_ARCH = \
arch-s390.h arch-s390.c arch-s390-syscalls.c \
arch-s390x.h arch-s390x.c arch-s390x-syscalls.c
-SOURCES_GEN = \
- api.c system.h system.c \
- db.h db.c \
- hash.h hash.c \
- gen_pfc.h gen_pfc.c gen_bpf.h gen_bpf.c
-
EXTRA_DIST = arch-syscall-validate
TESTS = arch-syscall-check
@@ -50,11 +48,11 @@ check_PROGRAMS = arch-syscall-check arch-syscall-dump
lib_LTLIBRARIES = libseccomp.la
-arch_syscall_dump_SOURCES = arch-syscall-dump.c ${SOURCES_ARCH}
+arch_syscall_dump_SOURCES = arch-syscall-dump.c ${SOURCES_ALL}
-arch_syscall_check_SOURCES = arch-syscall-check.c ${SOURCES_ARCH}
+arch_syscall_check_SOURCES = arch-syscall-check.c ${SOURCES_ALL}
-libseccomp_la_SOURCES = ${SOURCES_GEN} ${SOURCES_ARCH}
+libseccomp_la_SOURCES = ${SOURCES_ALL}
libseccomp_la_CPPFLAGS = ${AM_CPPFLAGS} -I$(top_builddir)/include
libseccomp_la_CFLAGS = ${AM_CFLAGS} ${CFLAGS} -fPIC -DPIC -fvisibility=hidden
libseccomp_la_LDFLAGS = ${AM_LDFLAGS} ${LDFLAGS} \
diff --git a/src/arch-aarch64.c b/src/arch-aarch64.c
index 6eb66f5..7b596db 100644
--- a/src/arch-aarch64.c
+++ b/src/arch-aarch64.c
@@ -35,4 +35,5 @@ const struct arch_def arch_def_aarch64 = {
.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 8207986..713f393 100644
--- a/src/arch-arm.c
+++ b/src/arch-arm.c
@@ -35,4 +35,5 @@ const struct arch_def arch_def_arm = {
.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 3684714..3c3dd8d 100644
--- a/src/arch-mips.c
+++ b/src/arch-mips.c
@@ -36,6 +36,7 @@ const struct arch_def arch_def_mips = {
.syscall_resolve_num = mips_syscall_resolve_num,
.syscall_rewrite = NULL,
.filter_rewrite = NULL,
+ .rule_add = NULL,
};
const struct arch_def arch_def_mipsel = {
@@ -47,4 +48,5 @@ const struct arch_def arch_def_mipsel = {
.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 a71864f..9327bb6 100644
--- a/src/arch-mips64.c
+++ b/src/arch-mips64.c
@@ -34,6 +34,7 @@ const struct arch_def arch_def_mips64 = {
.syscall_resolve_num = mips64_syscall_resolve_num,
.syscall_rewrite = NULL,
.filter_rewrite = NULL,
+ .rule_add = NULL,
};
const struct arch_def arch_def_mipsel64 = {
@@ -45,4 +46,5 @@ const struct arch_def arch_def_mipsel64 = {
.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 b6a56e1..6831592 100644
--- a/src/arch-mips64n32.c
+++ b/src/arch-mips64n32.c
@@ -36,6 +36,7 @@ const struct arch_def arch_def_mips64n32 = {
.syscall_resolve_num = mips64n32_syscall_resolve_num,
.syscall_rewrite = NULL,
.filter_rewrite = NULL,
+ .rule_add = NULL,
};
const struct arch_def arch_def_mipsel64n32 = {
@@ -47,4 +48,5 @@ const struct arch_def arch_def_mipsel64n32 = {
.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 058b66b..3586422 100644
--- a/src/arch-ppc.c
+++ b/src/arch-ppc.c
@@ -34,4 +34,5 @@ const struct arch_def arch_def_ppc = {
.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 087e2f3..2da9970 100644
--- a/src/arch-ppc64.c
+++ b/src/arch-ppc64.c
@@ -34,6 +34,7 @@ const struct arch_def arch_def_ppc64 = {
.syscall_resolve_num = ppc64_syscall_resolve_num,
.syscall_rewrite = NULL,
.filter_rewrite = NULL,
+ .rule_add = NULL,
};
const struct arch_def arch_def_ppc64le = {
@@ -45,4 +46,5 @@ const struct arch_def arch_def_ppc64le = {
.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 31f082a..494c0de 100644
--- a/src/arch-s390.c
+++ b/src/arch-s390.c
@@ -19,4 +19,5 @@ const struct arch_def arch_def_s390 = {
.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 0a1fdc8..038622a 100644
--- a/src/arch-s390x.c
+++ b/src/arch-s390x.c
@@ -19,4 +19,5 @@ const struct arch_def arch_def_s390x = {
.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 c64f7b9..15ddb1d 100644
--- a/src/arch-x32.c
+++ b/src/arch-x32.c
@@ -36,4 +36,5 @@ const struct arch_def arch_def_x32 = {
.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 8954ec3..00c3a97 100644
--- a/src/arch-x86.c
+++ b/src/arch-x86.c
@@ -39,6 +39,7 @@ const struct arch_def arch_def_x86 = {
.syscall_resolve_num = x86_syscall_resolve_num,
.syscall_rewrite = x86_syscall_rewrite,
.filter_rewrite = x86_filter_rewrite,
+ .rule_add = NULL,
};
/**
diff --git a/src/arch-x86_64.c b/src/arch-x86_64.c
index b5453b3..17beaea 100644
--- a/src/arch-x86_64.c
+++ b/src/arch-x86_64.c
@@ -35,4 +35,5 @@ const struct arch_def arch_def_x86_64 = {
.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 f9bec47..0fc0062 100644
--- a/src/arch.c
+++ b/src/arch.c
@@ -42,6 +42,7 @@
#include "arch-ppc64.h"
#include "arch-s390.h"
#include "arch-s390x.h"
+#include "db.h"
#include "system.h"
#define default_arg_count_max 6
@@ -394,8 +395,8 @@ int arch_syscall_rewrite(const struct arch_def *arch, int *syscall)
* @arch, and negative values on failure.
*
*/
-int arch_filter_rewrite(const struct arch_def *arch, bool strict,
- struct db_api_rule_list *rule)
+static int arch_filter_rewrite(const struct arch_def *arch, bool strict,
+ struct db_api_rule_list *rule)
{
int rc;
int sys = rule->syscall;
@@ -421,3 +422,102 @@ int arch_filter_rewrite(const struct arch_def *arch, bool strict,
return -EDOM;
return 0;
}
+
+/**
+ * Add a new rule to the specified filter
+ * @param db the seccomp filter db
+ * @param strict the strict flag
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param chain_len the number of argument filters in the argument filter chain
+ * @param chain the argument filter chain
+ *
+ * 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.
+ *
+ */
+int arch_filter_rule_add(struct db_filter *db, bool strict,
+ uint32_t action, int syscall,
+ unsigned int chain_len, struct db_api_arg *chain)
+{
+ int rc;
+ size_t chain_size = sizeof(*chain) * chain_len;
+ struct db_api_rule_list *rule, *rule_tail;
+
+ /* ensure we aren't using any reserved syscall values */
+ if (syscall < 0 && syscall > -100)
+ return -EINVAL;
+
+ /* copy of the chain for each filter in the collection */
+ rule = malloc(sizeof(*rule));
+ if (rule == NULL)
+ return -ENOMEM;
+ rule->args = malloc(chain_size);
+ if (rule->args == NULL) {
+ free(rule);
+ return -ENOMEM;
+ }
+ rule->action = action;
+ rule->syscall = syscall;
+ rule->args_cnt = chain_len;
+ memcpy(rule->args, chain, chain_size);
+ rule->prev = NULL;
+ rule->next = NULL;
+
+ /* 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)
+ 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);
+ if (rc == 0) {
+ /* insert the chain to the end of the filter's rule list */
+ rule_tail = rule;
+ while (rule_tail->next)
+ rule_tail = rule_tail->next;
+ if (db->rules != NULL) {
+ rule->prev = db->rules->prev;
+ rule_tail->next = db->rules;
+ db->rules->prev->next = rule;
+ db->rules->prev = rule_tail;
+ } else {
+ rule->prev = rule_tail;
+ rule_tail->next = rule;
+ db->rules = rule;
+ }
+ } else
+ goto rule_add_failure;
+
+ return 0;
+
+rule_add_failure:
+ do {
+ rule_tail = rule;
+ rule = rule->next;
+ free(rule_tail->args);
+ free(rule_tail);
+ } while (rule);
+ return rc;
+}
diff --git a/src/arch.h b/src/arch.h
index c3ac524..54380f7 100644
--- a/src/arch.h
+++ b/src/arch.h
@@ -30,6 +30,8 @@
#include "system.h"
+struct db_filter;
+struct db_api_arg;
struct db_api_rule_list;
struct arch_def {
@@ -52,6 +54,8 @@ struct arch_def {
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,
+ struct db_api_rule_list *rule);
};
/* arch_def for the current architecture */
@@ -99,7 +103,8 @@ const char *arch_syscall_resolve_num(const struct arch_def *arch, int num);
int arch_syscall_translate(const struct arch_def *arch, int *syscall);
int arch_syscall_rewrite(const struct arch_def *arch, int *syscall);
-int arch_filter_rewrite(const struct arch_def *arch, bool strict,
- struct db_api_rule_list *rule);
+int arch_filter_rule_add(struct db_filter *db, bool strict,
+ uint32_t action, int syscall,
+ unsigned int chain_len, struct db_api_arg *chain);
#endif
diff --git a/src/db.c b/src/db.c
index 321a064..793a1db 100644
--- a/src/db.c
+++ b/src/db.c
@@ -1229,8 +1229,7 @@ gen_32_failure:
* filter DB. Returns zero on success, negative values on failure.
*
*/
-static int _db_rule_add(struct db_filter *db,
- const struct db_api_rule_list *rule)
+int db_rule_add(struct db_filter *db, const struct db_api_rule_list *rule)
{
int rc = -ENOMEM;
int syscall = rule->syscall;
@@ -1568,9 +1567,7 @@ int db_col_rule_add(struct db_filter_col *col,
unsigned int chain_len;
unsigned int arg_num;
size_t chain_size;
- struct db_filter *filter;
struct db_api_arg *chain = NULL;
- struct db_api_rule_list *rule;
struct scmp_arg_cmp arg_data;
/* collect the arguments for the filter rule */
@@ -1614,67 +1611,9 @@ int db_col_rule_add(struct db_filter_col *col,
}
for (iter = 0; iter < col->filter_cnt; iter++) {
- filter = col->filters[iter];
-
- /* copy of the chain for each filter in the collection */
- rule = malloc(sizeof(*rule));
- if (rule == NULL) {
- rc_tmp = -ENOMEM;
- goto add_failure;
- }
- rule->args = malloc(chain_size);
- if (rule->args == NULL) {
- free(rule);
- rc_tmp = -ENOMEM;
- goto add_failure;
- }
- rule->action = action;
- rule->syscall = syscall;
- rule->args_cnt = chain_len;
- memcpy(rule->args, chain, chain_size);
-
- rc_tmp = arch_syscall_translate(filter->arch, &rule->syscall);
- if (rc_tmp < 0) {
- free(rule->args);
- free(rule);
- goto 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_tmp = arch_filter_rewrite(filter->arch, strict,
- rule);
- if (rc_tmp < 0) {
- free(rule->args);
- free(rule);
- if ((rc_tmp == -EDOM) && (!strict))
- continue;
- goto add_failure;
- }
- }
-
- /* add the new rule to the existing filter */
- rc_tmp = _db_rule_add(filter, rule);
- if (rc_tmp == 0) {
- /* insert the chain to the end of the filter's rule list */
- if (filter->rules != NULL) {
- rule->prev = filter->rules->prev;
- rule->next = filter->rules;
- filter->rules->prev->next = rule;
- filter->rules->prev = rule;
- } else {
- rule->prev = rule;
- rule->next = rule;
- filter->rules = rule;
- }
- } else {
- free(rule->args);
- free(rule);
- }
-
-add_failure:
+ rc_tmp = arch_filter_rule_add(col->filters[iter], strict,
+ action, syscall,
+ chain_len, chain);
if (rc == 0 && rc_tmp < 0)
rc = rc_tmp;
}
@@ -1755,7 +1694,7 @@ int db_col_transaction_start(struct db_filter_col *col)
}
/* insert the rule into the filter */
- if (_db_rule_add(filter_s, rule_o) != 0)
+ if (db_rule_add(filter_s, rule_o) != 0)
goto trans_start_failure;
/* next rule */
diff --git a/src/db.h b/src/db.h
index 02e9394..6e1202e 100644
--- a/src/db.h
+++ b/src/db.h
@@ -219,4 +219,6 @@ int db_col_transaction_start(struct db_filter_col *col);
void db_col_transaction_abort(struct db_filter_col *col);
void db_col_transaction_commit(struct db_filter_col *col);
+int db_rule_add(struct db_filter *db, const struct db_api_rule_list *rule);
+
#endif