X-Git-Url: http://git.ieval.ro/?p=linux-seccomp.git;a=blobdiff_plain;f=libseccomp%2Ftools%2Fscmp_bpf_sim.c;fp=libseccomp%2Ftools%2Fscmp_bpf_sim.c;h=0000000000000000000000000000000000000000;hp=a0cf6d1d6f5397de44f2110d1c472a8f4ff2a6bb;hb=a7f80a138de41255578bc28d034438a295ecbb2e;hpb=a8d04cb21e9ce2cfa37d893162df3e4943d9e480 diff --git a/libseccomp/tools/scmp_bpf_sim.c b/libseccomp/tools/scmp_bpf_sim.c deleted file mode 100644 index a0cf6d1..0000000 --- a/libseccomp/tools/scmp_bpf_sim.c +++ /dev/null @@ -1,354 +0,0 @@ -/** - * BPF Simulator - * - * 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 -#include -#include -#include -#include -#include - -#include "bpf.h" -#include "util.h" - -#define BPF_PRG_MAX_LEN 4096 - -/** - * BPF simulator machine state - */ -struct sim_state { - uint32_t acc; - uint32_t temp[BPF_SCRATCH_SIZE]; -}; - -struct bpf_program { - size_t i_cnt; - bpf_instr_raw *i; -}; - -static unsigned int opt_verbose = 0; - -/** - * Print the usage information to stderr and exit - * @param program the name of the current program being invoked - * - * Print the usage information and exit with EINVAL. - * - */ -static void exit_usage(const char *program) -{ - fprintf(stderr, - "usage: %s -f [-v] [-h]" - " -a -s [-0 ] ... [-5 ]\n", - program); - exit(EINVAL); -} - -/** - * Handle a simulator fault - * @param rc the error or return code - * - * Print a "FAULT" to stderr to indicate a simulator fault, and an errno value - * if the simulator is running in verbose mode, then exit with EFAULT. - * - */ -static void exit_fault(unsigned int rc) -{ - if (opt_verbose) - fprintf(stderr, "FAULT: errno = %d\n", rc); - else - fprintf(stderr, "FAULT\n"); - exit(EFAULT); -} - -/** - * Handle a BPF program error - * @param rc the error or return code - * @param line the line number - * - * Print an "ERROR" to stderr to indicate a program error, and an errno value - * if the simulator is running in verbose mode, then exit with ENOEXEC. - * - */ -static void exit_error(unsigned int rc, unsigned int line) -{ - if (opt_verbose) - fprintf(stderr, "ERROR: errno = %d, line = %d\n", rc, line); - else - fprintf(stderr, "ERROR\n"); - exit(ENOEXEC); -} - -/** - * Handle a simulator return/action - * @param action the return value - * @param line the line number - * - * Display the action to stdout and exit with 0. - * - */ -static void end_action(uint32_t action, unsigned int line) -{ - uint32_t act = action & SECCOMP_RET_ACTION; - uint32_t data = action & SECCOMP_RET_DATA; - - switch (act) { - case SECCOMP_RET_KILL: - fprintf(stdout, "KILL\n"); - break; - case SECCOMP_RET_TRAP: - fprintf(stdout, "TRAP\n"); - break; - case SECCOMP_RET_ERRNO: - fprintf(stdout, "ERRNO(%u)\n", data); - break; - case SECCOMP_RET_TRACE: - fprintf(stdout, "TRACE(%u)\n", data); - break; - case SECCOMP_RET_ALLOW: - fprintf(stdout, "ALLOW\n"); - break; - default: - exit_error(EDOM, line); - } - - exit(0); -} - -/** - * Execute a BPF program - * @param prg the loaded BPF program - * @param sys_data the syscall record being tested - * - * Simulate the BPF program with the given syscall record. - * - */ -static void bpf_execute(const struct bpf_program *prg, - const struct seccomp_data *sys_data) -{ - unsigned int ip, ip_c; - struct sim_state state; - bpf_instr_raw *bpf; - unsigned char *sys_data_b = (unsigned char *)sys_data; - uint16_t code; - uint8_t jt; - uint8_t jf; - uint32_t k; - - /* initialize the machine state */ - ip_c = 0; - ip = 0; - memset(&state, 0, sizeof(state)); - - while (ip < prg->i_cnt) { - /* get the instruction and bump the ip */ - ip_c = ip; - bpf = &prg->i[ip++]; - - code = ttoh16(arch, bpf->code); - jt = bpf->jt; - jf = bpf->jf; - k = ttoh32(arch, bpf->k); - - switch (code) { - case BPF_LD+BPF_W+BPF_ABS: - if (k < BPF_SYSCALL_MAX) { - uint32_t val = *((uint32_t *)&sys_data_b[k]); - state.acc = ttoh32(arch, val); - } else - exit_error(ERANGE, ip_c); - break; - case BPF_ALU+BPF_OR+BPF_K: - state.acc |= k; - break; - case BPF_ALU+BPF_AND+BPF_K: - state.acc &= k; - break; - case BPF_JMP+BPF_JA: - ip += k; - break; - case BPF_JMP+BPF_JEQ+BPF_K: - if (state.acc == k) - ip += jt; - else - ip += jf; - break; - case BPF_JMP+BPF_JGT+BPF_K: - if (state.acc > k) - ip += jt; - else - ip += jf; - break; - case BPF_JMP+BPF_JGE+BPF_K: - if (state.acc >= k) - ip += jt; - else - ip += jf; - break; - case BPF_RET+BPF_K: - end_action(k, ip_c); - break; - default: - /* since we don't support the full bpf language just - * yet, this could be either a fault or an error, we'll - * treat it as a fault until we provide full support */ - exit_fault(EOPNOTSUPP); - } - } - - /* if we've reached here there is a problem with the program */ - exit_error(ERANGE, ip_c); -} - -/** - * main - */ -int main(int argc, char *argv[]) -{ - int opt; - int iter; - char *opt_file = NULL; - FILE *file; - size_t file_read_len; - struct seccomp_data sys_data; - struct bpf_program bpf_prg; - - /* initialize the syscall record */ - memset(&sys_data, 0, sizeof(sys_data)); - - /* parse the command line */ - while ((opt = getopt(argc, argv, "a:f:hs:v0:1:2:3:4:5:")) > 0) { - switch (opt) { - case 'a': - if (strcmp(optarg, "x86") == 0) - arch = AUDIT_ARCH_I386; - else if (strcmp(optarg, "x86_64") == 0) - arch = AUDIT_ARCH_X86_64; - else if (strcmp(optarg, "x32") == 0) - arch = AUDIT_ARCH_X86_64; - else if (strcmp(optarg, "arm") == 0) - arch = AUDIT_ARCH_ARM; - else if (strcmp(optarg, "aarch64") == 0) - arch = AUDIT_ARCH_AARCH64; - else if (strcmp(optarg, "mips") == 0) - arch = AUDIT_ARCH_MIPS; - else if (strcmp(optarg, "mipsel") == 0) - arch = AUDIT_ARCH_MIPSEL; - else if (strcmp(optarg, "mips64") == 0) - arch = AUDIT_ARCH_MIPS64; - else if (strcmp(optarg, "mipsel64") == 0) - arch = AUDIT_ARCH_MIPSEL64; - else if (strcmp(optarg, "mips64n32") == 0) - arch = AUDIT_ARCH_MIPS64N32; - else if (strcmp(optarg, "mipsel64n32") == 0) - arch = AUDIT_ARCH_MIPSEL64N32; - else if (strcmp(optarg, "ppc") == 0) - arch = AUDIT_ARCH_PPC; - else if (strcmp(optarg, "ppc64") == 0) - arch = AUDIT_ARCH_PPC64; - else if (strcmp(optarg, "ppc64le") == 0) - arch = AUDIT_ARCH_PPC64LE; - else if (strcmp(optarg, "s390") == 0) - arch = AUDIT_ARCH_S390; - else if (strcmp(optarg, "s390x") == 0) - arch = AUDIT_ARCH_S390X; - else - exit_fault(EINVAL); - break; - case 'f': - opt_file = strdup(optarg); - if (opt_file == NULL) - exit_fault(ENOMEM); - break; - case 's': - sys_data.nr = strtol(optarg, NULL, 0); - break; - case 'v': - opt_verbose = 1; - break; - case '0': - sys_data.args[0] = strtoull(optarg, NULL, 0); - break; - case '1': - sys_data.args[1] = strtoull(optarg, NULL, 0); - break; - case '2': - sys_data.args[2] = strtoull(optarg, NULL, 0); - break; - case '3': - sys_data.args[3] = strtoull(optarg, NULL, 0); - break; - case '4': - sys_data.args[4] = strtoull(optarg, NULL, 0); - break; - case '5': - sys_data.args[5] = strtoull(optarg, NULL, 0); - break; - case 'h': - default: - /* usage information */ - exit_usage(argv[0]); - } - } - - /* adjust the endianess of sys_data to match the target */ - sys_data.nr = htot32(arch, sys_data.nr); - sys_data.arch = htot32(arch, arch); - sys_data.instruction_pointer = htot64(arch, - sys_data.instruction_pointer); - for (iter = 0; iter < BPF_SYS_ARG_MAX; iter++) - sys_data.args[iter] = htot64(arch, sys_data.args[iter]); - - /* allocate space for the bpf program */ - /* XXX - we should make this dynamic */ - bpf_prg.i_cnt = 0; - bpf_prg.i = calloc(BPF_PRG_MAX_LEN, sizeof(*bpf_prg.i)); - if (bpf_prg.i == NULL) - exit_fault(ENOMEM); - - /* load the bpf program */ - file = fopen(opt_file, "r"); - if (file == NULL) - exit_fault(errno); - do { - file_read_len = fread(&(bpf_prg.i[bpf_prg.i_cnt]), - sizeof(*bpf_prg.i), 1, file); - if (file_read_len == 1) - bpf_prg.i_cnt++; - - /* check the size */ - if (bpf_prg.i_cnt == BPF_PRG_MAX_LEN) - exit_fault(E2BIG); - } while (file_read_len > 0); - fclose(file); - - /* execute the bpf program */ - bpf_execute(&bpf_prg, &sys_data); - - /* we should never reach here */ - exit_fault(EFAULT); - return 0; -}