diff --git a/libbpf b/libbpf
index 39635dd04328cf581ed629f0ad0d19a313386bcc..2e3baf61a6178304ceb1e670910da67c8c239eda 160000
--- a/libbpf
+++ b/libbpf
@@ -1 +1 @@
-Subproject commit 39635dd04328cf581ed629f0ad0d19a313386bcc
+Subproject commit 2e3baf61a6178304ceb1e670910da67c8c239eda
diff --git a/src/task_filter_magic.bpf.c b/src/task_filter_magic.bpf.c
index 18807f2874cda4ac79643ad49c4dcb22b50c77d3..f11fcd889279fb700d18bcc326f6b167586e4f03 100644
--- a/src/task_filter_magic.bpf.c
+++ b/src/task_filter_magic.bpf.c
@@ -4,27 +4,107 @@
 #include <bpf/bpf_helpers.h>
 
 #include "task_lib.bpf.h"
-#include "task_ag.h"
+
+#define NAME task_filter_magic
+
+/* https://stackoverflow.com/questions/5873722/c-macro-dynamic-include */
+#define __header(x) #x
+#define _name_h(x) __header(x.h)
+#define name_h(x) _name_h(x)
+#include name_h(NAME)
 
 char LICENSE[] SEC("license") = "Dual BSD/GPL";
 
+struct bpf_map_def SEC("maps") args = {
+    .type = BPF_MAP_TYPE_HASH,
+    .key_size = sizeof(uint32_t),
+    .value_size = sizeof(size_t),
+    .max_entries = 1,
+};
+
+size_t offset;
+size_t magic_size;
+uintptr_t u_pathbufs;
+uintptr_t u_bpfmem;
+uintptr_t u_buf;
+uintptr_t u_magic;
+uintptr_t u_statbuf;
+
 SEC("task")
 int entry(void *ctx)
 {
 	int err = 0;
 
-	bpf_printk("ctx = %llx", ctx);
+	/* struct stat *statbuf = bpf_task_map(sizeof(struct stat), u_statbuf); */
+	/* if (statbuf == NULL) { */
+	/* 	bpf_printk("Error: buf is NULL"); */
+	/* 	return -1; */
+	/* } */
 
-	/* BUG: why does this reutrn -1? */
-	char *buf = bpf_task_map(SIZE, ctx);
-	if (buf == NULL) {
-		bpf_printk("Error: buf is NULL");
-		return -1;
+	struct bpfmem *bpfmem;
+	bpfmem = bpf_task_map(sizeof(struct bpfmem), u_bpfmem);
+	if (bpfmem == NULL) {
+		bpf_printk("Error: bpfmem is NULL");
+		err = -1;
+		goto end;
 	}
 
-	err = *buf;
+	char *magic = &bpfmem->magic[0];
+	char *buf = &bpfmem->buf[0];
+	struct stat *statbuf = &bpfmem->statbuf;
+
+	goto unmap;
+	/* size_t burst_size = bpf_map_lookup_elem(args, 0); */
+
+	for (size_t i = 0; i < MAX_BURST_SIZE; i++) {
+		uintptr_t u_pathbuf = u_pathbufs + i * MAX_PATHLEN;
+
+		int fd = open((char *) u_pathbuf, O_RDONLY);
+		if (fd == -1) {
+			err = -3;
+			goto unmap;
+		}
+
+		/* err = fstat(fd, u_statbuf); */
+		/* if (err != 0) { */
+		/* 	goto unmap; */
+		/* } */
+		/* if (statbuf.st_size < offset + magic_size-1) { */
+		/* 	err = -1; */
+		/* 	goto unmap; */
+		/* } */
+
+		/* if (offset) { */
+		/* 	off_t o = lseek(fd, offset, SEEK_SET); */
+		/* 	if (o == -1) { */
+		/* 		err = -1; */
+		/* 		goto unmap; */
+		/* 	} */
+		/* } */
+
+		ssize_t nread = read(fd, u_buf, magic_size-1);
+		if (nread == -1) {
+			err = -1;
+			goto unmap;
+		}
+		if (nread < magic_size-1) {
+			err = -2;
+			goto unmap;
+		}
+
+		/* if (strcmp(magic, buf) == 0) { */
+		/* 	printf("%s\n", u_pathbuf); */
+		/* } */
+
+	close:
+		err = close(fd);
+		if (err) {
+			goto unmap;
+		}
+	}
 
 unmap:
-	bpf_task_unmap(buf, SIZE);
+	bpf_task_unmap(bpfmem, sizeof(struct bpfmem));
+end:
 	return err;
 }
diff --git a/src/task_filter_magic.c b/src/task_filter_magic.c
index 8a32d5b5b9dab855dcbc6320fa12970b643aab52..9572636437bd33bfe4452cc3230f99d4dc33203d 100644
--- a/src/task_filter_magic.c
+++ b/src/task_filter_magic.c
@@ -144,8 +144,6 @@ static void plog(const unsigned int level, const char *fmt, ...) {
 	va_end(args);
 }
 
-#define MAX_PATHLEN 512
-
 static int filter_magic_user_fp(size_t offset, const char *magic) {
 	int err;
 	size_t magic_size = strlen(magic) + 1;
@@ -404,7 +402,7 @@ static int filter_magic_user_burst(size_t offset, const char *magic, size_t max_
 	}
 }
 
-static int filter_magic_bpf(size_t offset, const char *magic, size_t max_burst_size) {
+static int filter_magic_bpf(size_t offset, const char *magic_argv, size_t max_burst_size) {
 	int err;
 	int ret = EXIT_SUCCESS;
 
@@ -423,12 +421,26 @@ static int filter_magic_bpf(size_t offset, const char *magic, size_t max_burst_s
 		return EXIT_FAILURE;
 	}
 
-
-	size_t magic_size = strlen(magic) + 1;
-	char buf[magic_size];
-	buf[magic_size-1] = '\0';
 	char pathbufs[max_burst_size][MAX_PATHLEN];
-	/* TODO: Write pathbufs, buf, offset and magic into program. */
+
+	/* TODO: use struct mem */
+	struct bpfmem bpfmem;
+	size_t magic_size = strlen(magic_argv) + 1;
+	if (magic_size > MAX_MAGIC_SIZE) {
+		log_err("magic too long");
+		return EXIT_FAILURE;
+	}
+	bpfmem.buf[magic_size-1] = '\0';
+	strcpy(&bpfmem.magic[0], magic_argv);
+
+	/* Write pathbufs, buf, offset and magic into program. */
+	skel->bss->offset = offset;
+	skel->bss->magic_size = magic_size;
+	skel->bss->u_pathbufs = pathbufs;
+	skel->bss->u_bpfmem = &bpfmem;
+	skel->bss->u_buf = &bpfmem.buf[0];
+	skel->bss->u_magic = &bpfmem.magic[0];
+	skel->bss->u_statbuf = &bpfmem.statbuf;
 
 	/* Load & verify BPF programs */
 	err = BPF_LOAD(skel);
@@ -542,6 +554,12 @@ int main(int argc, char **argv)
 	} else if (strcmp(variant, "user_burst_skip") == 0) {
 		return filter_magic_user_burst(offset, magic, max_burst_size, true);
 	} else if (strcmp(variant, "bpf") == 0) {
+		if (max_burst_size != MAX_BURST_SIZE) {
+			log_err("bpf only supports max_burst_size = %u", MAX_BURST_SIZE);
+			return EXIT_FAILURE;
+		}
 		return filter_magic_bpf(offset, magic, max_burst_size);
+	} else {
+		return EXIT_FAILURE;
 	}
 }
diff --git a/src/task_filter_magic.h b/src/task_filter_magic.h
index ce6021e6a9bc16b42c59f5564d10519cab8a3843..fd4490407c08c0f5dc420fe34577f246fc12b6ab 100644
--- a/src/task_filter_magic.h
+++ b/src/task_filter_magic.h
@@ -1,6 +1,14 @@
 #ifndef __TASK_BULK_H_
 #define __TASK_BULK_H_
 
-#define SIZE 4096
+#define MAX_MAGIC_SIZE 32
+#define MAX_PATHLEN 512
+#define MAX_BURST_SIZE 1024
+
+struct bpfmem {
+	char buf[MAX_MAGIC_SIZE];
+	char magic[MAX_MAGIC_SIZE];
+	struct stat statbuf;
+};
 
 #endif // __TASK_BULK_H_
diff --git a/src/task_lib.bpf.h b/src/task_lib.bpf.h
index 59d1e960978f3821c77542e6fac15c480b325415..28d53ae9c97499526bf0fcc9a2b78d16853ffd38 100644
--- a/src/task_lib.bpf.h
+++ b/src/task_lib.bpf.h
@@ -14,10 +14,14 @@
 #define false ((bool) 0)
 #define true ((bool) 1)
 
+typedef __u32 uint32_t;
 typedef __u64 uint64_t;
 /* BUG: This asserts a 64-bit system. */
 typedef __u64 uintptr_t;
+typedef long intptr_t;
+
 typedef uintptr_t size_t;
+typedef intptr_t ssize_t;
 typedef __u64 ino64_t;
 typedef __u64 off64_t;
 typedef off64_t off_t;
@@ -40,6 +44,36 @@ struct timespec {
 	long   tv_nsec;       /* nanoseconds */
 };
 
+/* fstat(2) */
+typedef int dev_t;
+typedef int ino_t;
+typedef int mode_t;
+typedef int nlink_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int blksize_t;
+typedef int blkcnt_t;
+struct stat {
+	dev_t     st_dev;         /* ID of device containing file */
+	ino_t     st_ino;         /* Inode number */
+	mode_t    st_mode;        /* File type and mode */
+	nlink_t   st_nlink;       /* Number of hard links */
+	uid_t     st_uid;         /* User ID of owner */
+	gid_t     st_gid;         /* Group ID of owner */
+	dev_t     st_rdev;        /* Device ID (if special file) */
+	off_t     st_size;        /* Total size, in bytes */
+	blksize_t st_blksize;     /* Block size for filesystem I/O */
+	blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */
+
+	/* Since Linux 2.6, the kernel supports nanosecond
+	   precision for the following timestamp fields.
+	   For the details before Linux 2.6, see NOTES. */
+
+	struct timespec st_atim;  /* Time of last access */
+	struct timespec st_mtim;  /* Time of last modification */
+	struct timespec st_ctim;  /* Time of last status change */
+};
+
 static char *strncpy(char *dest, const char *src, size_t n) {
 	for (size_t i = 0; i < n; i++) {
 		dest[i] = src[i];
@@ -56,7 +90,19 @@ static void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t
 }
 
 static int nanosleep(const struct timespec *req, struct timespec *rem) {
-	return (int) bpf_task_sys_nanosleep_2(req, rem);
+	return (int) bpf_task_sys_nanosleep_2((uint64_t) req, (uint64_t) rem);
+}
+
+static int open(const char *pathname, int flags) {
+	return (int) bpf_task_sys_open_2((uint64_t) pathname, flags);
+}
+
+static ssize_t read(int fd, void *buf, size_t count) {
+	return (ssize_t) bpf_task_sys_read_3(fd, (uint64_t) buf, count);
+}
+
+static int close(int fd) {
+	return (int) bpf_task_sys_close_1(fd);
 }
 
 #endif // __TASK_LIBC_BPF_H_