X-Git-Url: http://git.ieval.ro/?p=linux-seccomp.git;a=blobdiff_plain;f=libseccomp%2Ftools%2Fscmp_bpf_disasm.c;fp=libseccomp%2Ftools%2Fscmp_bpf_disasm.c;h=0000000000000000000000000000000000000000;hp=e8e376b0448ae581ddfed202c1ed8ee46100c9e0;hb=a7f80a138de41255578bc28d034438a295ecbb2e;hpb=a8d04cb21e9ce2cfa37d893162df3e4943d9e480 diff --git a/libseccomp/tools/scmp_bpf_disasm.c b/libseccomp/tools/scmp_bpf_disasm.c deleted file mode 100644 index e8e376b..0000000 --- a/libseccomp/tools/scmp_bpf_disasm.c +++ /dev/null @@ -1,529 +0,0 @@ -/** - * BPF Disassembler - * - * 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 - -#include "bpf.h" -#include "util.h" - -#define _OP_FMT "%-3s" - -/** - * 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 -a [-d] [-h]\n", program); - exit(EINVAL); -} - -/** - * Decode the BPF operand - * @param bpf the BPF instruction - * - * Decode the BPF operand and print it to stdout. - * - */ -static const char *bpf_decode_op(const bpf_instr_raw *bpf) -{ - switch (bpf->code) { - case BPF_LD+BPF_W+BPF_IMM: - case BPF_LD+BPF_W+BPF_ABS: - case BPF_LD+BPF_W+BPF_IND: - case BPF_LD+BPF_W+BPF_MEM: - case BPF_LD+BPF_W+BPF_LEN: - case BPF_LD+BPF_W+BPF_MSH: - return "ld"; - case BPF_LD+BPF_H+BPF_IMM: - case BPF_LD+BPF_H+BPF_ABS: - case BPF_LD+BPF_H+BPF_IND: - case BPF_LD+BPF_H+BPF_MEM: - case BPF_LD+BPF_H+BPF_LEN: - case BPF_LD+BPF_H+BPF_MSH: - return "ldh"; - case BPF_LD+BPF_B+BPF_IMM: - case BPF_LD+BPF_B+BPF_ABS: - case BPF_LD+BPF_B+BPF_IND: - case BPF_LD+BPF_B+BPF_MEM: - case BPF_LD+BPF_B+BPF_LEN: - case BPF_LD+BPF_B+BPF_MSH: - return "ldb"; - case BPF_LDX+BPF_W+BPF_IMM: - case BPF_LDX+BPF_W+BPF_ABS: - case BPF_LDX+BPF_W+BPF_IND: - case BPF_LDX+BPF_W+BPF_MEM: - case BPF_LDX+BPF_W+BPF_LEN: - case BPF_LDX+BPF_W+BPF_MSH: - case BPF_LDX+BPF_H+BPF_IMM: - case BPF_LDX+BPF_H+BPF_ABS: - case BPF_LDX+BPF_H+BPF_IND: - case BPF_LDX+BPF_H+BPF_MEM: - case BPF_LDX+BPF_H+BPF_LEN: - case BPF_LDX+BPF_H+BPF_MSH: - case BPF_LDX+BPF_B+BPF_IMM: - case BPF_LDX+BPF_B+BPF_ABS: - case BPF_LDX+BPF_B+BPF_IND: - case BPF_LDX+BPF_B+BPF_MEM: - case BPF_LDX+BPF_B+BPF_LEN: - case BPF_LDX+BPF_B+BPF_MSH: - return "ldx"; - case BPF_ST: - return "st"; - case BPF_STX: - return "stx"; - case BPF_ALU+BPF_ADD+BPF_K: - case BPF_ALU+BPF_ADD+BPF_X: - return "add"; - case BPF_ALU+BPF_SUB+BPF_K: - case BPF_ALU+BPF_SUB+BPF_X: - return "sub"; - case BPF_ALU+BPF_MUL+BPF_K: - case BPF_ALU+BPF_MUL+BPF_X: - return "mul"; - case BPF_ALU+BPF_DIV+BPF_K: - case BPF_ALU+BPF_DIV+BPF_X: - return "div"; - case BPF_ALU+BPF_OR+BPF_K: - case BPF_ALU+BPF_OR+BPF_X: - return "or"; - case BPF_ALU+BPF_AND+BPF_K: - case BPF_ALU+BPF_AND+BPF_X: - return "and"; - case BPF_ALU+BPF_LSH+BPF_K: - case BPF_ALU+BPF_LSH+BPF_X: - return "lsh"; - case BPF_ALU+BPF_RSH+BPF_K: - case BPF_ALU+BPF_RSH+BPF_X: - return "rsh"; - case BPF_ALU+BPF_NEG+BPF_K: - case BPF_ALU+BPF_NEG+BPF_X: - return "neg"; - case BPF_JMP+BPF_JA+BPF_K: - case BPF_JMP+BPF_JA+BPF_X: - return "jmp"; - case BPF_JMP+BPF_JEQ+BPF_K: - case BPF_JMP+BPF_JEQ+BPF_X: - return "jeq"; - case BPF_JMP+BPF_JGT+BPF_K: - case BPF_JMP+BPF_JGT+BPF_X: - return "jgt"; - case BPF_JMP+BPF_JGE+BPF_K: - case BPF_JMP+BPF_JGE+BPF_X: - return "jge"; - case BPF_JMP+BPF_JSET+BPF_K: - case BPF_JMP+BPF_JSET+BPF_X: - return "jset"; - case BPF_RET+BPF_K: - case BPF_RET+BPF_X: - case BPF_RET+BPF_A: - return "ret"; - case BPF_MISC+BPF_TAX: - return "tax"; - case BPF_MISC+BPF_TXA: - return "txa"; - } - return "???"; -} - -/** - * Decode a RET action - * @param k the return action - * - * Decode the action and print it to stdout. - * - */ -static void bpf_decode_action(uint32_t k) -{ - uint32_t act = k & SECCOMP_RET_ACTION; - uint32_t data = k & SECCOMP_RET_DATA; - - switch (act) { - case SECCOMP_RET_KILL: - printf("KILL"); - break; - case SECCOMP_RET_TRAP: - printf("TRAP"); - break; - case SECCOMP_RET_ERRNO: - printf("ERRNO(%u)", data); - break; - case SECCOMP_RET_TRACE: - printf("TRACE(%u)", data); - break; - case SECCOMP_RET_ALLOW: - printf("ALLOW"); - break; - default: - printf("0x%.8x", k); - } -} - -/** - * Decode the BPF arguments (JT, JF, and K) - * @param bpf the BPF instruction - * @param line the current line number - * - * Decode the BPF arguments (JT, JF, and K) and print the relevant information - * to stdout based on the operand. - * - */ -static void bpf_decode_args(const bpf_instr_raw *bpf, unsigned int line) -{ - switch (BPF_CLASS(bpf->code)) { - case BPF_LD: - case BPF_LDX: - switch (BPF_MODE(bpf->code)) { - case BPF_ABS: - printf("$data[%u]", bpf->k); - break; - case BPF_MEM: - printf("$temp[%u]", bpf->k); - break; - case BPF_IMM: - printf("%u", bpf->k); - break; - case BPF_IND: - printf("$data[X + %u]", bpf->k); - break; - case BPF_LEN: - printf("len($data)"); - break; - case BPF_MSH: - printf("4 * $data[%u] & 0x0f", bpf->k); - break; - } - break; - case BPF_ST: - case BPF_STX: - printf("$temp[%u]", bpf->k); - break; - case BPF_ALU: - if (BPF_SRC(bpf->code) == BPF_K) { - switch (BPF_OP(bpf->code)) { - case BPF_OR: - case BPF_AND: - printf("0x%.8x", bpf->k); - break; - default: - printf("%u", bpf->k); - } - } else - printf("%u", bpf->k); - break; - case BPF_JMP: - if (BPF_OP(bpf->code) == BPF_JA) { - printf("%.4u", (line + 1) + bpf->k); - } else { - printf("%-4u true:%.4u false:%.4u", - bpf->k, - (line + 1) + bpf->jt, - (line + 1) + bpf->jf); - } - break; - case BPF_RET: - if (BPF_RVAL(bpf->code) == BPF_A) { - /* XXX - accumulator? */ - printf("$acc"); - } else if (BPF_SRC(bpf->code) == BPF_K) { - bpf_decode_action(bpf->k); - } else if (BPF_SRC(bpf->code) == BPF_X) { - /* XXX - any idea? */ - printf("???"); - } - break; - case BPF_MISC: - break; - default: - printf("???"); - } -} - -/** - * Perform a simple decoding of the BPF program - * @param file the BPF program - * - * Read the BPF program and display the instructions. Returns zero on success, - * negative values on failure. - * - */ -static int bpf_decode(FILE *file) -{ - unsigned int line = 0; - size_t len; - bpf_instr_raw bpf; - - /* header */ - printf(" line OP JT JF K\n"); - printf("=================================\n"); - - while ((len = fread(&bpf, sizeof(bpf), 1, file))) { - /* convert the bpf statement */ - bpf.code = ttoh16(arch, bpf.code); - bpf.k = ttoh32(arch, bpf.k); - - /* display a hex dump */ - printf(" %.4u: 0x%.2x 0x%.2x 0x%.2x 0x%.8x", - line, bpf.code, bpf.jt, bpf.jf, bpf.k); - - /* display the assembler statements */ - printf(" "); - printf(_OP_FMT, bpf_decode_op(&bpf)); - printf(" "); - bpf_decode_args(&bpf, line); - printf("\n"); - - line++; - } - - if (ferror(file)) - return errno; - return 0; -} - -/** - * Decode the BPF arguments (JT, JF, and K) - * @param bpf the BPF instruction - * @param line the current line number - * - * Decode the BPF arguments (JT, JF, and K) and print the relevant information - * to stdout based on the operand. - * - */ -static void bpf_dot_decode_args(const bpf_instr_raw *bpf, unsigned int line) -{ - const char *op = bpf_decode_op(bpf); - - printf("\tline%d[label=\"%s", line, op); - switch (BPF_CLASS(bpf->code)) { - case BPF_LD: - case BPF_LDX: - switch (BPF_MODE(bpf->code)) { - case BPF_ABS: - printf(" $data[%u]\",shape=parallelogram]\n", bpf->k); - break; - case BPF_MEM: - printf(" $temp[%u]\",shape=parallelogram]\n", bpf->k); - break; - case BPF_IMM: - printf(" %u\",shape=parallelogram]\n", bpf->k); - break; - case BPF_IND: - printf(" $data[X + %u]\",shape=parallelogram]\n", bpf->k); - break; - case BPF_LEN: - printf(" len($data)\",shape=parallelogram]\n"); - break; - case BPF_MSH: - printf(" 4 * $data[%u] & 0x0f\",shape=parallelogram]\n", bpf->k); - break; - } - break; - case BPF_ST: - case BPF_STX: - printf(" $temp[%u]\",shape=parallelogram]\n", - bpf->k); - break; - case BPF_ALU: - if (BPF_SRC(bpf->code) == BPF_K) { - switch (BPF_OP(bpf->code)) { - case BPF_OR: - case BPF_AND: - printf(" 0x%.8x\",shape=rectangle]\n", bpf->k); - break; - default: - printf(" %u\",shape=rectangle]\n", bpf->k); - } - } else - printf(" %u\",shape=rectangle]\n", bpf->k); - break; - case BPF_JMP: - if (BPF_OP(bpf->code) == BPF_JA) { - printf("\",shape=hexagon]\n"); - printf("\tline%d -> line%d\n", - line, (line + 1) + bpf->k); - } else { - printf(" %-4u", bpf->k); - /* Heuristic: if k > 256, also emit hex version */ - if (bpf->k > 256) - printf("\\n(0x%.8x)", bpf->k); - printf("\",shape=diamond]\n"); - printf("\tline%d -> line%d [label=\"true\"]\n", - line, (line + 1) + bpf->jt); - printf("\tline%d -> line%d [label=\"false\"]\n", - line, (line + 1) + bpf->jf); - } - break; - case BPF_RET: - if (BPF_RVAL(bpf->code) == BPF_A) { - /* XXX - accumulator? */ - printf(" $acc\", shape=\"box\", style=rounded]\n"); - } else if (BPF_SRC(bpf->code) == BPF_K) { - printf(" "); - bpf_decode_action(bpf->k); - printf("\", shape=\"box\", style=rounded]\n"); - } else if (BPF_SRC(bpf->code) == BPF_X) { - /* XXX - any idea? */ - printf(" ???\", shape=\"box\", style=rounded]\n"); - } - break; - case BPF_MISC: - printf("\"]\n"); - break; - default: - printf(" ???\"]\n"); - } -} - -/** - * Perform a simple decoding of the BPF program to a dot graph - * @param file the BPF program - * - * Read the BPF program and display the instructions. Returns zero on success, - * negative values on failure. - * - */ -static int bpf_dot_decode(FILE *file) -{ - unsigned int line = 0; - size_t len; - bpf_instr_raw bpf; - int prev_class = 0; - - /* header */ - printf("digraph {\n"); - printf("\tstart[shape=\"box\", style=rounded];\n"); - - while ((len = fread(&bpf, sizeof(bpf), 1, file))) { - /* convert the bpf statement */ - bpf.code = ttoh16(arch, bpf.code); - bpf.k = ttoh32(arch, bpf.k); - - /* display the statement */ - bpf_dot_decode_args(&bpf, line); - - /* if previous line wasn't RET/JMP, link it to this line */ - if (line == 0) - printf("\tstart -> line%d\n", line); - else if ((prev_class != BPF_JMP) && (prev_class != BPF_RET)) - printf("\tline%d -> line%d\n", line - 1, line); - prev_class = BPF_CLASS(bpf.code); - - line++; - } - printf("}\n"); - - if (ferror(file)) - return errno; - return 0; -} - -/** - * main - */ -int main(int argc, char *argv[]) -{ - int rc; - int opt; - bool dot_out = false; - FILE *file; - - /* parse the command line */ - while ((opt = getopt(argc, argv, "a:dh")) > 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, "ppc64") == 0) - arch = AUDIT_ARCH_PPC64; - else if (strcmp(optarg, "ppc64le") == 0) - arch = AUDIT_ARCH_PPC64LE; - else if (strcmp(optarg, "ppc") == 0) - arch = AUDIT_ARCH_PPC; - else if (strcmp(optarg, "s390") == 0) - arch = AUDIT_ARCH_S390; - else if (strcmp(optarg, "s390x") == 0) - arch = AUDIT_ARCH_S390X; - else - exit_usage(argv[0]); - break; - case 'd': - dot_out = true; - break; - default: - /* usage information */ - exit_usage(argv[0]); - } - } - - if ((optind > 1) && (optind < argc)) { - int opt_file = optind - 1 ; - file = fopen(argv[opt_file], "r"); - if (file == NULL) { - fprintf(stderr, "error: unable to open \"%s\" (%s)\n", - argv[opt_file], strerror(errno)); - return errno; - } - } else - file = stdin; - - if (dot_out) - rc = bpf_dot_decode(file); - else - rc = bpf_decode(file); - fclose(file); - - return rc; -}