From f9c60d5a3aaecc11b1dbb933bca45c461b03ca83 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 28 Dec 2017 12:28:08 -0500 Subject: replacing seccomp printing with a seccomp disassembler --- src/fsec-print/print.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 src/fsec-print/print.c (limited to 'src/fsec-print/print.c') diff --git a/src/fsec-print/print.c b/src/fsec-print/print.c new file mode 100644 index 000000000..964a3a8a9 --- /dev/null +++ b/src/fsec-print/print.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2014-2017 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * + * Parts of this code was lifted from libseccomp project, license LGPV 2.1. + * This is the original copyright notice in libseccomp code: + * + * + * + * 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 "fsec_print.h" + +// From /usr/include/linux/filter.h +//struct sock_filter { /* Filter block */ +// __u16 code; /* Actual filter code */ +// __u8 jt; /* Jump true */ +// __u8 jf; /* Jump false */ +// __u32 k; /* Generic multiuse field */ +//}; + + +static const char *bpf_decode_op(const struct sock_filter *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_ALU+BPF_MOD+BPF_K: + case BPF_ALU+BPF_MOD+BPF_X: + return "mod"; + case BPF_ALU+BPF_XOR+BPF_K: + case BPF_ALU+BPF_XOR+BPF_X: + return "xor"; + 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 "???"; +} + +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_LOG: + printf("LOG"); + break; + case SECCOMP_RET_ALLOW: + printf("ALLOW"); + break; + default: + printf("0x%.8x", k); + } +} + + +// implementing a simple state machine around accumulator +// in order to translate the syscall number +int syscall_loaded = 0; +int native_arch = 0; + +static void bpf_decode_args(const struct sock_filter *bpf, unsigned int line) { + switch (BPF_CLASS(bpf->code)) { + case BPF_LD: + case BPF_LDX: + switch (BPF_MODE(bpf->code)) { + case BPF_ABS: + syscall_loaded = 0; + if (bpf->k == offsetof(struct seccomp_data, arch)) + printf("data.architecture"); + else if (bpf->k == offsetof(struct seccomp_data, nr)) { + printf("data.syscall-number"); + syscall_loaded = 1; + } + else if (bpf->k == offsetof(struct seccomp_data, nr)) + printf("data.instruction_pointer"); + else { + int index = bpf->k - offsetof(struct seccomp_data, args); + printf("data.args[%x]", index); + } + break; + case BPF_MEM: + printf("$temp[%u]", bpf->k); + break; + case BPF_IMM: + printf("%x", bpf->k); + break; + case BPF_IND: + printf("$data[X + %x]", bpf->k); + break; + case BPF_LEN: + printf("len($data)"); + break; + case BPF_MSH: + printf("4 * $data[%x] & 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("%.8x", bpf->k); + break; + default: + printf("%x", 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 { + const char *name = NULL; + if (syscall_loaded && native_arch) + name = syscall_find_nr(bpf->k); + if (bpf->k == ARCH_32) { + printf("ARCH_32 %.4x (false %.4x)", + (line + 1) + bpf->jt, + (line + 1) + bpf->jf); + native_arch = (ARCH_NR == ARCH_32)? 1: 0; + } + else if (bpf->k == ARCH_64) { + printf("ARCH_64 %.4x (false %.4x)", + (line + 1) + bpf->jt, + (line + 1) + bpf->jf); + native_arch = (ARCH_NR == ARCH_64)? 1: 0; + } + else if (bpf->k == X32_SYSCALL_BIT) + printf("X32_ABI true:%.4x (false %.4x)", + (line + 1) + bpf->jt, + (line + 1) + bpf->jf); + else if (name) + printf("%s %.4x (false %.4x)", + name, + (line + 1) + bpf->jt, + (line + 1) + bpf->jf); + else + printf("%x %.4x (false %.4x)", + 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("???"); + } +} + +void print(struct sock_filter *filter, int entries) { + unsigned int line = 0; + int i; + + /* header */ + printf(" line OP JT JF K\n"); + printf("=================================\n"); + struct sock_filter *bpf = filter; + for (i = 0; i < entries; i++, bpf++) { + + /* convert the bpf statement */ +// bpf.code = ttoh16(arch, bpf.code); +// bpf.k = ttoh32(arch, bpf.k); + + /* display a hex dump */ + printf(" %.4x: %.2x %.2x %.2x %.8x", + i, bpf->code, bpf->jt, bpf->jf, bpf->k); + + /* display the assembler statements */ + printf(" "); + printf("%-3s", bpf_decode_op(bpf)); + printf(" "); + bpf_decode_args(bpf, i); + + printf("\n"); + } +} + -- cgit v1.2.3-70-g09d2