From 49378b61bb4cba23add15bc2ffdba3de298f649a Mon Sep 17 00:00:00 2001 From: Luis Gerhorst <privat@luisgerhorst.de> Date: Fri, 2 Apr 2021 11:56:56 +0200 Subject: [PATCH] Use bpf_task_{un}map to sanitize userspace address --- libbpf | 2 +- src/task.bpf.c | 31 +++++++++++++------------------ src/task.c | 9 ++++++--- src/task.h | 6 ++++++ src/task_mmap.bpf.c | 3 +++ src/task_mmap.c | 2 +- 6 files changed, 30 insertions(+), 23 deletions(-) create mode 100644 src/task.h diff --git a/libbpf b/libbpf index bd56208..aadb563 160000 --- a/libbpf +++ b/libbpf @@ -1 +1 @@ -Subproject commit bd56208c08425849e496ba06170551a8ba8241ed +Subproject commit aadb5632638eb93dc2b60e3623f50e81b3ac10ae diff --git a/src/task.bpf.c b/src/task.bpf.c index 91615b1..599bf24 100644 --- a/src/task.bpf.c +++ b/src/task.bpf.c @@ -4,45 +4,40 @@ #include <bpf/bpf_helpers.h> #include "libc.bpf.h" +#include "task.h" char LICENSE[] SEC("license") = "Dual BSD/GPL"; -#define PATHLEN 256 -#define UBUF_SIZE 256 +#define PATHLEN UBUF_SIZE char start_path[PATHLEN]; +uintptr_t ubuf_addr; SEC("task") -int handle_tp(long **ctx) +int handle_tp(void *ctx) { int err = 0; bpf_printk("ctx = %llx", ctx); char *ubuf; - ubuf = bpf_task_mmap(UBUF_SIZE); + ubuf = bpf_task_map(UBUF_SIZE, ubuf_addr); if (ubuf == NULL) { + bpf_printk("Error: ubuf is NULL"); return -1; } bpf_printk("ubuf = %llx:%llx, start_path = %s", ubuf, ubuf + UBUF_SIZE, start_path); - /* BUG: page fault, page not present */ - bpf_printk("ubuf = '%c'", ubuf[0]); - - /* BUG: This triggers a segfault in the kernel (at least on the - * hardware). How does ringbuf prevent this? */ - /* bpf_printk("ubuf = %s", ubuf); */ - strncpy(ubuf, start_path, PATHLEN); - /* bpf_printk seems to so some magic to ensure it never reads past the - * allocated area. */ + bpf_printk("ubuf = %s", ubuf); - int dfd = bpf_task_sys_open_3((uint64_t) ubuf, O_RDONLY | O_DIRECTORY, 0777); + int dfd = bpf_task_sys_open_3((uint64_t) ubuf_addr, O_RDONLY | O_DIRECTORY, 0777); if (dfd < 0) { err = dfd; - goto munmap; + bpf_printk("Error: sys_open = %d", dfd); + goto unmap; } - long nread = bpf_task_sys_getdents64_3(dfd, (uint64_t) ubuf, UBUF_SIZE); + long nread = bpf_task_sys_getdents64_3(dfd, (uint64_t) ubuf_addr, UBUF_SIZE); size_t recpos = 0; #pragma clang loop unroll(full) @@ -61,7 +56,7 @@ int handle_tp(long **ctx) if (close_err) { bpf_printk("close_err = %d", close_err); } -munmap: - bpf_task_munmap(ubuf, PATHLEN); +unmap: + bpf_task_unmap(ubuf, UBUF_SIZE); return err; } diff --git a/src/task.c b/src/task.c index e476ed9..9972d6a 100644 --- a/src/task.c +++ b/src/task.c @@ -6,6 +6,8 @@ #include <bpf/libbpf.h> #include "task.skel.h" +#include "task.h" + /* Must match __NR_bpftask in unistd.h of the target kernel. */ #define SYS_bpftask 442 @@ -50,7 +52,10 @@ int main(int argc, char **argv) return 1; } + char ubuf[UBUF_SIZE]; + strncpy(skel->bss->start_path, argv[1], sizeof(skel->bss->start_path)); + skel->bss->ubuf_addr = ubuf; /* Load & verify BPF programs */ err = task_bpf__load(skel); @@ -61,11 +66,9 @@ int main(int argc, char **argv) int prog_fd = bpf_program__fd(skel->progs.handle_tp); - long *output; - long ret = syscall(SYS_bpftask, prog_fd, &output); + long ret = syscall(SYS_bpftask, prog_fd, NULL); printf("syscall(SYS_bfptask, %d, ...) = %d\n", prog_fd, (int) ret); - char *ubuf = (char *) ret; ubuf[0] = 'c'; printf("Successfully started!\n"); diff --git a/src/task.h b/src/task.h new file mode 100644 index 0000000..3fe592a --- /dev/null +++ b/src/task.h @@ -0,0 +1,6 @@ +#ifndef __TASK_H_ +#define __TASK_H_ + +#define UBUF_SIZE 512 + +#endif // __TASK_H_ diff --git a/src/task_mmap.bpf.c b/src/task_mmap.bpf.c index 3b667ec..dce1d0d 100644 --- a/src/task_mmap.bpf.c +++ b/src/task_mmap.bpf.c @@ -36,6 +36,9 @@ int entry(long *ctx) e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) return -1; + + bpf_printk("e = %llx", e); + e->ubuf = ubuf; bpf_ringbuf_submit(e, 0); diff --git a/src/task_mmap.c b/src/task_mmap.c index eb37c48..22c936b 100644 --- a/src/task_mmap.c +++ b/src/task_mmap.c @@ -37,7 +37,7 @@ static int handle_event(void *ctx, void *data, size_t data_sz) { const struct event *e = data; - printf("ubuf = %p\n", e->ubuf); + printf("e = %p, ubuf = %p\n", e, e->ubuf); e->ubuf[0] = 'c'; done = true; -- GitLab