From 25d98b201f53bfd60087989f2ed2286716e0c644 Mon Sep 17 00:00:00 2001
From: Luis Gerhorst <privat@luisgerhorst.de>
Date: Tue, 19 Jan 2021 09:02:36 +0100
Subject: [PATCH] bpftask: return exit code

---
 include/linux/bpf_types.h      |  3 +++
 include/linux/syscalls.h       |  2 +-
 include/uapi/linux/bpf.h       |  1 +
 kernel/bpf/task.c              | 24 +++++++++++++++++++-----
 scripts/bpf_helpers_doc.py     |  2 ++
 tools/include/uapi/linux/bpf.h |  1 +
 tools/lib/bpf/libbpf.c         |  1 +
 tools/lib/bpf/libbpf_probes.c  |  1 +
 8 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
index a52a5688418e5..6319d0e4f15f4 100644
--- a/include/linux/bpf_types.h
+++ b/include/linux/bpf_types.h
@@ -77,6 +77,9 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_LSM, lsm,
 	       void *, void *)
 #endif /* CONFIG_BPF_LSM */
 #endif
+#ifdef CONFIG_BPFTASK_SYSCALL
+BPF_PROG_TYPE(BPF_PROG_TYPE_TASK, task, void *, void *) /* TODO: What are arg2..arg4? */
+#endif
 
 BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
 BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 14aa88fe7078e..55a84700d6f7d 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -970,7 +970,7 @@ asmlinkage long sys_getrandom(char __user *buf, size_t count,
 			      unsigned int flags);
 asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags);
 asmlinkage long sys_bpf(int cmd, union bpf_attr *attr, unsigned int size);
-asmlinkage long sys_bpftask(const char __user *pathname, const char __user *filename, int ofd, char __user *buf);
+asmlinkage long sys_bpftask(int prog_fd, void __user *arg);
 asmlinkage long sys_execveat(int dfd, const char __user *filename,
 			const char __user *const __user *argv,
 			const char __user *const __user *envp, int flags);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index b6238b2209b71..aa4a630b9a995 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -197,6 +197,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_EXT,
 	BPF_PROG_TYPE_LSM,
 	BPF_PROG_TYPE_SK_LOOKUP,
+	BPF_PROG_TYPE_TASK,
 };
 
 enum bpf_attach_type {
diff --git a/kernel/bpf/task.c b/kernel/bpf/task.c
index 8d4180a462f30..75677bdc811f4 100644
--- a/kernel/bpf/task.c
+++ b/kernel/bpf/task.c
@@ -6,6 +6,7 @@
 #include <linux/errname.h>
 #include <linux/dirent.h>
 #include <linux/vmalloc.h>
+#include <linux/filter.h>
 
 #define BUF_SIZE 1024
 
@@ -199,15 +200,28 @@ static long find(const char __user *pathname_user, const char __user *filename_u
 	return err;
 }
 
-SYSCALL_DEFINE4(bpftask, const char __user *, pathname, const char __user *, filename, int, ofd, char __user *, buf_user)
+/* dummy _ops. The verifier will operate on target program's ops. */
+const struct bpf_verifier_ops task_verifier_ops = {
+};
+const struct bpf_prog_ops task_prog_ops = {
+};
+
+SYSCALL_DEFINE2(bpftask, int, prog_fd, void *, arg)
 {
-	void *vm = vmalloc(1);
-	void *vmuser = vmalloc_user(1);
-	printk("bpftask, %p ?= %p, buf_user = %p, vmalloc = %p, vmalloc_user = %p\n", compat_alloc_user_space(16), compat_alloc_user_space(16), buf_user, vm, vmuser);
+	int ret = 0;
 
 	/* The same check as in bpf/syscall.c */
 	if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
 		return -EPERM;
 
-	return find(pathname, filename, ofd, buf_user);
+	struct bpf_prog *prog = bpf_prog_get(prog_fd);
+	if (IS_ERR(prog)) {
+		ret = PTR_ERR(prog);
+		goto out;
+	}
+	ret = BPF_PROG_RUN(prog, NULL);
+
+	bpf_prog_put(prog);
+out:
+	return ret;
 }
diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
index 5bfa448b4704b..535f81e93be64 100755
--- a/scripts/bpf_helpers_doc.py
+++ b/scripts/bpf_helpers_doc.py
@@ -472,6 +472,8 @@ class PrinterHelpers(Printer):
             'struct tcp_request_sock',
             'struct udp6_sock',
             'struct task_struct',
+        # Added for bpftask:
+        'struct bpf_redir_neigh', 'struct linux_binprm', 'struct path', 'struct btf_ptr', 'struct inode', 'struct socket', 'struct file'
     }
     mapped_types = {
             'u8': '__u8',
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index b6238b2209b71..aa4a630b9a995 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -197,6 +197,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_EXT,
 	BPF_PROG_TYPE_LSM,
 	BPF_PROG_TYPE_SK_LOOKUP,
+	BPF_PROG_TYPE_TASK,
 };
 
 enum bpf_attach_type {
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e493d6048143f..51da2f64c67d3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -6995,6 +6995,7 @@ static const struct bpf_sec_def section_defs[] = {
 	BPF_PROG_SEC("struct_ops",		BPF_PROG_TYPE_STRUCT_OPS),
 	BPF_EAPROG_SEC("sk_lookup/",		BPF_PROG_TYPE_SK_LOOKUP,
 						BPF_SK_LOOKUP),
+	BPF_PROG_SEC("task", BPF_PROG_TYPE_TASK),
 };
 
 #undef BPF_PROG_SEC_IMPL
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index 5a3d3f0784081..2972055ecde80 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -112,6 +112,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
 	case BPF_PROG_TYPE_STRUCT_OPS:
 	case BPF_PROG_TYPE_EXT:
 	case BPF_PROG_TYPE_LSM:
+	case BPF_PROG_TYPE_TASK:
 	default:
 		break;
 	}
-- 
GitLab