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