diff options
author | Paul Moore <pmoore@redhat.com> | 2012-09-21 12:07:02 -0400 |
---|---|---|
committer | Paul Moore <pmoore@redhat.com> | 2012-09-27 17:15:02 -0400 |
commit | 6ebd717ad64d51eaca892026e937e6da866b0f94 (patch) | |
tree | 2337742259bdaabfe4957c1fafa663cf62d56986 /src | |
parent | b3416eb2d7295b8f217eeaf0f5213a9ea5f9e202 (diff) | |
download | libseccomp-6ebd717ad64d51eaca892026e937e6da866b0f94.tar.gz |
pfc: provide basic multiple arch/filter support
Add support for multiple architectures/filters to the PFC filter
generation code. This patch also cleans up the PFC output a bit in
hopes of making it more readable and consistent.
Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gen_pfc.c | 150 |
1 files changed, 97 insertions, 53 deletions
diff --git a/src/gen_pfc.c b/src/gen_pfc.c index 3f36f11..7d4463b 100644 --- a/src/gen_pfc.c +++ b/src/gen_pfc.c @@ -26,6 +26,9 @@ #include <string.h> #include <unistd.h> +/* NOTE: needed for the arch->token decoding in _pfc_arch() */ +#include <linux/audit.h> + #include <seccomp.h> #include "arch.h" @@ -40,6 +43,22 @@ struct pfc_sys_list { /* XXX - we should check the fprintf() return values */ /** + * Display a string representation of the architecture + * @param arch the architecture definition + */ +static const char *_pfc_arch(const struct arch_def *arch) +{ + switch (arch->token) { + case AUDIT_ARCH_I386: + return "x86"; + case AUDIT_ARCH_X86_64: + return "x86_64"; + default: + return "UNKNOWN"; + } +} + +/** * Display a string representation of the node argument * @param fds the file stream to send the output * @param arch the architecture definition @@ -67,22 +86,22 @@ static void _pfc_action(FILE *fds, uint32_t action) { switch (action & 0xffff0000) { case SCMP_ACT_KILL: - fprintf(fds, " action KILL;\n"); + fprintf(fds, "action KILL;\n"); break; case SCMP_ACT_TRAP: - fprintf(fds, " action TRAP;\n"); + fprintf(fds, "action TRAP;\n"); break; case SCMP_ACT_ERRNO(0): - fprintf(fds, " action ERRNO(%u);\n", (action & 0x0000ffff)); + fprintf(fds, "action ERRNO(%u);\n", (action & 0x0000ffff)); break; case SCMP_ACT_TRACE(0): - fprintf(fds, " action TRACE(%u);\n", (action & 0x0000ffff)); + fprintf(fds, "action TRACE(%u);\n", (action & 0x0000ffff)); break; case SCMP_ACT_ALLOW: - fprintf(fds, " action ALLOW;\n"); + fprintf(fds, "action ALLOW;\n"); break; default: - fprintf(fds, " action 0x%x;\n", action); + fprintf(fds, "action 0x%x;\n", action); } } @@ -97,7 +116,7 @@ static void _pfc_action(FILE *fds, uint32_t action) static void _indent(FILE *fds, unsigned int lvl) { while (lvl-- > 0) - fprintf(fds, " "); + fprintf(fds, " "); } /** @@ -125,7 +144,7 @@ static void _gen_pfc_chain(const struct arch_def *arch, while (c_iter != NULL) { /* comparison operation */ _indent(fds, lvl); - fprintf(fds, " if ("); + fprintf(fds, "if ("); _pfc_arg(fds, arch, c_iter); switch (c_iter->op) { case SCMP_CMP_EQ: @@ -155,12 +174,12 @@ static void _gen_pfc_chain(const struct arch_def *arch, /* false result */ if (c_iter->act_f_flg) { _indent(fds, lvl); - fprintf(fds, " else\n"); + fprintf(fds, "else\n"); _indent(fds, lvl + 1); _pfc_action(fds, c_iter->act_f); } else if (c_iter->nxt_f != NULL) { _indent(fds, lvl); - fprintf(fds, " else\n"); + fprintf(fds, "else\n"); _gen_pfc_chain(arch, c_iter->nxt_f, lvl + 1, fds); } @@ -183,58 +202,42 @@ static void _gen_pfc_syscall(const struct arch_def *arch, { unsigned int sys_num = sys->num; - fprintf(fds, "# filter code for syscall #%d (priority: %d)\n", + _indent(fds, 1); + fprintf(fds, "# filter for syscall #%d (priority: %d)\n", sys_num, sys->priority); - if (sys->chains != NULL) { - fprintf(fds, " if ($syscall != %d) goto syscal_%d_end;\n", - sys_num, sys_num); - _gen_pfc_chain(arch, sys->chains, 0, fds); - fprintf(fds, " syscall_%d_end:\n", sys_num); - } else { - fprintf(fds, " if ($syscall == %d)", sys_num); + _indent(fds, 1); + fprintf(fds, "if ($syscall == %d)\n", sys_num); + if (sys->chains == NULL) { + _indent(fds, 2); _pfc_action(fds, sys->action); - } + } else + _gen_pfc_chain(arch, sys->chains, 2, fds); } /** - * Generate a pseudo filter code string representation + * Generate pseudo filter code for an architecture * @param col the seccomp filter collection - * @param fd the fd to send the output + * @param db the single seccomp filter + * @param fds the file stream to send the output * * This function generates a pseudo filter code representation of the given - * filter collection and writes it to the given fd. Returns zero on success, - * negative values on failure. + * filter DB and writes it to the given output stream. Returns zero on + * success, negative values on failure. * */ -int gen_pfc_generate(const struct db_filter_col *col, int fd) +static int _gen_pfc_arch(const struct db_filter_col *col, + const struct db_filter *db, FILE *fds) { - int rc = 0; - int newfd; - FILE *fds; - struct db_filter *db; + int rc; struct db_sys_list *s_iter; struct pfc_sys_list *p_iter = NULL, *p_new, *p_head = NULL, *p_prev; - /* NOTE: temporary until we fully support filter collections */ - if (col->filter_cnt != 1 || col->filters[0]->arch != &arch_def_native) - return -EFAULT; - db = col->filters[0]; - - newfd = dup(fd); - if (newfd < 0) - return errno; - fds = fdopen(newfd, "a"); - if (fds == NULL) { - close(newfd); - return errno; - } - /* sort the syscall list */ db_list_foreach(s_iter, db->syscalls) { p_new = malloc(sizeof(*p_new)); if (p_new == NULL) { rc = -ENOMEM; - goto generate_return; + goto arch_return; } memset(p_new, 0, sizeof(*p_new)); p_new->sys = s_iter; @@ -257,10 +260,9 @@ int gen_pfc_generate(const struct db_filter_col *col, int fd) } } - /* generate the pfc */ - fprintf(fds, "#\n"); - fprintf(fds, "# pseudo filter code start\n"); - fprintf(fds, "#\n"); + fprintf(fds, "# filter for arch %s (%u)\n", + _pfc_arch(db->arch), db->arch->token); + fprintf(fds, "if ($arch == %u)\n", db->arch->token); p_iter = p_head; while (p_iter != NULL) { if (p_iter->sys->valid == 0) @@ -268,8 +270,56 @@ int gen_pfc_generate(const struct db_filter_col *col, int fd) _gen_pfc_syscall(db->arch, p_iter->sys, fds); p_iter = p_iter->next; } + _indent(fds, 1); fprintf(fds, "# default action\n"); + _indent(fds, 1); _pfc_action(fds, col->attr.act_default); + +arch_return: + while (p_head != NULL) { + p_iter = p_head; + p_head = p_head->next; + free(p_iter); + } + return rc; +} + +/** + * Generate a pseudo filter code string representation + * @param col the seccomp filter collection + * @param fd the fd to send the output + * + * This function generates a pseudo filter code representation of the given + * filter collection and writes it to the given fd. Returns zero on success, + * negative values on failure. + * + */ +int gen_pfc_generate(const struct db_filter_col *col, int fd) +{ + int rc = 0; + int newfd; + unsigned int iter; + FILE *fds; + + newfd = dup(fd); + if (newfd < 0) + return errno; + fds = fdopen(newfd, "a"); + if (fds == NULL) { + close(newfd); + return errno; + } + + /* generate the pfc */ + fprintf(fds, "#\n"); + fprintf(fds, "# pseudo filter code start\n"); + fprintf(fds, "#\n"); + + for (iter = 0; iter < col->filter_cnt; iter++) + _gen_pfc_arch(col, col->filters[iter], fds); + + fprintf(fds, "# invalid architecture action\n"); + _pfc_action(fds, col->attr.act_badarch); fprintf(fds, "#\n"); fprintf(fds, "# pseudo filter code end\n"); fprintf(fds, "#\n"); @@ -277,11 +327,5 @@ int gen_pfc_generate(const struct db_filter_col *col, int fd) fflush(fds); fclose(fds); -generate_return: - while (p_head != NULL) { - p_iter = p_head; - p_head = p_head->next; - free(p_iter); - } return rc; } |