Add the seccomp_arch_add() and seccomp_arch_remove() functions to add and remove architectures from the filter.
Signed-off-by: Paul Moore <[email protected]> --- include/seccomp.h | 35 +++++++++++++++++++++++++++++ src/api.c | 39 ++++++++++++++++++++++++++++++++ src/arch.c | 45 ++++++++++++++++++++++++++++++++++--- src/arch.h | 4 +++ src/db.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/db.h | 3 ++ 6 files changed, 184 insertions(+), 7 deletions(-) diff --git a/include/seccomp.h b/include/seccomp.h index f6cffea..1a8dc0f 100644 --- a/include/seccomp.h +++ b/include/seccomp.h @@ -24,6 +24,7 @@ #include <inttypes.h> #include <asm/unistd.h> +#include <linux/audit.h> #ifdef __cplusplus extern "C" { @@ -84,6 +85,16 @@ struct scmp_arg_cmp { */ /** + * The x86 (32-bit) architecture token + */ +#define SCMP_ARCH_X86 AUDIT_ARCH_I386 + +/** + * The x86-64 (64-bit) architecture token + */ +#define SCMP_ARCH_X86_64 AUDIT_ARCH_X86_64 + +/** * Convert a syscall name into the associated syscall number * @param x the syscall name */ @@ -194,6 +205,30 @@ int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action); void seccomp_release(scmp_filter_ctx ctx); /** + * Adds an architecture to the filter + * @param ctx the filter context + * @param arch_token the architecture token, e.g. SCMP_ARCH_* + * + * This function adds a new architecture to the given seccomp filter context. + * Any new rules added after this function successfully returns will be added + * to this architecture but existing rules will not be added to this + * architecture. Returns zero on success, negative values on failure. + * + */ +int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token); + +/** + * Removes an architecture from the filter + * @param ctx the filter context + * @param arch_token the architecture token, e.g. SCMP_ARCH_* + * + * This function removes an architecture from the given seccomp filter context. + * Returns zero on success, negative values on failure. + * + */ +int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token); + +/** * Loads the filter into the kernel * @param ctx the filter context * diff --git a/src/api.c b/src/api.c index b69880f..9d26a42 100644 --- a/src/api.c +++ b/src/api.c @@ -124,6 +124,45 @@ void seccomp_release(scmp_filter_ctx ctx) } /* NOTE - function header comment in include/seccomp.h */ +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_valid(arch_token)) + return -EINVAL; + if (db_col_arch_exist(col, arch_token)) + return -EEXIST; + + arch = arch_def_lookup(arch_token); + if (arch) + 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; +} + +/* NOTE - function header comment in include/seccomp.h */ +int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token) +{ + struct db_filter_col *col = (struct db_filter_col *)ctx; + + if (arch_valid(arch_token)) + return -EINVAL; + if (db_col_arch_exist(col, arch_token) != -EEXIST) + return -EEXIST; + + return db_col_db_remove(col, arch_token); +} + +/* NOTE - function header comment in include/seccomp.h */ int seccomp_load(const scmp_filter_ctx ctx) { int rc; diff --git a/src/arch.c b/src/arch.c index 8ab3c0a..a82f33f 100644 --- a/src/arch.c +++ b/src/arch.c @@ -59,13 +59,31 @@ const struct arch_def arch_def_native = { }; /** + * Validate the architecture token + * @param arch the architecture token + * + * Verify the given architecture token; return zero if valid, -EINVAL if not. + * + */ +int arch_valid(uint32_t arch) +{ + switch (arch) { + case AUDIT_ARCH_I386: + case AUDIT_ARCH_X86_64: + return 0; + } + + return -EINVAL; +} + +/** * Lookup the syscall table for an architecture * @param token the architecure token * * Return the architecture's syscall table, returns NULL on failure. * */ -const struct arch_syscall_def *_arch_def_lookup(uint32_t token) +static const struct arch_syscall_def *_arch_syscall_lookup(uint32_t token) { switch (token) { case AUDIT_ARCH_I386: @@ -80,6 +98,27 @@ const struct arch_syscall_def *_arch_def_lookup(uint32_t token) } /** + * Lookup the architecture definition + * @param token the architecure token + * + * Return the matching architecture definition, returns NULL on failure. + * + */ +const struct arch_def *arch_def_lookup(uint32_t token) +{ + switch (token) { + case AUDIT_ARCH_I386: + return &arch_def_i386; + break; + case AUDIT_ARCH_X86_64: + return &arch_def_x86_64; + break; + } + + return NULL; +} + +/** * Determine the maximum number of syscall arguments * @param arch the architecture definition * @@ -154,7 +193,7 @@ int arch_syscall_resolve_name(const struct arch_def *arch, const char *name) unsigned int iter; const struct arch_syscall_def *table; - table = _arch_def_lookup(arch->token); + table = _arch_syscall_lookup(arch->token); if (table == NULL) return __NR_SCMP_ERROR; @@ -182,7 +221,7 @@ const char *arch_syscall_resolve_num(const struct arch_def *arch, int num) unsigned int iter; const struct arch_syscall_def *table; - table = _arch_def_lookup(arch->token); + table = _arch_syscall_lookup(arch->token); if (table == NULL) return NULL; diff --git a/src/arch.h b/src/arch.h index 43ef19f..ada353d 100644 --- a/src/arch.h +++ b/src/arch.h @@ -73,6 +73,10 @@ struct arch_syscall_def { #define ARG_COUNT_MAX 6 +int arch_valid(uint32_t arch); + +const struct arch_def *arch_def_lookup(uint32_t token); + int arch_arg_count_max(const struct arch_def *arch); /** diff --git a/src/db.c b/src/db.c index 174c95c..9e341bc 100644 --- a/src/db.c +++ b/src/db.c @@ -404,6 +404,27 @@ int db_col_valid(struct db_filter_col *col) } /** + * Check to see if an architecture filter exists in the filter collection + * @param col the seccomp filter collection + * @param arch_token the architecture token + * + * Iterate through the given filter collection checking to see if a filter + * exists for the specified architecture. Returns -EEXIST if a filter is found, + * zero if a matching filter does not exist. + * + */ +int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token) +{ + unsigned int iter; + + for (iter = 0; iter < col->filter_cnt; iter++) + if (col->filters[iter]->arch->token == arch_token) + return -EEXIST; + + return 0; +} + +/** * Get a filter attribute * @param col the seccomp filter collection * @param attr the filter attribute @@ -481,12 +502,10 @@ int db_col_attr_set(struct db_filter_col *col, */ int db_col_db_add(struct db_filter_col *col, struct db_filter *db) { - unsigned int iter; struct db_filter **dbs; - for (iter = 0; iter < col->filter_cnt; iter++) - if (col->filters[iter]->arch->token == db->arch->token) - return -EEXIST; + if (db_col_arch_exist(col, db->arch->token)) + return -EEXIST; dbs = realloc(col->filters, sizeof(struct db_filter *) * (col->filter_cnt + 1)); @@ -500,6 +519,44 @@ int db_col_db_add(struct db_filter_col *col, struct db_filter *db) } /** + * Remove a filter DB from a filter collection + * @param col the seccomp filter collection + * @param arch_token the architecture token + * + * This function removes an existing seccomp filter DB from an existing seccomp + * filter collection. Returns zero on success, negative values on failure. + * + */ +int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token) +{ + unsigned int iter; + unsigned int found; + struct db_filter **dbs; + + if ((col->filter_cnt <= 1) || (db_col_arch_exist(col, arch_token) == 0)) + return -EINVAL; + + for (found = 0, iter = 0; iter < col->filter_cnt; iter++) { + if (found) + col->filters[iter - 1] = col->filters[iter]; + else if (col->filters[iter]->arch->token == arch_token) { + db_release(col->filters[iter]); + found = 1; + } + } + col->filters[--col->filter_cnt] = NULL; + + /* NOTE: if we can't do the realloc it isn't fatal, we just have some + * extra space that will get cleaned up later */ + dbs = realloc(col->filters, + sizeof(struct db_filter *) * col->filter_cnt); + if (dbs != NULL) + col->filters = dbs; + + return 0; +} + +/** * Free and reset the seccomp filter DB * @param db the seccomp filter DB * @param def_action the default filter action diff --git a/src/db.h b/src/db.h index a9ebbc9..95280e3 100644 --- a/src/db.h +++ b/src/db.h @@ -170,12 +170,15 @@ void db_col_release(struct db_filter_col *col); int db_col_valid(struct db_filter_col *col); +int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token); + int db_col_attr_get(const struct db_filter_col *col, enum scmp_filter_attr attr, uint32_t *value); int db_col_attr_set(struct db_filter_col *col, enum scmp_filter_attr attr, uint32_t value); int db_col_db_add(struct db_filter_col *col, struct db_filter *db); +int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token); struct db_filter *db_init(const struct arch_def *arch); void db_reset(struct db_filter *db); ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ libseccomp-discuss mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libseccomp-discuss
