From 06b0f6d323c396ca1df000af96fdd07cc69b06e0 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Thu, 23 Mar 2023 17:06:00 +0100 Subject: filter: add logging mode The logging mode creates a BPF filter where all the syscalls trigger a notification to the seccomp notifier. --- Makefile | 4 ++-- build.c | 3 ++- filter.c | 21 ++++++++++++++++++-- filter.h | 2 +- seitan.c | 69 +++++++++++++++++++++++++++++++++++++--------------------------- 5 files changed, 64 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 79155e0..4b59853 100644 --- a/Makefile +++ b/Makefile @@ -25,8 +25,8 @@ bpf_dbg: disasm.c disasm.h bpf_dbg.c seitan-eater: eater.c common.h common.c $(CC) $(CFLAGS) -o seitan-eater eater.c common.c -seitan: seitan.c transform.h common.h common.c - $(CC) $(CFLAGS) -o seitan seitan.c common.c +seitan: seitan.c transform.h common.h common.c operations.c + $(CC) $(CFLAGS) -o seitan seitan.c common.c operations.c numbers.h: ./nr_syscalls.sh diff --git a/build.c b/build.c index f99dc97..93ce97b 100644 --- a/build.c +++ b/build.c @@ -23,7 +23,8 @@ int main(int argc, char **argv) perror("missing input file"); exit(EXIT_FAILURE); } - ret = convert_bpf(argv[1], calls, sizeof(calls) / sizeof(calls[0])); + ret = convert_bpf(argv[1], calls, sizeof(calls) / sizeof(calls[0]), + true); if (ret < 0) { perror("converting bpf program"); exit(EXIT_FAILURE); diff --git a/filter.c b/filter.c index f8b782d..dbda7ca 100644 --- a/filter.c +++ b/filter.c @@ -174,6 +174,20 @@ static unsigned int get_total_args(const struct syscall_entry table[], return n; } +unsigned int create_bpf_program_log(struct sock_filter filter[]) +{ + filter[0] = (struct sock_filter)BPF_STMT( + BPF_LD | BPF_W | BPF_ABS, + (offsetof(struct seccomp_data, arch))); + filter[1] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, + SEITAN_AUDIT_ARCH, 0, 1); + filter[2] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K, + SECCOMP_RET_USER_NOTIF); + filter[3] = (struct sock_filter)BPF_STMT(BPF_RET | BPF_K, + SECCOMP_RET_ALLOW); + return 4; +} + unsigned int create_bfp_program(struct syscall_entry table[], struct sock_filter filter[], unsigned int n_syscall) @@ -258,7 +272,7 @@ static int compare_names(const void *a, const void *b) ((struct syscall_numbers *)b)->name); } -int convert_bpf(char *file, struct bpf_call *entries, int n) +int convert_bpf(char *file, struct bpf_call *entries, int n, bool log) { int nt, fd, fsize; struct syscall_entry table[N_SYSCALL]; @@ -270,7 +284,10 @@ int convert_bpf(char *file, struct bpf_call *entries, int n) qsort(entries, n, sizeof(struct bpf_call), compare_bpf_call_names); nt = construct_table(entries, n, table); - fsize = create_bfp_program(table, filter, nt); + if (log) + fsize = create_bpf_program_log(filter); + else + fsize = create_bfp_program(table, filter, nt); fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR); diff --git a/filter.h b/filter.h index 134a16b..ee5ab12 100644 --- a/filter.h +++ b/filter.h @@ -34,6 +34,6 @@ unsigned int right_child(unsigned int parent_index); unsigned int create_bfp_program(struct syscall_entry table[], struct sock_filter filter[], unsigned int n_syscall); -int convert_bpf(char *file, struct bpf_call *entries, int n); +int convert_bpf(char *file, struct bpf_call *entries, int n, bool log); #endif diff --git a/seitan.c b/seitan.c index 6ced328..5d2df21 100644 --- a/seitan.c +++ b/seitan.c @@ -36,6 +36,8 @@ #include #include "common.h" +#include "gluten.h" +#include "operations.h" #define EPOLL_EVENTS 8 #define errExit(msg) \ @@ -259,24 +261,25 @@ int handle(struct seccomp_notif *req, int notifyfd) static int create_socket(const char *path) { struct sockaddr_un addr; - const int optval = 1; - int fd; + int ret, conn; + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + errExit("error creating UNIX socket"); - if ((fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) - errExit("socket"); - - if (strlen(path) >= sizeof(addr.sun_path)) - errExit("path is invalid"); strcpy(addr.sun_path, path); addr.sun_family = AF_UNIX; - if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) errExit("bind"); - if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < - 0) - errExit("setsockopt"); + ret = listen(fd, 1); + if (ret < 0) + errExit("listen"); + conn = accept(fd, NULL, NULL); + if (conn < 0) + errExit("accept"); - return fd; + return conn; } static int recvfd(int sockfd) @@ -324,16 +327,16 @@ static int write_syscall(int fd, struct seccomp_notif *req) char buf[1000]; /* TODO: Define format and print syscall with the right arguments */ - snprintf(buf, sizeof(buf), "nr_syscall=%d", req->data.nr); - write(fd, buf, sizeof(buf)); + snprintf(buf, sizeof(buf), "nr_syscall=%d\n", req->data.nr); + write(fd, buf, strlen(buf)); + return 0; } int main(int argc, char **argv) { int s = nl_init(), ret, pidfd, notifier; - char resp_b[BUFSIZ], req_b[BUFSIZ]; + char req_b[BUFSIZ]; struct epoll_event ev, events[EPOLL_EVENTS]; - struct seccomp_notif_resp *resp = (struct seccomp_notif_resp *)resp_b; struct seccomp_notif *req = (struct seccomp_notif *)req_b; struct arguments arguments; char path[PATH_MAX + 1]; @@ -352,8 +355,9 @@ int main(int argc, char **argv) if (strcmp(arguments.output_file, "") > 0) { output = true; - if ((fdout = open(arguments.output_file, O_CREAT | O_WRONLY)) < - 0) + unlink(arguments.output_file); + if ((fdout = open(arguments.output_file, + O_CREAT | O_RDWR | O_TRUNC)) < 0) errExit("open"); } @@ -369,6 +373,7 @@ int main(int argc, char **argv) /* Unblock seitan-loader */ unblock_eater(pidfd); } else if (strcmp(arguments.socket, "") > 0) { + unlink(arguments.socket); if ((fd = create_socket(arguments.socket)) < 0) exit(EXIT_FAILURE); if ((notifier = recvfd(fd)) < 0) @@ -398,27 +403,33 @@ int main(int argc, char **argv) perror("epoll_wait"); exit(EXIT_FAILURE); } - /* TODO: Open syscall transformation table blob, actually handle - * syscalls actions as parsed - */ memset(req, 0, sizeof(*req)); + if (ioctl(notifier, SECCOMP_IOCTL_NOTIF_RECV, req) < 0) + errExit("recieving seccomp notification"); for (i = 0; i < nevents; ++i) { if (events[i].events & EPOLLHUP) { /* The notifier fd was closed by the target */ running = false; } else if (notifier == events[i].data.fd) { - if (!handle(req, events[i].data.fd)) - continue; - - resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE; - resp->id = req->id; - resp->error = 0; - resp->val = 0; + /* + * TODO: remove until we parse correctly the + * operations from the bytecode + */ + struct op operations[] = { + { .type = OP_CONT }, + }; + if (do_operations(NULL, operations, req, + sizeof(operations) / + sizeof(operations[0]), + req->pid, notifier, + req->id) == -1) + errExit("failed executing operation"); - ioctl(notifier, SECCOMP_IOCTL_NOTIF_SEND, resp); if (output) write_syscall(fdout, req); } } } + if (strcmp(arguments.socket, "") > 0) + unlink(arguments.socket); } -- cgit v1.2.3