X-Git-Url: http://git.ieval.ro/?p=linux-seccomp.git;a=blobdiff_plain;f=libseccomp%2Fsrc%2Fgen_pfc.c;fp=libseccomp%2Fsrc%2Fgen_pfc.c;h=0000000000000000000000000000000000000000;hp=99c3297a99696eaac14eb1fb1a9ea3ed22079e69;hb=a7f80a138de41255578bc28d034438a295ecbb2e;hpb=a8d04cb21e9ce2cfa37d893162df3e4943d9e480 diff --git a/libseccomp/src/gen_pfc.c b/libseccomp/src/gen_pfc.c deleted file mode 100644 index 99c3297..0000000 --- a/libseccomp/src/gen_pfc.c +++ /dev/null @@ -1,363 +0,0 @@ -/** - * Seccomp Pseudo Filter Code (PFC) Generator - * - * Copyright (c) 2012 Red Hat - * Author: Paul Moore - */ - -/* - * This library is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License as - * published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, see . - */ - -#include -#include -#include -#include -#include -#include - -/* NOTE: needed for the arch->token decoding in _pfc_arch() */ -#include - -#include - -#include "arch.h" -#include "db.h" -#include "gen_pfc.h" - -struct pfc_sys_list { - struct db_sys_list *sys; - struct pfc_sys_list *next; -}; - -/* 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 SCMP_ARCH_X86: - return "x86"; - case SCMP_ARCH_X86_64: - return "x86_64"; - case SCMP_ARCH_X32: - return "x32"; - case SCMP_ARCH_ARM: - return "arm"; - case SCMP_ARCH_AARCH64: - return "aarch64"; - case SCMP_ARCH_MIPS: - return "mips"; - case SCMP_ARCH_MIPSEL: - return "mipsel"; - case SCMP_ARCH_MIPS64: - return "mips64"; - case SCMP_ARCH_MIPSEL64: - return "mipsel64"; - case SCMP_ARCH_MIPS64N32: - return "mips64n32"; - case SCMP_ARCH_MIPSEL64N32: - return "mipsel64n32"; - case SCMP_ARCH_PPC64: - return "ppc64"; - case SCMP_ARCH_PPC64LE: - return "ppc64le"; - case SCMP_ARCH_PPC: - return "ppc"; - case SCMP_ARCH_S390X: - return "s390x"; - case SCMP_ARCH_S390: - return "s390"; - 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 - * @param node the node - */ -static void _pfc_arg(FILE *fds, - const struct arch_def *arch, - const struct db_arg_chain_tree *node) -{ - if (arch->size == ARCH_SIZE_64) { - if (arch_arg_offset_hi(arch, node->arg) == node->arg_offset) - fprintf(fds, "$a%d.hi32", node->arg); - else - fprintf(fds, "$a%d.lo32", node->arg); - } else - fprintf(fds, "$a%d", node->arg); -} - -/** - * Display a string representation of the filter action - * @param fds the file stream to send the output - * @param action the action - */ -static void _pfc_action(FILE *fds, uint32_t action) -{ - switch (action & 0xffff0000) { - case SCMP_ACT_KILL: - fprintf(fds, "action KILL;\n"); - break; - case SCMP_ACT_TRAP: - fprintf(fds, "action TRAP;\n"); - break; - case SCMP_ACT_ERRNO(0): - fprintf(fds, "action ERRNO(%u);\n", (action & 0x0000ffff)); - break; - case SCMP_ACT_TRACE(0): - fprintf(fds, "action TRACE(%u);\n", (action & 0x0000ffff)); - break; - case SCMP_ACT_ALLOW: - fprintf(fds, "action ALLOW;\n"); - break; - default: - fprintf(fds, "action 0x%x;\n", action); - } -} - -/** - * Indent the output stream - * @param fds the file stream to send the output - * @param lvl the indentation level - * - * This function indents the output stream with whitespace based on the - * requested indentation level. - */ -static void _indent(FILE *fds, unsigned int lvl) -{ - while (lvl-- > 0) - fprintf(fds, " "); -} - -/** - * Generate the pseudo filter code for an argument chain - * @param arch the architecture definition - * @param node the head of the argument chain - * @param lvl the indentation level - * @param fds the file stream to send the output - * - * This function generates the pseudo filter code representation of the given - * argument chain and writes it to the given output stream. - * - */ -static void _gen_pfc_chain(const struct arch_def *arch, - const struct db_arg_chain_tree *node, - unsigned int lvl, FILE *fds) -{ - const struct db_arg_chain_tree *c_iter; - - /* get to the start */ - c_iter = node; - while (c_iter->lvl_prv != NULL) - c_iter = c_iter->lvl_prv; - - while (c_iter != NULL) { - /* comparison operation */ - _indent(fds, lvl); - fprintf(fds, "if ("); - _pfc_arg(fds, arch, c_iter); - switch (c_iter->op) { - case SCMP_CMP_EQ: - fprintf(fds, " == "); - break; - case SCMP_CMP_GE: - fprintf(fds, " >= "); - break; - case SCMP_CMP_GT: - fprintf(fds, " > "); - break; - case SCMP_CMP_MASKED_EQ: - fprintf(fds, " & 0x%.8x == ", c_iter->mask); - break; - case SCMP_CMP_NE: - case SCMP_CMP_LT: - case SCMP_CMP_LE: - default: - fprintf(fds, " ??? "); - } - fprintf(fds, "%u)\n", c_iter->datum); - - /* true result */ - if (c_iter->act_t_flg) { - _indent(fds, lvl + 1); - _pfc_action(fds, c_iter->act_t); - } else if (c_iter->nxt_t != NULL) - _gen_pfc_chain(arch, c_iter->nxt_t, lvl + 1, fds); - - /* false result */ - if (c_iter->act_f_flg) { - _indent(fds, lvl); - 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"); - _gen_pfc_chain(arch, c_iter->nxt_f, lvl + 1, fds); - } - - c_iter = c_iter->lvl_nxt; - } -} - -/** - * Generate pseudo filter code for a syscall - * @param arch the architecture definition - * @param sys the syscall filter - * @param fds the file stream to send the output - * - * This function generates a pseduo filter code representation of the given - * syscall filter and writes it to the given output stream. - * - */ -static void _gen_pfc_syscall(const struct arch_def *arch, - const struct db_sys_list *sys, FILE *fds) -{ - unsigned int sys_num = sys->num; - const char *sys_name = arch_syscall_resolve_num(arch, sys_num); - - _indent(fds, 1); - fprintf(fds, "# filter for syscall \"%s\" (%d) [priority: %d]\n", - (sys_name ? sys_name : "UNKNOWN"), sys_num, sys->priority); - _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 pseudo filter code for an architecture - * @param col the seccomp filter collection - * @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 DB and writes it to the given output stream. Returns zero on - * success, negative values on failure. - * - */ -static int _gen_pfc_arch(const struct db_filter_col *col, - const struct db_filter *db, FILE *fds) -{ - int rc = 0; - struct db_sys_list *s_iter; - struct pfc_sys_list *p_iter = NULL, *p_new, *p_head = NULL, *p_prev; - - /* sort the syscall list */ - db_list_foreach(s_iter, db->syscalls) { - p_new = malloc(sizeof(*p_new)); - if (p_new == NULL) { - rc = -ENOMEM; - goto arch_return; - } - memset(p_new, 0, sizeof(*p_new)); - p_new->sys = s_iter; - - p_prev = NULL; - p_iter = p_head; - while (p_iter != NULL && - s_iter->priority < p_iter->sys->priority) { - p_prev = p_iter; - p_iter = p_iter->next; - } - if (p_head == NULL) - p_head = p_new; - else if (p_prev == NULL) { - p_new->next = p_head; - p_head = p_new; - } else { - p_new->next = p_iter; - p_prev->next = p_new; - } - } - - fprintf(fds, "# filter for arch %s (%u)\n", - _pfc_arch(db->arch), db->arch->token_bpf); - fprintf(fds, "if ($arch == %u)\n", db->arch->token_bpf); - p_iter = p_head; - while (p_iter != NULL) { - if (!p_iter->sys->valid) - continue; - _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"); - - fflush(fds); - fclose(fds); - - return rc; -}