aboutgitcodelistschat:MatrixIRC
path: root/src/debug
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/Makefile37
-rw-r--r--src/debug/bpf_dbg.c32
-rw-r--r--src/debug/build.c33
-rw-r--r--src/debug/disasm.c281
-rw-r--r--src/debug/disasm.h14
5 files changed, 397 insertions, 0 deletions
diff --git a/src/debug/Makefile b/src/debug/Makefile
new file mode 100644
index 0000000..6ef7900
--- /dev/null
+++ b/src/debug/Makefile
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# seitan - Syscall Expressive Interpreter, Transformer and Notifier
+#
+# debug/Makefile - Makefile for debug utilities: bpf_dbg
+#
+# Copyright 2023 Red Hat GmbH
+# Author: Alice Frosi <afrosi@redhat.com>
+
+SRCS := bpf_dbg.c disasm.c
+HEADERS := disasm.h
+BIN := $(OUTDIR)bpf_dbg
+CFLAGS += -Wall -Wextra -pedantic
+
+# TODO: remove this part together with the build binary
+# when cooker is ready
+TARGET := $(shell $(CC) -dumpmachine)
+TARGET_ARCH := $(shell echo $(TARGET) | cut -f1 -d- | tr [A-Z] [a-z])
+TARGET_ARCH := $(shell echo $(TARGET_ARCH) | sed 's/powerpc/ppc/')
+
+AUDIT_ARCH := $(shell echo $(TARGET_ARCH) | tr [a-z] [A-Z] | sed 's/^ARM.*/ARM/')
+AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/I[456]86/I386/')
+AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPC64/PPC/')
+AUDIT_ARCH := $(shell echo $(AUDIT_ARCH) | sed 's/PPCLE/PPC64LE/')
+
+bpf_dbg: $(SRCS) $(HEADERS)
+ $(CC) $(CFLAGS) -o $(BIN) $(SRCS)
+
+# TODO: remove when cooker is ready
+build: build.c ../cooker/filter.c ../cooker/filter.h ../common/numbers.h
+ $(CC) $(CFLAGS) -I../common -I../cooker -DSEITAN_AUDIT_ARCH=AUDIT_ARCH_$(AUDIT_ARCH)\
+ -o $(OUTDIR)build ../cooker/filter.c build.c
+
+all: $(BIN)
+
+clean:
+ rm -f $(BIN) build
diff --git a/src/debug/bpf_dbg.c b/src/debug/bpf_dbg.c
new file mode 100644
index 0000000..b84c713
--- /dev/null
+++ b/src/debug/bpf_dbg.c
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright 2023 Red Hat GmbH
+ * Author: Alice Frosi <afrosi@redhat.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <linux/filter.h>
+#include <unistd.h>
+
+#include "disasm.h"
+
+int main(int argc, char **argv)
+{
+ struct sock_filter *filter;
+ size_t fd, n;
+
+ if (argc < 2) {
+ perror("missing input file");
+ exit(EXIT_FAILURE);
+ }
+ filter = calloc(SIZE_FILTER, sizeof(struct sock_filter));
+ fd = open(argv[1], O_CLOEXEC | O_RDONLY);
+
+ n = read(fd, filter, sizeof(struct sock_filter) * SIZE_FILTER);
+ close(fd);
+ printf("Read %ld entries\n", n / sizeof(struct sock_filter));
+ bpf_disasm_all(filter, n / sizeof(struct sock_filter));
+ free(filter);
+ return 0;
+}
diff --git a/src/debug/build.c b/src/debug/build.c
new file mode 100644
index 0000000..93ce97b
--- /dev/null
+++ b/src/debug/build.c
@@ -0,0 +1,33 @@
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "filter.h"
+
+struct bpf_call calls[] = {
+ {
+ .name = "connect",
+ .args = { 0, 111, 0, 0, 0, 0 },
+ .check_arg = { false, false, false, false, false, false },
+ },
+};
+
+int main(int argc, char **argv)
+{
+ int ret;
+ if (argc < 2) {
+ perror("missing input file");
+ exit(EXIT_FAILURE);
+ }
+ ret = convert_bpf(argv[1], calls, sizeof(calls) / sizeof(calls[0]),
+ true);
+ if (ret < 0) {
+ perror("converting bpf program");
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
diff --git a/src/debug/disasm.c b/src/debug/disasm.c
new file mode 100644
index 0000000..fae96b7
--- /dev/null
+++ b/src/debug/disasm.c
@@ -0,0 +1,281 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright 2023 Red Hat GmbH
+ * Author: Alice Frosi <afrosi@redhat.com>
+ */
+
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <linux/filter.h>
+
+#include "disasm.h"
+
+/* From linux tools/bpf/bpf_dbg.c */
+#define BPF_LDX_B (BPF_LDX | BPF_B)
+#define BPF_LDX_W (BPF_LDX | BPF_W)
+#define BPF_JMP_JA (BPF_JMP | BPF_JA)
+#define BPF_JMP_JEQ (BPF_JMP | BPF_JEQ)
+#define BPF_JMP_JGT (BPF_JMP | BPF_JGT)
+#define BPF_JMP_JGE (BPF_JMP | BPF_JGE)
+#define BPF_JMP_JSET (BPF_JMP | BPF_JSET)
+#define BPF_ALU_ADD (BPF_ALU | BPF_ADD)
+#define BPF_ALU_SUB (BPF_ALU | BPF_SUB)
+#define BPF_ALU_MUL (BPF_ALU | BPF_MUL)
+#define BPF_ALU_DIV (BPF_ALU | BPF_DIV)
+#define BPF_ALU_MOD (BPF_ALU | BPF_MOD)
+#define BPF_ALU_NEG (BPF_ALU | BPF_NEG)
+#define BPF_ALU_AND (BPF_ALU | BPF_AND)
+#define BPF_ALU_OR (BPF_ALU | BPF_OR)
+#define BPF_ALU_XOR (BPF_ALU | BPF_XOR)
+#define BPF_ALU_LSH (BPF_ALU | BPF_LSH)
+#define BPF_ALU_RSH (BPF_ALU | BPF_RSH)
+#define BPF_MISC_TAX (BPF_MISC | BPF_TAX)
+#define BPF_MISC_TXA (BPF_MISC | BPF_TXA)
+#define BPF_LD_B (BPF_LD | BPF_B)
+#define BPF_LD_H (BPF_LD | BPF_H)
+#define BPF_LD_W (BPF_LD | BPF_W)
+static const char *const op_table[] = {
+ [BPF_ST] = "st", [BPF_STX] = "stx", [BPF_LD_B] = "ldb",
+ [BPF_LD_H] = "ldh", [BPF_LD_W] = "ld", [BPF_LDX] = "ldx",
+ [BPF_LDX_B] = "ldxb", [BPF_JMP_JA] = "ja", [BPF_JMP_JEQ] = "jeq",
+ [BPF_JMP_JGT] = "jgt", [BPF_JMP_JGE] = "jge", [BPF_JMP_JSET] = "jset",
+ [BPF_ALU_ADD] = "add", [BPF_ALU_SUB] = "sub", [BPF_ALU_MUL] = "mul",
+ [BPF_ALU_DIV] = "div", [BPF_ALU_MOD] = "mod", [BPF_ALU_NEG] = "neg",
+ [BPF_ALU_AND] = "and", [BPF_ALU_OR] = "or", [BPF_ALU_XOR] = "xor",
+ [BPF_ALU_LSH] = "lsh", [BPF_ALU_RSH] = "rsh", [BPF_MISC_TAX] = "tax",
+ [BPF_MISC_TXA] = "txa", [BPF_RET] = "ret",
+};
+
+void bpf_disasm(const struct sock_filter f, unsigned int i)
+{
+ const char *op, *fmt;
+ int val = f.k;
+ char buf[256];
+
+ switch (f.code) {
+ case BPF_RET | BPF_K:
+ op = op_table[BPF_RET];
+ fmt = "#%#x";
+ break;
+ case BPF_RET | BPF_A:
+ op = op_table[BPF_RET];
+ fmt = "a";
+ break;
+ case BPF_RET | BPF_X:
+ op = op_table[BPF_RET];
+ fmt = "x";
+ break;
+ case BPF_MISC_TAX:
+ op = op_table[BPF_MISC_TAX];
+ fmt = "";
+ break;
+ case BPF_MISC_TXA:
+ op = op_table[BPF_MISC_TXA];
+ fmt = "";
+ break;
+ case BPF_ST:
+ op = op_table[BPF_ST];
+ fmt = "M[%d]";
+ break;
+ case BPF_STX:
+ op = op_table[BPF_STX];
+ fmt = "M[%d]";
+ break;
+ case BPF_LD_W | BPF_ABS:
+ op = op_table[BPF_LD_W];
+ fmt = "[%d]";
+ break;
+ case BPF_LD_H | BPF_ABS:
+ op = op_table[BPF_LD_H];
+ fmt = "[%d]";
+ break;
+ case BPF_LD_B | BPF_ABS:
+ op = op_table[BPF_LD_B];
+ fmt = "[%d]";
+ break;
+ case BPF_LD_W | BPF_LEN:
+ op = op_table[BPF_LD_W];
+ fmt = "#len";
+ break;
+ case BPF_LD_W | BPF_IND:
+ op = op_table[BPF_LD_W];
+ fmt = "[x+%d]";
+ break;
+ case BPF_LD_H | BPF_IND:
+ op = op_table[BPF_LD_H];
+ fmt = "[x+%d]";
+ break;
+ case BPF_LD_B | BPF_IND:
+ op = op_table[BPF_LD_B];
+ fmt = "[x+%d]";
+ break;
+ case BPF_LD | BPF_IMM:
+ op = op_table[BPF_LD_W];
+ fmt = "#%#x";
+ break;
+ case BPF_LDX | BPF_IMM:
+ op = op_table[BPF_LDX];
+ fmt = "#%#x";
+ break;
+ case BPF_LDX_B | BPF_MSH:
+ op = op_table[BPF_LDX_B];
+ fmt = "4*([%d]&0xf)";
+ break;
+ case BPF_LD | BPF_MEM:
+ op = op_table[BPF_LD_W];
+ fmt = "M[%d]";
+ break;
+ case BPF_LDX | BPF_MEM:
+ op = op_table[BPF_LDX];
+ fmt = "M[%d]";
+ break;
+ case BPF_JMP_JA:
+ op = op_table[BPF_JMP_JA];
+ fmt = "%d";
+ val = i + 1 + f.k;
+ break;
+ case BPF_JMP_JGT | BPF_X:
+ op = op_table[BPF_JMP_JGT];
+ fmt = "x";
+ break;
+ case BPF_JMP_JGT | BPF_K:
+ op = op_table[BPF_JMP_JGT];
+ fmt = "#%#x";
+ break;
+ case BPF_JMP_JGE | BPF_X:
+ op = op_table[BPF_JMP_JGE];
+ fmt = "x";
+ break;
+ case BPF_JMP_JGE | BPF_K:
+ op = op_table[BPF_JMP_JGE];
+ fmt = "#%#x";
+ break;
+ case BPF_JMP_JEQ | BPF_X:
+ op = op_table[BPF_JMP_JEQ];
+ fmt = "x";
+ break;
+ case BPF_JMP_JEQ | BPF_K:
+ op = op_table[BPF_JMP_JEQ];
+ fmt = "#%#x";
+ break;
+ case BPF_JMP_JSET | BPF_X:
+ op = op_table[BPF_JMP_JSET];
+ fmt = "x";
+ break;
+ case BPF_JMP_JSET | BPF_K:
+ op = op_table[BPF_JMP_JSET];
+ fmt = "#%#x";
+ break;
+ case BPF_ALU_NEG:
+ op = op_table[BPF_ALU_NEG];
+ fmt = "";
+ break;
+ case BPF_ALU_LSH | BPF_X:
+ op = op_table[BPF_ALU_LSH];
+ fmt = "x";
+ break;
+ case BPF_ALU_LSH | BPF_K:
+ op = op_table[BPF_ALU_LSH];
+ fmt = "#%d";
+ break;
+ case BPF_ALU_RSH | BPF_X:
+ op = op_table[BPF_ALU_RSH];
+ fmt = "x";
+ break;
+ case BPF_ALU_RSH | BPF_K:
+ op = op_table[BPF_ALU_RSH];
+ fmt = "#%d";
+ break;
+ case BPF_ALU_ADD | BPF_X:
+ op = op_table[BPF_ALU_ADD];
+ fmt = "x";
+ break;
+ case BPF_ALU_ADD | BPF_K:
+ op = op_table[BPF_ALU_ADD];
+ fmt = "#%d";
+ break;
+ case BPF_ALU_SUB | BPF_X:
+ op = op_table[BPF_ALU_SUB];
+ fmt = "x";
+ break;
+ case BPF_ALU_SUB | BPF_K:
+ op = op_table[BPF_ALU_SUB];
+ fmt = "#%d";
+ break;
+ case BPF_ALU_MUL | BPF_X:
+ op = op_table[BPF_ALU_MUL];
+ fmt = "x";
+ break;
+ case BPF_ALU_MUL | BPF_K:
+ op = op_table[BPF_ALU_MUL];
+ fmt = "#%d";
+ break;
+ case BPF_ALU_DIV | BPF_X:
+ op = op_table[BPF_ALU_DIV];
+ fmt = "x";
+ break;
+ case BPF_ALU_DIV | BPF_K:
+ op = op_table[BPF_ALU_DIV];
+ fmt = "#%d";
+ break;
+ case BPF_ALU_MOD | BPF_X:
+ op = op_table[BPF_ALU_MOD];
+ fmt = "x";
+ break;
+ case BPF_ALU_MOD | BPF_K:
+ op = op_table[BPF_ALU_MOD];
+ fmt = "#%d";
+ break;
+ case BPF_ALU_AND | BPF_X:
+ op = op_table[BPF_ALU_AND];
+ fmt = "x";
+ break;
+ case BPF_ALU_AND | BPF_K:
+ op = op_table[BPF_ALU_AND];
+ fmt = "#%#x";
+ break;
+ case BPF_ALU_OR | BPF_X:
+ op = op_table[BPF_ALU_OR];
+ fmt = "x";
+ break;
+ case BPF_ALU_OR | BPF_K:
+ op = op_table[BPF_ALU_OR];
+ fmt = "#%#x";
+ break;
+ case BPF_ALU_XOR | BPF_X:
+ op = op_table[BPF_ALU_XOR];
+ fmt = "x";
+ break;
+ case BPF_ALU_XOR | BPF_K:
+ op = op_table[BPF_ALU_XOR];
+ fmt = "#%#x";
+ break;
+ default:
+ op = "nosup";
+ fmt = "%#x";
+ val = f.code;
+ break;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf), fmt, val);
+ buf[sizeof(buf) - 1] = 0;
+
+ if ((BPF_CLASS(f.code) == BPF_JMP && BPF_OP(f.code) != BPF_JA)) {
+ printf("l%d:\t%s %s, l%d, l%d\n", i, op, buf, i + 1 + f.jt,
+ i + 1 + f.jf);
+ } else {
+ printf("l%d:\t%s %s\n", i, op, buf);
+ }
+}
+
+void bpf_disasm_all(const struct sock_filter *f, unsigned int len)
+{
+ unsigned int i;
+ for (i = 0; i < len; i++)
+ bpf_disasm(f[i], i);
+}
diff --git a/src/debug/disasm.h b/src/debug/disasm.h
new file mode 100644
index 0000000..c3e3ad9
--- /dev/null
+++ b/src/debug/disasm.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright 2023 Red Hat GmbH
+ * Author: Alice Frosi <afrosi@redhat.com>
+ */
+
+#ifndef DISASM_H_
+#define DISASM_H_
+
+#define SIZE_FILTER 1024
+
+void bpf_disasm(const struct sock_filter f, unsigned int i);
+void bpf_disasm_all(const struct sock_filter *f, unsigned int len);
+
+#endif