All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/5] bpf: Light skeleton for the kernel.
@ 2022-02-04 23:17 Alexei Starovoitov
  2022-02-04 23:17 ` [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs Alexei Starovoitov
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Alexei Starovoitov @ 2022-02-04 23:17 UTC (permalink / raw)
  To: davem; +Cc: daniel, andrii, bpf, kernel-team

From: Alexei Starovoitov <ast@kernel.org>

The libbpf performs a set of complex operations to load BPF programs.
With "loader program" and "CO-RE in the kernel" the loading job of
libbpf was diminished. The light skeleton became lean enough to perform
program loading and map creation tasks without libbpf.
It's now possible to tweak it further to make light skeleton usable
out of user space and out of kernel module.
This allows bpf_preload.ko to drop user-mode-driver usage,
drop host compiler dependency, allow cross compilation and simplify the code.
It's a building block toward safe and portable kernel modules.

Alexei Starovoitov (5):
  bpf: Extend sys_bpf commands for bpf_syscall programs.
  libbpf: Prepare light skeleton for the kernel.
  bpftool: Generalize light skeleton generation.
  bpf: Update iterators.lskel.h.
  bpf: Convert bpf_preload.ko to use light skeleton.

 kernel/bpf/inode.c                            |  39 ++--
 kernel/bpf/preload/Kconfig                    |   9 +-
 kernel/bpf/preload/Makefile                   |  14 +-
 kernel/bpf/preload/bpf_preload.h              |   8 +-
 kernel/bpf/preload/bpf_preload_kern.c         | 119 +++++--------
 kernel/bpf/preload/bpf_preload_umd_blob.S     |   7 -
 .../preload/iterators/bpf_preload_common.h    |  13 --
 kernel/bpf/preload/iterators/iterators.c      | 108 -----------
 .../bpf/preload/iterators/iterators.lskel.h   |  28 ++-
 kernel/bpf/syscall.c                          |  40 ++++-
 tools/bpf/bpftool/gen.c                       |  45 +++--
 tools/lib/bpf/skel_internal.h                 | 168 ++++++++++++++++--
 12 files changed, 296 insertions(+), 302 deletions(-)
 delete mode 100644 kernel/bpf/preload/bpf_preload_umd_blob.S
 delete mode 100644 kernel/bpf/preload/iterators/bpf_preload_common.h
 delete mode 100644 kernel/bpf/preload/iterators/iterators.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs.
  2022-02-04 23:17 [PATCH bpf-next 0/5] bpf: Light skeleton for the kernel Alexei Starovoitov
@ 2022-02-04 23:17 ` Alexei Starovoitov
  2022-02-08 16:20     ` kernel test robot
  2022-02-08 17:11   ` Yonghong Song
  2022-02-04 23:17 ` [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel Alexei Starovoitov
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 12+ messages in thread
From: Alexei Starovoitov @ 2022-02-04 23:17 UTC (permalink / raw)
  To: davem; +Cc: daniel, andrii, bpf, kernel-team

From: Alexei Starovoitov <ast@kernel.org>

bpf_sycall programs can be used directly by the kernel modules
to load programs and create maps via kernel skeleton.
. Export bpf_sys_bpf syscall wrapper to be used in kernel skeleton.
. Export bpf_map_get to be used in kernel skeleton.
. Allow prog_run cmd for bpf_syscall programs with recursion check.
. Enable link_create and raw_tp_open cmds.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 kernel/bpf/syscall.c | 38 ++++++++++++++++++++++++++++++++++----
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 72ce1edde950..08ac01acc51e 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -985,6 +985,7 @@ struct bpf_map *bpf_map_get(u32 ufd)
 
 	return map;
 }
+EXPORT_SYMBOL(bpf_map_get);
 
 struct bpf_map *bpf_map_get_with_uref(u32 ufd)
 {
@@ -4756,23 +4757,52 @@ static bool syscall_prog_is_valid_access(int off, int size,
 	return true;
 }
 
-BPF_CALL_3(bpf_sys_bpf, int, cmd, void *, attr, u32, attr_size)
+BPF_CALL_3(bpf_sys_bpf, int, cmd, union bpf_attr *, attr, u32, attr_size)
 {
+	struct bpf_prog *prog;
+
 	switch (cmd) {
 	case BPF_MAP_CREATE:
 	case BPF_MAP_UPDATE_ELEM:
 	case BPF_MAP_FREEZE:
 	case BPF_PROG_LOAD:
 	case BPF_BTF_LOAD:
+	case BPF_LINK_CREATE:
+	case BPF_RAW_TRACEPOINT_OPEN:
 		break;
-	/* case BPF_PROG_TEST_RUN:
-	 * is not part of this list to prevent recursive test_run
-	 */
+#ifdef CONFIG_BPF_JIT /* __bpf_prog_enter_sleepable used by trampoline and JIT */
+	case BPF_PROG_TEST_RUN:
+		if (attr->test.data_in || attr->test.data_out ||
+		    attr->test.ctx_out || attr->test.duration ||
+		    attr->test.repeat || attr->test.flags)
+			return -EINVAL;
+
+		prog = bpf_prog_get_type(attr->test.prog_fd, BPF_PROG_TYPE_SYSCALL);
+		if (IS_ERR(prog))
+			return PTR_ERR(prog);
+
+		if (attr->test.ctx_size_in < prog->aux->max_ctx_offset ||
+		    attr->test.ctx_size_in > U16_MAX) {
+			bpf_prog_put(prog);
+			return -EINVAL;
+		}
+
+		if (!__bpf_prog_enter_sleepable(prog)) {
+			/* recursion detected */
+			bpf_prog_put(prog);
+			return -EBUSY;
+		}
+		attr->test.retval = bpf_prog_run(prog, (void *) (long) attr->test.ctx_in);
+		__bpf_prog_exit_sleepable(prog, 0 /* bpf_prog_run does runtime stats */);
+		bpf_prog_put(prog);
+		return 0;
+#endif
 	default:
 		return -EINVAL;
 	}
 	return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size);
 }
+EXPORT_SYMBOL(bpf_sys_bpf);
 
 static const struct bpf_func_proto bpf_sys_bpf_proto = {
 	.func		= bpf_sys_bpf,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel.
  2022-02-04 23:17 [PATCH bpf-next 0/5] bpf: Light skeleton for the kernel Alexei Starovoitov
  2022-02-04 23:17 ` [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs Alexei Starovoitov
@ 2022-02-04 23:17 ` Alexei Starovoitov
  2022-02-07 20:04   ` Andrii Nakryiko
  2022-02-04 23:17 ` [PATCH bpf-next 3/5] bpftool: Generalize light skeleton generation Alexei Starovoitov
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Alexei Starovoitov @ 2022-02-04 23:17 UTC (permalink / raw)
  To: davem; +Cc: daniel, andrii, bpf, kernel-team

From: Alexei Starovoitov <ast@kernel.org>

Prepare light skeleton to be used in the kernel module and in the user space.
The look and feel of lskel.h is mostly the same with the difference that for
user space the skel->rodata is the same pointer before and after skel_load
operation, while in the kernel the skel->rodata after skel_open and the
skel->rodata after skel_load are different pointers.
Typical usage of skeleton remains the same for kernel and user space:
skel = my_bpf__open();
skel->rodata->my_global_var = init_val;
err = my_bpf__load(skel);
err = my_bpf__attach(skel);
// access skel->rodata->my_global_var;
// access skel->bss->another_var;

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/lib/bpf/skel_internal.h | 168 +++++++++++++++++++++++++++++++---
 1 file changed, 153 insertions(+), 15 deletions(-)

diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h
index dcd3336512d4..4d99ef8cbbba 100644
--- a/tools/lib/bpf/skel_internal.h
+++ b/tools/lib/bpf/skel_internal.h
@@ -3,9 +3,19 @@
 #ifndef __SKEL_INTERNAL_H
 #define __SKEL_INTERNAL_H
 
+#ifdef __KERNEL__
+#include <linux/fdtable.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+#include <linux/bpf.h>
+#else
 #include <unistd.h>
 #include <sys/syscall.h>
 #include <sys/mman.h>
+#include <stdlib.h>
+#include "bpf.h"
+#endif
 
 #ifndef __NR_bpf
 # if defined(__mips__) && defined(_ABIO32)
@@ -25,16 +35,12 @@
  * requested during loader program generation.
  */
 struct bpf_map_desc {
-	union {
-		/* input for the loader prog */
-		struct {
-			__aligned_u64 initial_value;
-			__u32 max_entries;
-		};
+	struct {
 		/* output of the loader prog */
-		struct {
-			int map_fd;
-		};
+		int map_fd;
+		/* input for the loader prog */
+		__u32 max_entries;
+		__aligned_u64 initial_value;
 	};
 };
 struct bpf_prog_desc {
@@ -57,11 +63,135 @@ struct bpf_load_and_run_opts {
 	const char *errstr;
 };
 
+long bpf_sys_bpf(__u32 cmd, void *attr, __u32 attr_size);
+
 static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
 			  unsigned int size)
 {
+#ifdef __KERNEL__
+	return bpf_sys_bpf(cmd, attr, size);
+#else
 	return syscall(__NR_bpf, cmd, attr, size);
+#endif
+}
+
+#ifdef __KERNEL__
+static inline int close(int fd)
+{
+	return close_fd(fd);
+}
+static inline void *skel_alloc(size_t size)
+{
+	return kcalloc(1, size, GFP_KERNEL);
+}
+static inline void skel_free(const void *p)
+{
+	kfree(p);
+}
+static inline void skel_free_map_data(void *p, __u64 addr, size_t sz)
+{
+	if (addr && addr != ~0ULL)
+		vm_munmap(addr, sz);
+	if (addr != ~0ULL)
+		kvfree(p);
+}
+/* skel->bss/rodata maps are populated in three steps.
+ *
+ * For kernel use:
+ * skel_prep_map_data() allocates kernel memory that kernel module can directly access.
+ * skel_prep_init_value() allocates a region in user space process and copies
+ * potentially modified initial map value into it.
+ * The loader program will perform copy_from_user() from maps.rodata.initial_value.
+ * skel_finalize_map_data() sets skel->rodata to point to actual value in a bpf map.
+ *
+ * For user space:
+ * skel_prep_map_data() mmaps anon memory into skel->rodata that can be accessed directly.
+ * skel_prep_init_value() copies rodata pointer into map.rodata.initial_value.
+ * The loader program will perform copy_from_user() from maps.rodata.initial_value.
+ * skel_finalize_map_data() remaps bpf array map value from the kernel memory into
+ * skel->rodata address.
+ */
+static inline void *skel_prep_map_data(const void *val, size_t mmap_sz, size_t val_sz)
+{
+	void *addr;
+
+	addr = kvmalloc(val_sz, GFP_KERNEL);
+	if (!addr)
+		return NULL;
+	memcpy(addr, val, val_sz);
+	return addr;
+}
+static inline __u64 skel_prep_init_value(void **addr, size_t mmap_sz, size_t val_sz)
+{
+	__u64 ret = 0;
+	void *uaddr;
+
+	uaddr = (void *) vm_mmap(NULL, 0, mmap_sz, PROT_READ | PROT_WRITE,
+				 MAP_SHARED | MAP_ANONYMOUS, 0);
+	if (IS_ERR(uaddr))
+		goto out;
+	if (copy_to_user(uaddr, *addr, val_sz)) {
+		vm_munmap((long) uaddr, mmap_sz);
+		goto out;
+	}
+	ret = (__u64) (long) uaddr;
+out:
+	kvfree(*addr);
+	*addr = NULL;
+	return ret;
 }
+static inline void *skel_finalize_map_data(__u64 *addr, size_t mmap_sz, int flags, int fd)
+{
+	struct bpf_map *map;
+	void *ptr = NULL;
+
+	vm_munmap(*addr, mmap_sz);
+	*addr = ~0ULL;
+
+	map = bpf_map_get(fd);
+	if (IS_ERR(map))
+		return NULL;
+	if (map->map_type != BPF_MAP_TYPE_ARRAY)
+		goto out;
+	ptr = ((struct bpf_array *)map)->value;
+	/* the ptr stays valid, since FD is not closed */
+out:
+	bpf_map_put(map);
+	return ptr;
+}
+#else
+static inline void *skel_alloc(size_t size)
+{
+	return calloc(1, size);
+}
+static inline void skel_free(void *p)
+{
+	free(p);
+}
+static inline void skel_free_map_data(void *p, __u64 addr, size_t sz)
+{
+	munmap(p, sz);
+}
+static inline void *skel_prep_map_data(const void *val, size_t mmap_sz, size_t val_sz)
+{
+	void *addr;
+
+	addr = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
+		    MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+	if (addr == (void *) -1)
+		return NULL;
+	memcpy(addr, val, val_sz);
+	return addr;
+}
+static inline __u64 skel_prep_init_value(void **addr, size_t mmap_sz, size_t val_sz)
+{
+	return (__u64) (long) *addr;
+}
+static inline void *skel_finalize_map_data(__u64 *addr, size_t mmap_sz, int flags, int fd)
+{
+	return mmap((void *)*addr, mmap_sz, flags, MAP_SHARED | MAP_FIXED, fd, 0);
+}
+#endif
 
 static inline int skel_closenz(int fd)
 {
@@ -136,22 +266,28 @@ static inline int skel_link_create(int prog_fd, int target_fd,
 	return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz);
 }
 
+#ifdef __KERNEL__
+#define set_err
+#else
+#define set_err err = -errno
+#endif
+
 static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
 {
 	int map_fd = -1, prog_fd = -1, key = 0, err;
 	union bpf_attr attr;
 
-	map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1);
+	err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1);
 	if (map_fd < 0) {
 		opts->errstr = "failed to create loader map";
-		err = -errno;
+		set_err;
 		goto out;
 	}
 
 	err = skel_map_update_elem(map_fd, &key, opts->data, 0);
 	if (err < 0) {
 		opts->errstr = "failed to update loader map";
-		err = -errno;
+		set_err;
 		goto out;
 	}
 
@@ -166,10 +302,10 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
 	attr.log_size = opts->ctx->log_size;
 	attr.log_buf = opts->ctx->log_buf;
 	attr.prog_flags = BPF_F_SLEEPABLE;
-	prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+	err = prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 	if (prog_fd < 0) {
 		opts->errstr = "failed to load loader prog";
-		err = -errno;
+		set_err;
 		goto out;
 	}
 
@@ -181,10 +317,12 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
 	if (err < 0 || (int)attr.test.retval < 0) {
 		opts->errstr = "failed to execute loader prog";
 		if (err < 0) {
-			err = -errno;
+			set_err;
 		} else {
 			err = (int)attr.test.retval;
+#ifndef __KERNEL__
 			errno = -err;
+#endif
 		}
 		goto out;
 	}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH bpf-next 3/5] bpftool: Generalize light skeleton generation.
  2022-02-04 23:17 [PATCH bpf-next 0/5] bpf: Light skeleton for the kernel Alexei Starovoitov
  2022-02-04 23:17 ` [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs Alexei Starovoitov
  2022-02-04 23:17 ` [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel Alexei Starovoitov
@ 2022-02-04 23:17 ` Alexei Starovoitov
  2022-02-04 23:17 ` [PATCH bpf-next 4/5] bpf: Update iterators.lskel.h Alexei Starovoitov
  2022-02-04 23:17 ` [PATCH bpf-next 5/5] bpf: Convert bpf_preload.ko to use light skeleton Alexei Starovoitov
  4 siblings, 0 replies; 12+ messages in thread
From: Alexei Starovoitov @ 2022-02-04 23:17 UTC (permalink / raw)
  To: davem; +Cc: daniel, andrii, bpf, kernel-team

From: Alexei Starovoitov <ast@kernel.org>

Generealize light skeleton by hiding mmap details in skel_internal.h
In this form generated lskel.h is usable both by user space and by the kernel.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/bpf/bpftool/gen.c | 45 ++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index eacfc6a2060d..903abbf077ce 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -472,7 +472,7 @@ static void codegen_destroy(struct bpf_object *obj, const char *obj_name)
 			continue;
 		if (bpf_map__is_internal(map) &&
 		    (bpf_map__map_flags(map) & BPF_F_MMAPABLE))
-			printf("\tmunmap(skel->%1$s, %2$zd);\n",
+			printf("\tskel_free_map_data(skel->%1$s, skel->maps.%1$s.initial_value, %2$zd);\n",
 			       ident, bpf_map_mmap_sz(map));
 		codegen("\
 			\n\
@@ -481,7 +481,7 @@ static void codegen_destroy(struct bpf_object *obj, const char *obj_name)
 	}
 	codegen("\
 		\n\
-			free(skel);					    \n\
+			skel_free(skel);				    \n\
 		}							    \n\
 		",
 		obj_name);
@@ -525,7 +525,7 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
 		{							    \n\
 			struct %1$s *skel;				    \n\
 									    \n\
-			skel = calloc(sizeof(*skel), 1);		    \n\
+			skel = skel_alloc(sizeof(*skel));		    \n\
 			if (!skel)					    \n\
 				goto cleanup;				    \n\
 			skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\
@@ -544,18 +544,12 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
 
 		codegen("\
 			\n\
-				skel->%1$s =					 \n\
-					mmap(NULL, %2$zd, PROT_READ | PROT_WRITE,\n\
-					     MAP_SHARED | MAP_ANONYMOUS, -1, 0); \n\
-				if (skel->%1$s == (void *) -1)			 \n\
-					goto cleanup;				 \n\
-				memcpy(skel->%1$s, (void *)\"\\			 \n\
-			", ident, bpf_map_mmap_sz(map));
+				skel->%1$s = skel_prep_map_data((void *)\"\\	 \n\
+			", ident);
 		mmap_data = bpf_map__initial_value(map, &mmap_size);
 		print_hex(mmap_data, mmap_size);
-		printf("\", %2$zd);\n"
-		       "\tskel->maps.%1$s.initial_value = (__u64)(long)skel->%1$s;\n",
-		       ident, mmap_size);
+		printf("\", %1$zd, %2$zd);\n",
+		       bpf_map_mmap_sz(map), mmap_size);
 	}
 	codegen("\
 		\n\
@@ -592,6 +586,24 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
 	codegen("\
 		\n\
 		\";							    \n\
+		");
+	bpf_object__for_each_map(map, obj) {
+		size_t mmap_size = 0;
+
+		if (!get_map_ident(map, ident, sizeof(ident)))
+			continue;
+
+		if (!bpf_map__is_internal(map) ||
+		    !(bpf_map__map_flags(map) & BPF_F_MMAPABLE))
+			continue;
+
+		bpf_map__initial_value(map, &mmap_size);
+		printf("\tskel->maps.%1$s.initial_value ="
+		       " skel_prep_init_value((void **)&skel->%1$s, %2$zd, %3$zd);\n",
+		       ident, bpf_map_mmap_sz(map), mmap_size);
+	}
+	codegen("\
+		\n\
 			err = bpf_load_and_run(&opts);			    \n\
 			if (err < 0)					    \n\
 				return err;				    \n\
@@ -611,9 +623,8 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
 		else
 			mmap_flags = "PROT_READ | PROT_WRITE";
 
-		printf("\tskel->%1$s =\n"
-		       "\t\tmmap(skel->%1$s, %2$zd, %3$s, MAP_SHARED | MAP_FIXED,\n"
-		       "\t\t\tskel->maps.%1$s.map_fd, 0);\n",
+		printf("\tskel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n"
+		       "\t\t\t%2$zd, %3$s, skel->maps.%1$s.map_fd);\n",
 		       ident, bpf_map_mmap_sz(map), mmap_flags);
 	}
 	codegen("\
@@ -751,8 +762,6 @@ static int do_skeleton(int argc, char **argv)
 		#ifndef %2$s						    \n\
 		#define %2$s						    \n\
 									    \n\
-		#include <stdlib.h>					    \n\
-		#include <bpf/bpf.h>					    \n\
 		#include <bpf/skel_internal.h>				    \n\
 									    \n\
 		struct %1$s {						    \n\
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH bpf-next 4/5] bpf: Update iterators.lskel.h.
  2022-02-04 23:17 [PATCH bpf-next 0/5] bpf: Light skeleton for the kernel Alexei Starovoitov
                   ` (2 preceding siblings ...)
  2022-02-04 23:17 ` [PATCH bpf-next 3/5] bpftool: Generalize light skeleton generation Alexei Starovoitov
@ 2022-02-04 23:17 ` Alexei Starovoitov
  2022-02-04 23:17 ` [PATCH bpf-next 5/5] bpf: Convert bpf_preload.ko to use light skeleton Alexei Starovoitov
  4 siblings, 0 replies; 12+ messages in thread
From: Alexei Starovoitov @ 2022-02-04 23:17 UTC (permalink / raw)
  To: davem; +Cc: daniel, andrii, bpf, kernel-team

From: Alexei Starovoitov <ast@kernel.org>

Light skeleton and skel_internal.h have changed.
Update iterators.lskel.h.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 .../bpf/preload/iterators/iterators.lskel.h   | 28 +++++++------------
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/kernel/bpf/preload/iterators/iterators.lskel.h b/kernel/bpf/preload/iterators/iterators.lskel.h
index d90562d672d2..3e45237f59f4 100644
--- a/kernel/bpf/preload/iterators/iterators.lskel.h
+++ b/kernel/bpf/preload/iterators/iterators.lskel.h
@@ -3,8 +3,6 @@
 #ifndef __ITERATORS_BPF_SKEL_H__
 #define __ITERATORS_BPF_SKEL_H__
 
-#include <stdlib.h>
-#include <bpf/bpf.h>
 #include <bpf/skel_internal.h>
 
 struct iterators_bpf {
@@ -70,31 +68,25 @@ iterators_bpf__destroy(struct iterators_bpf *skel)
 	iterators_bpf__detach(skel);
 	skel_closenz(skel->progs.dump_bpf_map.prog_fd);
 	skel_closenz(skel->progs.dump_bpf_prog.prog_fd);
-	munmap(skel->rodata, 4096);
+	skel_free_map_data(skel->rodata, skel->maps.rodata.initial_value, 4096);
 	skel_closenz(skel->maps.rodata.map_fd);
-	free(skel);
+	skel_free(skel);
 }
 static inline struct iterators_bpf *
 iterators_bpf__open(void)
 {
 	struct iterators_bpf *skel;
 
-	skel = calloc(sizeof(*skel), 1);
+	skel = skel_alloc(sizeof(*skel));
 	if (!skel)
 		goto cleanup;
 	skel->ctx.sz = (void *)&skel->links - (void *)skel;
-	skel->rodata =
-		mmap(NULL, 4096, PROT_READ | PROT_WRITE,
-		     MAP_SHARED | MAP_ANONYMOUS, -1, 0);
-	if (skel->rodata == (void *) -1)
-		goto cleanup;
-	memcpy(skel->rodata, (void *)"\
+	skel->rodata = skel_prep_map_data((void *)"\
 \x20\x20\x69\x64\x20\x6e\x61\x6d\x65\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
 \x20\x20\x20\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\x0a\0\x25\x34\x75\x20\
 \x25\x2d\x31\x36\x73\x25\x36\x64\x0a\0\x20\x20\x69\x64\x20\x6e\x61\x6d\x65\x20\
 \x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x61\x74\x74\x61\x63\x68\x65\
-\x64\x0a\0\x25\x34\x75\x20\x25\x2d\x31\x36\x73\x20\x25\x73\x20\x25\x73\x0a\0", 98);
-	skel->maps.rodata.initial_value = (__u64)(long)skel->rodata;
+\x64\x0a\0\x25\x34\x75\x20\x25\x2d\x31\x36\x73\x20\x25\x73\x20\x25\x73\x0a\0", 4096, 98);
 	return skel;
 cleanup:
 	iterators_bpf__destroy(skel);
@@ -343,11 +335,11 @@ iterators_bpf__load(struct iterators_bpf *skel)
 \0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x30\x0e\0\0\xb7\x03\0\0\x1c\0\0\0\x85\0\0\0\
 \xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xd4\xff\0\0\0\0\x63\x7a\x78\xff\0\0\0\0\
 \x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x80\x0e\0\0\x63\x01\0\0\0\
-\0\0\0\x61\x60\x20\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\x61\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\
 \x5c\x0e\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\
 \0\x50\x0e\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\
 \xc5\x07\xc3\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\0\0\0\0\0\
-\0\x79\x63\x18\0\0\0\0\0\x15\x03\x04\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x98\
+\0\x79\x63\x20\0\0\0\0\0\x15\x03\x04\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x98\
 \x0e\0\0\xb7\x02\0\0\x62\0\0\0\x85\0\0\0\x94\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\
 \0\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\x0f\0\0\x63\x01\0\
 \0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x0f\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\
@@ -401,12 +393,12 @@ iterators_bpf__load(struct iterators_bpf *skel)
 \x28\0\0\0\0\0\x61\xa0\x84\xff\0\0\0\0\x63\x06\x2c\0\0\0\0\0\x18\x61\0\0\0\0\0\
 \0\0\0\0\0\0\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x18\0\0\0\0\0\xb7\0\0\0\0\0\0\0\
 \x95\0\0\0\0\0\0\0";
+	skel->maps.rodata.initial_value = skel_prep_init_value((void **)&skel->rodata, 4096, 98);
 	err = bpf_load_and_run(&opts);
 	if (err < 0)
 		return err;
-	skel->rodata =
-		mmap(skel->rodata, 4096, PROT_READ, MAP_SHARED | MAP_FIXED,
-			skel->maps.rodata.map_fd, 0);
+	skel->rodata = skel_finalize_map_data(&skel->maps.rodata.initial_value,
+			4096, PROT_READ, skel->maps.rodata.map_fd);
 	return 0;
 }
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH bpf-next 5/5] bpf: Convert bpf_preload.ko to use light skeleton.
  2022-02-04 23:17 [PATCH bpf-next 0/5] bpf: Light skeleton for the kernel Alexei Starovoitov
                   ` (3 preceding siblings ...)
  2022-02-04 23:17 ` [PATCH bpf-next 4/5] bpf: Update iterators.lskel.h Alexei Starovoitov
@ 2022-02-04 23:17 ` Alexei Starovoitov
  4 siblings, 0 replies; 12+ messages in thread
From: Alexei Starovoitov @ 2022-02-04 23:17 UTC (permalink / raw)
  To: davem; +Cc: daniel, andrii, bpf, kernel-team

From: Alexei Starovoitov <ast@kernel.org>

The main change is a move of the single line
  #include "iterators.lskel.h"
from iterators/iterators.c to bpf_preload_kern.c.
Which means that generated light skeleton can be used from user space or
user mode driver like iterators.c or from the kernel module.
The direct use of light skeleton from the kernel module simplifies the code,
since UMD is no longer necessary. The libbpf.a required user space and UMD. The
CO-RE in the kernel and generated "loader bpf program" used by the light
skeleton are capable to perform complex loading operations traditionally
provided by libbpf. In addition UMD approach was launching UMD process
every time bpffs has to be mounted. With light skeleton in the kernel
the bpf_preload kernel module loads bpf iterators once and pins them
multiple times into different bpffs mounts.

Note the light skeleton cannot be used during early boot or out of kthread
since light skeleton needs a valid mm. This limitation could be lifted in the
future.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 kernel/bpf/inode.c                            |  39 ++----
 kernel/bpf/preload/Kconfig                    |   9 +-
 kernel/bpf/preload/Makefile                   |  14 +--
 kernel/bpf/preload/bpf_preload.h              |   8 +-
 kernel/bpf/preload/bpf_preload_kern.c         | 119 ++++++++----------
 kernel/bpf/preload/bpf_preload_umd_blob.S     |   7 --
 .../preload/iterators/bpf_preload_common.h    |  13 --
 kernel/bpf/preload/iterators/iterators.c      | 108 ----------------
 kernel/bpf/syscall.c                          |   2 +
 9 files changed, 72 insertions(+), 247 deletions(-)
 delete mode 100644 kernel/bpf/preload/bpf_preload_umd_blob.S
 delete mode 100644 kernel/bpf/preload/iterators/bpf_preload_common.h
 delete mode 100644 kernel/bpf/preload/iterators/iterators.c

diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index 5a8d9f7467bf..4f841e16779e 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -710,11 +710,10 @@ static DEFINE_MUTEX(bpf_preload_lock);
 static int populate_bpffs(struct dentry *parent)
 {
 	struct bpf_preload_info objs[BPF_PRELOAD_LINKS] = {};
-	struct bpf_link *links[BPF_PRELOAD_LINKS] = {};
 	int err = 0, i;
 
 	/* grab the mutex to make sure the kernel interactions with bpf_preload
-	 * UMD are serialized
+	 * are serialized
 	 */
 	mutex_lock(&bpf_preload_lock);
 
@@ -722,40 +721,22 @@ static int populate_bpffs(struct dentry *parent)
 	if (!bpf_preload_mod_get())
 		goto out;
 
-	if (!bpf_preload_ops->info.tgid) {
-		/* preload() will start UMD that will load BPF iterator programs */
-		err = bpf_preload_ops->preload(objs);
-		if (err)
+	err = bpf_preload_ops->preload(objs);
+	if (err)
+		goto out_put;
+	for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
+		bpf_link_inc(objs[i].link);
+		err = bpf_iter_link_pin_kernel(parent,
+					       objs[i].link_name, objs[i].link);
+		if (err) {
+			bpf_link_put(objs[i].link);
 			goto out_put;
-		for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
-			links[i] = bpf_link_by_id(objs[i].link_id);
-			if (IS_ERR(links[i])) {
-				err = PTR_ERR(links[i]);
-				goto out_put;
-			}
 		}
-		for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
-			err = bpf_iter_link_pin_kernel(parent,
-						       objs[i].link_name, links[i]);
-			if (err)
-				goto out_put;
-			/* do not unlink successfully pinned links even
-			 * if later link fails to pin
-			 */
-			links[i] = NULL;
-		}
-		/* finish() will tell UMD process to exit */
-		err = bpf_preload_ops->finish();
-		if (err)
-			goto out_put;
 	}
 out_put:
 	bpf_preload_mod_put();
 out:
 	mutex_unlock(&bpf_preload_lock);
-	for (i = 0; i < BPF_PRELOAD_LINKS && err; i++)
-		if (!IS_ERR_OR_NULL(links[i]))
-			bpf_link_put(links[i]);
 	return err;
 }
 
diff --git a/kernel/bpf/preload/Kconfig b/kernel/bpf/preload/Kconfig
index 26bced262473..9de6cfa5dbb1 100644
--- a/kernel/bpf/preload/Kconfig
+++ b/kernel/bpf/preload/Kconfig
@@ -18,10 +18,11 @@ menuconfig BPF_PRELOAD
 
 if BPF_PRELOAD
 config BPF_PRELOAD_UMD
-	tristate "bpf_preload kernel module with user mode driver"
-	depends on CC_CAN_LINK
-	depends on m || CC_CAN_LINK_STATIC
+	tristate "bpf_preload kernel module"
+	# light skeleton cannot run out of kthread without mm
+	depends on m
 	default m
 	help
-	  This builds bpf_preload kernel module with embedded user mode driver.
+	  This builds bpf_preload kernel module with embedded BPF programs for
+	  introspection in bpffs.
 endif
diff --git a/kernel/bpf/preload/Makefile b/kernel/bpf/preload/Makefile
index baf47d9c7557..167534e3b0b4 100644
--- a/kernel/bpf/preload/Makefile
+++ b/kernel/bpf/preload/Makefile
@@ -3,16 +3,6 @@
 LIBBPF_SRCS = $(srctree)/tools/lib/bpf/
 LIBBPF_INCLUDE = $(LIBBPF_SRCS)/..
 
-userccflags += -I $(srctree)/tools/include/ -I $(srctree)/tools/include/uapi \
-	-I $(LIBBPF_INCLUDE) -Wno-unused-result
-
-userprogs := bpf_preload_umd
-
-bpf_preload_umd-objs := iterators/iterators.o
-
-$(obj)/bpf_preload_umd:
-
-$(obj)/bpf_preload_umd_blob.o: $(obj)/bpf_preload_umd
-
 obj-$(CONFIG_BPF_PRELOAD_UMD) += bpf_preload.o
-bpf_preload-objs += bpf_preload_kern.o bpf_preload_umd_blob.o
+CFLAGS_bpf_preload_kern.o += -I $(LIBBPF_INCLUDE)
+bpf_preload-objs += bpf_preload_kern.o
diff --git a/kernel/bpf/preload/bpf_preload.h b/kernel/bpf/preload/bpf_preload.h
index 2f9932276f2e..f065c91213a0 100644
--- a/kernel/bpf/preload/bpf_preload.h
+++ b/kernel/bpf/preload/bpf_preload.h
@@ -2,13 +2,13 @@
 #ifndef _BPF_PRELOAD_H
 #define _BPF_PRELOAD_H
 
-#include <linux/usermode_driver.h>
-#include "iterators/bpf_preload_common.h"
+struct bpf_preload_info {
+	char link_name[16];
+	struct bpf_link *link;
+};
 
 struct bpf_preload_ops {
-        struct umd_info info;
 	int (*preload)(struct bpf_preload_info *);
-	int (*finish)(void);
 	struct module *owner;
 };
 extern struct bpf_preload_ops *bpf_preload_ops;
diff --git a/kernel/bpf/preload/bpf_preload_kern.c b/kernel/bpf/preload/bpf_preload_kern.c
index 53736e52c1df..30207c048d36 100644
--- a/kernel/bpf/preload/bpf_preload_kern.c
+++ b/kernel/bpf/preload/bpf_preload_kern.c
@@ -2,101 +2,80 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/pid.h>
-#include <linux/fs.h>
-#include <linux/sched/signal.h>
 #include "bpf_preload.h"
+#include "iterators/iterators.lskel.h"
 
-extern char bpf_preload_umd_start;
-extern char bpf_preload_umd_end;
+static struct bpf_link *maps_link, *progs_link;
+static struct iterators_bpf *skel;
 
-static int preload(struct bpf_preload_info *obj);
-static int finish(void);
+static void free_links_and_skel(void)
+{
+	if (!IS_ERR_OR_NULL(maps_link))
+		bpf_link_put(maps_link);
+	if (!IS_ERR_OR_NULL(progs_link))
+		bpf_link_put(progs_link);
+	iterators_bpf__destroy(skel);
+}
+
+static int preload(struct bpf_preload_info *obj)
+{
+	strlcpy(obj[0].link_name, "maps.debug", sizeof(obj[0].link_name));
+	obj[0].link = maps_link;
+	strlcpy(obj[1].link_name, "progs.debug", sizeof(obj[1].link_name));
+	obj[1].link = progs_link;
+	return 0;
+}
 
-static struct bpf_preload_ops umd_ops = {
-	.info.driver_name = "bpf_preload",
+static struct bpf_preload_ops ops = {
 	.preload = preload,
-	.finish = finish,
 	.owner = THIS_MODULE,
 };
 
-static int preload(struct bpf_preload_info *obj)
+static int load_skel(void)
 {
-	int magic = BPF_PRELOAD_START;
-	loff_t pos = 0;
-	int i, err;
-	ssize_t n;
+	int err;
 
-	err = fork_usermode_driver(&umd_ops.info);
+	skel = iterators_bpf__open();
+	if (!skel)
+		return -ENOMEM;
+	err = iterators_bpf__load(skel);
 	if (err)
-		return err;
-
-	/* send the start magic to let UMD proceed with loading BPF progs */
-	n = kernel_write(umd_ops.info.pipe_to_umh,
-			 &magic, sizeof(magic), &pos);
-	if (n != sizeof(magic))
-		return -EPIPE;
-
-	/* receive bpf_link IDs and names from UMD */
-	pos = 0;
-	for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
-		n = kernel_read(umd_ops.info.pipe_from_umh,
-				&obj[i], sizeof(*obj), &pos);
-		if (n != sizeof(*obj))
-			return -EPIPE;
+		goto out;
+	err = iterators_bpf__attach(skel);
+	if (err)
+		goto out;
+	maps_link = bpf_link_get_from_fd(skel->links.dump_bpf_map_fd);
+	if (IS_ERR(maps_link)) {
+		err = PTR_ERR(maps_link);
+		goto out;
 	}
-	return 0;
-}
-
-static int finish(void)
-{
-	int magic = BPF_PRELOAD_END;
-	struct pid *tgid;
-	loff_t pos = 0;
-	ssize_t n;
-
-	/* send the last magic to UMD. It will do a normal exit. */
-	n = kernel_write(umd_ops.info.pipe_to_umh,
-			 &magic, sizeof(magic), &pos);
-	if (n != sizeof(magic))
-		return -EPIPE;
-
-	tgid = umd_ops.info.tgid;
-	if (tgid) {
-		wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
-		umd_cleanup_helper(&umd_ops.info);
+	progs_link = bpf_link_get_from_fd(skel->links.dump_bpf_prog_fd);
+	if (IS_ERR(progs_link)) {
+		err = PTR_ERR(progs_link);
+		goto out;
 	}
 	return 0;
+out:
+	free_links_and_skel();
+	return err;
 }
 
-static int __init load_umd(void)
+static int __init load(void)
 {
 	int err;
 
-	err = umd_load_blob(&umd_ops.info, &bpf_preload_umd_start,
-			    &bpf_preload_umd_end - &bpf_preload_umd_start);
+	err = load_skel();
 	if (err)
 		return err;
-	bpf_preload_ops = &umd_ops;
+	bpf_preload_ops = &ops;
 	return err;
 }
 
-static void __exit fini_umd(void)
+static void __exit fini(void)
 {
-	struct pid *tgid;
-
 	bpf_preload_ops = NULL;
-
-	/* kill UMD in case it's still there due to earlier error */
-	tgid = umd_ops.info.tgid;
-	if (tgid) {
-		kill_pid(tgid, SIGKILL, 1);
-
-		wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
-		umd_cleanup_helper(&umd_ops.info);
-	}
-	umd_unload_blob(&umd_ops.info);
+	free_links_and_skel();
 }
-late_initcall(load_umd);
-module_exit(fini_umd);
+late_initcall(load);
+module_exit(fini);
 MODULE_LICENSE("GPL");
diff --git a/kernel/bpf/preload/bpf_preload_umd_blob.S b/kernel/bpf/preload/bpf_preload_umd_blob.S
deleted file mode 100644
index f1f40223b5c3..000000000000
--- a/kernel/bpf/preload/bpf_preload_umd_blob.S
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-	.section .init.rodata, "a"
-	.global bpf_preload_umd_start
-bpf_preload_umd_start:
-	.incbin "kernel/bpf/preload/bpf_preload_umd"
-	.global bpf_preload_umd_end
-bpf_preload_umd_end:
diff --git a/kernel/bpf/preload/iterators/bpf_preload_common.h b/kernel/bpf/preload/iterators/bpf_preload_common.h
deleted file mode 100644
index 8464d1a48c05..000000000000
--- a/kernel/bpf/preload/iterators/bpf_preload_common.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _BPF_PRELOAD_COMMON_H
-#define _BPF_PRELOAD_COMMON_H
-
-#define BPF_PRELOAD_START 0x5555
-#define BPF_PRELOAD_END 0xAAAA
-
-struct bpf_preload_info {
-	char link_name[16];
-	int link_id;
-};
-
-#endif
diff --git a/kernel/bpf/preload/iterators/iterators.c b/kernel/bpf/preload/iterators/iterators.c
deleted file mode 100644
index 4dafe0f4f2b2..000000000000
--- a/kernel/bpf/preload/iterators/iterators.c
+++ /dev/null
@@ -1,108 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2020 Facebook */
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/resource.h>
-#include <bpf/libbpf.h>
-#include <bpf/bpf.h>
-#include <sys/mount.h>
-#include "iterators.lskel.h"
-#include "bpf_preload_common.h"
-
-int to_kernel = -1;
-int from_kernel = 0;
-
-static int __bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
-{
-	union bpf_attr attr;
-	int err;
-
-	memset(&attr, 0, sizeof(attr));
-	attr.info.bpf_fd = bpf_fd;
-	attr.info.info_len = *info_len;
-	attr.info.info = (long) info;
-
-	err = skel_sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
-	if (!err)
-		*info_len = attr.info.info_len;
-	return err;
-}
-
-static int send_link_to_kernel(int link_fd, const char *link_name)
-{
-	struct bpf_preload_info obj = {};
-	struct bpf_link_info info = {};
-	__u32 info_len = sizeof(info);
-	int err;
-
-	err = __bpf_obj_get_info_by_fd(link_fd, &info, &info_len);
-	if (err)
-		return err;
-	obj.link_id = info.id;
-	if (strlen(link_name) >= sizeof(obj.link_name))
-		return -E2BIG;
-	strcpy(obj.link_name, link_name);
-	if (write(to_kernel, &obj, sizeof(obj)) != sizeof(obj))
-		return -EPIPE;
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	struct iterators_bpf *skel;
-	int err, magic;
-	int debug_fd;
-
-	debug_fd = open("/dev/console", O_WRONLY | O_NOCTTY | O_CLOEXEC);
-	if (debug_fd < 0)
-		return 1;
-	to_kernel = dup(1);
-	close(1);
-	dup(debug_fd);
-	/* now stdin and stderr point to /dev/console */
-
-	read(from_kernel, &magic, sizeof(magic));
-	if (magic != BPF_PRELOAD_START) {
-		printf("bad start magic %d\n", magic);
-		return 1;
-	}
-	/* libbpf opens BPF object and loads it into the kernel */
-	skel = iterators_bpf__open_and_load();
-	if (!skel) {
-		/* iterators.skel.h is little endian.
-		 * libbpf doesn't support automatic little->big conversion
-		 * of BPF bytecode yet.
-		 * The program load will fail in such case.
-		 */
-		printf("Failed load could be due to wrong endianness\n");
-		return 1;
-	}
-	err = iterators_bpf__attach(skel);
-	if (err)
-		goto cleanup;
-
-	/* send two bpf_link IDs with names to the kernel */
-	err = send_link_to_kernel(skel->links.dump_bpf_map_fd, "maps.debug");
-	if (err)
-		goto cleanup;
-	err = send_link_to_kernel(skel->links.dump_bpf_prog_fd, "progs.debug");
-	if (err)
-		goto cleanup;
-
-	/* The kernel will proceed with pinnging the links in bpffs.
-	 * UMD will wait on read from pipe.
-	 */
-	read(from_kernel, &magic, sizeof(magic));
-	if (magic != BPF_PRELOAD_END) {
-		printf("bad final magic %d\n", magic);
-		err = -EINVAL;
-	}
-cleanup:
-	iterators_bpf__destroy(skel);
-
-	return err != 0;
-}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 08ac01acc51e..54859f584115 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2490,6 +2490,7 @@ void bpf_link_put(struct bpf_link *link)
 		bpf_link_free(link);
 	}
 }
+EXPORT_SYMBOL(bpf_link_put);
 
 static int bpf_link_release(struct inode *inode, struct file *filp)
 {
@@ -2632,6 +2633,7 @@ struct bpf_link *bpf_link_get_from_fd(u32 ufd)
 
 	return link;
 }
+EXPORT_SYMBOL(bpf_link_get_from_fd);
 
 struct bpf_tracing_link {
 	struct bpf_link link;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel.
  2022-02-04 23:17 ` [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel Alexei Starovoitov
@ 2022-02-07 20:04   ` Andrii Nakryiko
  2022-02-07 21:27     ` Alexei Starovoitov
  0 siblings, 1 reply; 12+ messages in thread
From: Andrii Nakryiko @ 2022-02-07 20:04 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: David S. Miller, Daniel Borkmann, Andrii Nakryiko, bpf, Kernel Team

On Fri, Feb 4, 2022 at 3:17 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> From: Alexei Starovoitov <ast@kernel.org>
>
> Prepare light skeleton to be used in the kernel module and in the user space.
> The look and feel of lskel.h is mostly the same with the difference that for
> user space the skel->rodata is the same pointer before and after skel_load
> operation, while in the kernel the skel->rodata after skel_open and the
> skel->rodata after skel_load are different pointers.
> Typical usage of skeleton remains the same for kernel and user space:
> skel = my_bpf__open();
> skel->rodata->my_global_var = init_val;
> err = my_bpf__load(skel);
> err = my_bpf__attach(skel);
> // access skel->rodata->my_global_var;
> // access skel->bss->another_var;
>
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
> ---
>  tools/lib/bpf/skel_internal.h | 168 +++++++++++++++++++++++++++++++---
>  1 file changed, 153 insertions(+), 15 deletions(-)
>
> diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h
> index dcd3336512d4..4d99ef8cbbba 100644
> --- a/tools/lib/bpf/skel_internal.h
> +++ b/tools/lib/bpf/skel_internal.h
> @@ -3,9 +3,19 @@
>  #ifndef __SKEL_INTERNAL_H
>  #define __SKEL_INTERNAL_H
>
> +#ifdef __KERNEL__
> +#include <linux/fdtable.h>
> +#include <linux/mm.h>
> +#include <linux/mman.h>
> +#include <linux/slab.h>
> +#include <linux/bpf.h>
> +#else
>  #include <unistd.h>
>  #include <sys/syscall.h>
>  #include <sys/mman.h>
> +#include <stdlib.h>
> +#include "bpf.h"
> +#endif
>
>  #ifndef __NR_bpf
>  # if defined(__mips__) && defined(_ABIO32)
> @@ -25,16 +35,12 @@
>   * requested during loader program generation.
>   */
>  struct bpf_map_desc {
> -       union {
> -               /* input for the loader prog */
> -               struct {
> -                       __aligned_u64 initial_value;
> -                       __u32 max_entries;
> -               };
> +       struct {

Is this anonymous struct still needed?

>                 /* output of the loader prog */
> -               struct {
> -                       int map_fd;
> -               };
> +               int map_fd;
> +               /* input for the loader prog */
> +               __u32 max_entries;
> +               __aligned_u64 initial_value;
>         };
>  };
>  struct bpf_prog_desc {
> @@ -57,11 +63,135 @@ struct bpf_load_and_run_opts {
>         const char *errstr;
>  };
>
> +long bpf_sys_bpf(__u32 cmd, void *attr, __u32 attr_size);
> +
>  static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
>                           unsigned int size)
>  {
> +#ifdef __KERNEL__
> +       return bpf_sys_bpf(cmd, attr, size);
> +#else
>         return syscall(__NR_bpf, cmd, attr, size);
> +#endif
> +}
> +
> +#ifdef __KERNEL__
> +static inline int close(int fd)
> +{
> +       return close_fd(fd);
> +}
> +static inline void *skel_alloc(size_t size)
> +{
> +       return kcalloc(1, size, GFP_KERNEL);
> +}
> +static inline void skel_free(const void *p)
> +{
> +       kfree(p);
> +}

any reason to skim on empty lines between functions? The rest of this
file (and libbpf code in general) feels very different in terms of
spacing.

> +static inline void skel_free_map_data(void *p, __u64 addr, size_t sz)
> +{
> +       if (addr && addr != ~0ULL)
> +               vm_munmap(addr, sz);
> +       if (addr != ~0ULL)
> +               kvfree(p);

minor nit: a small comment explaining that we set addr to ~0ULL on
error (but we still call skel_free_map_data) would help a bit here

> +}
> +/* skel->bss/rodata maps are populated in three steps.
> + *
> + * For kernel use:
> + * skel_prep_map_data() allocates kernel memory that kernel module can directly access.
> + * skel_prep_init_value() allocates a region in user space process and copies
> + * potentially modified initial map value into it.
> + * The loader program will perform copy_from_user() from maps.rodata.initial_value.

I'm missing something here. If a light skeleton is used from a kernel
module, then this initialization data is also pointing to kernel
module memory, no? So why the copy_from_user() then?

Also this vm_mmap() and vm_munmap(), is it necessary for in-kernel
skeleton itself, or it's required so that if some user-space process
would fetch that BPF map by ID and tried to mmap() its content it
would be possible? Otherwise it's not clear, as kernel module can
access BPF array's value pointer directly anyways, so why the mmaping?


> + * skel_finalize_map_data() sets skel->rodata to point to actual value in a bpf map.
> + *
> + * For user space:
> + * skel_prep_map_data() mmaps anon memory into skel->rodata that can be accessed directly.
> + * skel_prep_init_value() copies rodata pointer into map.rodata.initial_value.
> + * The loader program will perform copy_from_user() from maps.rodata.initial_value.
> + * skel_finalize_map_data() remaps bpf array map value from the kernel memory into
> + * skel->rodata address.
> + */
> +static inline void *skel_prep_map_data(const void *val, size_t mmap_sz, size_t val_sz)
> +{
> +       void *addr;
> +
> +       addr = kvmalloc(val_sz, GFP_KERNEL);
> +       if (!addr)
> +               return NULL;
> +       memcpy(addr, val, val_sz);
> +       return addr;
> +}

[...]+

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel.
  2022-02-07 20:04   ` Andrii Nakryiko
@ 2022-02-07 21:27     ` Alexei Starovoitov
  2022-02-07 21:51       ` Andrii Nakryiko
  0 siblings, 1 reply; 12+ messages in thread
From: Alexei Starovoitov @ 2022-02-07 21:27 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: David S. Miller, Daniel Borkmann, Andrii Nakryiko, bpf, Kernel Team

On Mon, Feb 07, 2022 at 12:04:14PM -0800, Andrii Nakryiko wrote:
> >   */
> >  struct bpf_map_desc {
> > -       union {
> > -               /* input for the loader prog */
> > -               struct {
> > -                       __aligned_u64 initial_value;
> > -                       __u32 max_entries;
> > -               };
> > +       struct {
> 
> Is this anonymous struct still needed?

Right. Will remove.

> > +static inline void *skel_alloc(size_t size)
> > +{
> > +       return kcalloc(1, size, GFP_KERNEL);
> > +}
> > +static inline void skel_free(const void *p)
> > +{
> > +       kfree(p);
> > +}
> 
> any reason to skim on empty lines between functions? The rest of this
> file (and libbpf code in general) feels very different in terms of
> spacing.

Because it's more compact, but I don't mind extra lines.

> > +static inline void skel_free_map_data(void *p, __u64 addr, size_t sz)
> > +{
> > +       if (addr && addr != ~0ULL)
> > +               vm_munmap(addr, sz);
> > +       if (addr != ~0ULL)
> > +               kvfree(p);
> 
> minor nit: a small comment explaining that we set addr to ~0ULL on
> error (but we still call skel_free_map_data) would help a bit here

ok.

> > +}
> > +/* skel->bss/rodata maps are populated in three steps.
> > + *
> > + * For kernel use:
> > + * skel_prep_map_data() allocates kernel memory that kernel module can directly access.
> > + * skel_prep_init_value() allocates a region in user space process and copies
> > + * potentially modified initial map value into it.
> > + * The loader program will perform copy_from_user() from maps.rodata.initial_value.
> 
> I'm missing something here. If a light skeleton is used from a kernel
> module, then this initialization data is also pointing to kernel
> module memory, no? So why the copy_from_user() then?
> 
> Also this vm_mmap() and vm_munmap(), is it necessary for in-kernel
> skeleton itself, or it's required so that if some user-space process
> would fetch that BPF map by ID and tried to mmap() its content it
> would be possible? Otherwise it's not clear, as kernel module can
> access BPF array's value pointer directly anyways, so why the mmaping?

vm_mmap step only to preserve one version of light skeleton that
works for both user space and kernel. Otherwise bpftool would need another flag
and test coverage would need to increase. This way light skeleton for kernel
doesn't need a bunch of new tests.
Another option would be to add 'is_kernel' flag to bpf_loader_ctx and generate
loader program like:
if (ctx->is_kernel)
  bpf_probe_read_kernel
else
  bpf_copy_from_user

but 'ctx' will be modified after signature check, so the user space user
of light skel might trick it to populate maps with garbage kernel data.
The loader prog needs cap_perfmon anyway, so there are no security concerns,
but it's not great to have such room for error.
vm_mmap approach is not pretty, but looks to be the lesser evil.
I'm all ears if there are other options.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel.
  2022-02-07 21:27     ` Alexei Starovoitov
@ 2022-02-07 21:51       ` Andrii Nakryiko
  0 siblings, 0 replies; 12+ messages in thread
From: Andrii Nakryiko @ 2022-02-07 21:51 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: David S. Miller, Daniel Borkmann, Andrii Nakryiko, bpf, Kernel Team

On Mon, Feb 7, 2022 at 1:27 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Mon, Feb 07, 2022 at 12:04:14PM -0800, Andrii Nakryiko wrote:
> > >   */
> > >  struct bpf_map_desc {
> > > -       union {
> > > -               /* input for the loader prog */
> > > -               struct {
> > > -                       __aligned_u64 initial_value;
> > > -                       __u32 max_entries;
> > > -               };
> > > +       struct {
> >
> > Is this anonymous struct still needed?
>
> Right. Will remove.
>
> > > +static inline void *skel_alloc(size_t size)
> > > +{
> > > +       return kcalloc(1, size, GFP_KERNEL);
> > > +}
> > > +static inline void skel_free(const void *p)
> > > +{
> > > +       kfree(p);
> > > +}
> >
> > any reason to skim on empty lines between functions? The rest of this
> > file (and libbpf code in general) feels very different in terms of
> > spacing.
>
> Because it's more compact, but I don't mind extra lines.
>
> > > +static inline void skel_free_map_data(void *p, __u64 addr, size_t sz)
> > > +{
> > > +       if (addr && addr != ~0ULL)
> > > +               vm_munmap(addr, sz);
> > > +       if (addr != ~0ULL)
> > > +               kvfree(p);
> >
> > minor nit: a small comment explaining that we set addr to ~0ULL on
> > error (but we still call skel_free_map_data) would help a bit here
>
> ok.
>
> > > +}
> > > +/* skel->bss/rodata maps are populated in three steps.
> > > + *
> > > + * For kernel use:
> > > + * skel_prep_map_data() allocates kernel memory that kernel module can directly access.
> > > + * skel_prep_init_value() allocates a region in user space process and copies
> > > + * potentially modified initial map value into it.
> > > + * The loader program will perform copy_from_user() from maps.rodata.initial_value.
> >
> > I'm missing something here. If a light skeleton is used from a kernel
> > module, then this initialization data is also pointing to kernel
> > module memory, no? So why the copy_from_user() then?
> >
> > Also this vm_mmap() and vm_munmap(), is it necessary for in-kernel
> > skeleton itself, or it's required so that if some user-space process
> > would fetch that BPF map by ID and tried to mmap() its content it
> > would be possible? Otherwise it's not clear, as kernel module can
> > access BPF array's value pointer directly anyways, so why the mmaping?
>
> vm_mmap step only to preserve one version of light skeleton that
> works for both user space and kernel. Otherwise bpftool would need another flag
> and test coverage would need to increase. This way light skeleton for kernel
> doesn't need a bunch of new tests.
> Another option would be to add 'is_kernel' flag to bpf_loader_ctx and generate
> loader program like:
> if (ctx->is_kernel)
>   bpf_probe_read_kernel
> else
>   bpf_copy_from_user
>
> but 'ctx' will be modified after signature check, so the user space user
> of light skel might trick it to populate maps with garbage kernel data.
> The loader prog needs cap_perfmon anyway, so there are no security concerns,
> but it's not great to have such room for error.
> vm_mmap approach is not pretty, but looks to be the lesser evil.
> I'm all ears if there are other options.

Ah, ok, I didn't get that. Please leave comments explaining this. I
have no preference regarding ctx->is_kernel vs doing in-kernel
vm_mmap(), but this needs to be spelled out, as it's very non-obvious.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs.
  2022-02-04 23:17 ` [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs Alexei Starovoitov
@ 2022-02-08 16:20     ` kernel test robot
  2022-02-08 17:11   ` Yonghong Song
  1 sibling, 0 replies; 12+ messages in thread
From: kernel test robot @ 2022-02-08 16:20 UTC (permalink / raw)
  To: Alexei Starovoitov; +Cc: llvm, kbuild-all

Hi Alexei,

I love your patch! Perhaps something to improve:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Alexei-Starovoitov/bpf-Light-skeleton-for-the-kernel/20220205-071811
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: mips-buildonly-randconfig-r001-20220208 (https://download.01.org/0day-ci/archive/20220209/202202090005.4wGpcCXF-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project e8bff9ae54a55b4dbfeb6ba55f723abbd81bf494)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install mips cross compiling tool for clang build
        # apt-get install binutils-mips-linux-gnu
        # https://github.com/0day-ci/linux/commit/cf2c9222692d0cb93d17ab3ff9f972b40a0b7864
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Alexei-Starovoitov/bpf-Light-skeleton-for-the-kernel/20220205-071811
        git checkout cf2c9222692d0cb93d17ab3ff9f972b40a0b7864
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=mips SHELL=/bin/bash kernel/bpf/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> kernel/bpf/syscall.c:4762:19: warning: unused variable 'prog'
   struct bpf_prog
   ^
   fatal error: error in backend: Nested variants found in inline asm string: ' .set push
   .set mips64r2
   .if ( 0x00 ) != -1)) 0x00 ) != -1)) : ($( static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = $( .func = __func__, .file = "arch/mips/include/asm/atomic.h", .line = 156, $); 0x00 ) != -1)) : $))) ) && ( 0 ); .set push; .set mips64r2; .rept 1; sync 0x00; .endr; .set pop; .else; ; .endif
   1: ll $1, $2 # atomic_sub_return
   subu $0, $1, $3
   sc $0, $2
   beqz $0, 1b
   subu $0, $1, $3
   .set pop
   '
   PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
   Stack dump:
   0. Program arguments: clang -Wp,-MMD,kernel/bpf/.syscall.o.d -nostdinc -Iarch/mips/include -I./arch/mips/include/generated -Iinclude -I./include -Iarch/mips/include/uapi -I./arch/mips/include/generated/uapi -Iinclude/uapi -I./include/generated/uapi -include include/linux/compiler-version.h -include include/linux/kconfig.h -include include/linux/compiler_types.h -D__KERNEL__ -DVMLINUX_LOAD_ADDRESS=0xffffffff80060000 -DLINKER_LOAD_ADDRESS=0x80060000 -DDATAOFFSET=0 -Qunused-arguments -fmacro-prefix-map== -DKBUILD_EXTRA_WARN1 -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 --target=mips-linux -fintegrated-as -Werror=unknown-warning-option -Werror=ignored-optimization-argument -mno-check-zero-division -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -DGAS_HAS_SET_HARDFLOAT -Wa,-msoft-float -ffreestanding -EB -fno-stack-check -march=mips32r2 -Wa,--trap -DTOOLCHAIN_SUPPORTS_VIRT -Iarch/mips/include/asm/mach-ath79 -Iarch/mips/include/asm/mach-generic -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-address-of-packed-member -O2 -Wframe-larger-than=1024 -fno-stack-protector -Wimplicit-fallthrough -Wno-gnu -mno-global-merge -Wno-unused-but-set-variable -Wno-unused-const-variable -ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang -fno-stack-clash-protection -pg -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wcast-function-type -Wno-array-bounds -fno-strict-overflow -fno-stack-check -Werror=date-time -Werror=incompatible-pointer-types -Wextra -Wunused -Wno-unused-parameter -Wmissing-declarations -Wmissing-format-attribute -Wmissing-prototypes -Wold-style-definition -Wmissing-include-dirs -Wunused-but-set-variable -Wunused-const-variable -Wno-missing-field-initializers -Wno-sign-compare -Wno-type-limits -I kernel/bpf -I ./kernel/bpf -ffunction-sections -fdata-sections -DKBUILD_MODFILE="kernel/bpf/syscall" -DKBUILD_BASENAME="syscall" -DKBUILD_MODNAME="syscall" -D__KBUILD_MODNAME=kmod_syscall -c -o kernel/bpf/syscall.o kernel/bpf/syscall.c
   1. <eof> parser at end of file
   2. Code generation
   3. Running pass 'Function Pass Manager' on module 'kernel/bpf/syscall.c'.
   4. Running pass 'Mips Assembly Printer' on function '@bpf_map_free_deferred'
   #0 0x0000564a3997132f Signals.cpp:0:0
   #1 0x0000564a3996f20c llvm::sys::CleanupOnSignal(unsigned long) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x346420c)
   #2 0x0000564a398af687 llvm::CrashRecoveryContext::HandleExit(int) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x33a4687)
   #3 0x0000564a399678be llvm::sys::Process::Exit(int, bool) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x345c8be)
   #4 0x0000564a375aee3b (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x10a3e3b)
   #5 0x0000564a398b613c llvm::report_fatal_error(llvm::Twine const&, bool) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x33ab13c)
   #6 0x0000564a3a5a55a0 llvm::AsmPrinter::emitInlineAsm(llvm::MachineInstr const (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x409a5a0)
   #7 0x0000564a3a5a14d4 llvm::AsmPrinter::emitFunctionBody() (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x40964d4)
   #8 0x0000564a38016b57 llvm::MipsAsmPrinter::runOnMachineFunction(llvm::MachineFunction&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x1b0bb57)
   #9 0x0000564a38cc85dd llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.53) MachineFunctionPass.cpp:0:0
   #10 0x0000564a39103d97 llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x2bf8d97)
   #11 0x0000564a39103f11 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x2bf8f11)
   #12 0x0000564a39104a8f llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x2bf9a8f)
   #13 0x0000564a39c88ef7 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x377def7)
   #14 0x0000564a3a8bdb63 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x43b2b63)
   #15 0x0000564a3b392e29 clang::ParseAST(clang::Sema&, bool, bool) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x4e87e29)
   #16 0x0000564a3a8bc99f clang::CodeGenAction::ExecuteAction() (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x43b199f)
   #17 0x0000564a3a2bb1e1 clang::FrontendAction::Execute() (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3db01e1)
   #18 0x0000564a3a25211a clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3d4711a)
   #19 0x0000564a3a37f85b (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3e7485b)
   #20 0x0000564a375b03ec cc1_main(llvm::ArrayRef<char char (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x10a53ec)
   #21 0x0000564a375ad0bb ExecuteCC1Tool(llvm::SmallVectorImpl<char driver.cpp:0:0
   #22 0x0000564a3a0e9c85 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> const::'lambda'()>(long) Job.cpp:0:0
   #23 0x0000564a398af543 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x33a4543)
   #24 0x0000564a3a0ea57e clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> const (.part.216) Job.cpp:0:0
   #25 0x0000564a3a0bf177 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3bb4177)
   #26 0x0000564a3a0bfb57 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command >&) const (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3bb4b57)
   #27 0x0000564a3a0c91e9 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command >&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3bbe1e9)
   #28 0x0000564a374d626f main (/opt/cross/clang-e8bff9ae54/bin/clang-15+0xfcb26f)
   #29 0x00007fa3ac551d0a __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26d0a)
   #30 0x0000564a375acbda _start (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x10a1bda)
   clang-15: error: clang frontend command failed with exit code 70 (use -v to see invocation)
   clang version 15.0.0 (git://gitmirror/llvm_project e8bff9ae54a55b4dbfeb6ba55f723abbd81bf494)
   Target: mips-unknown-linux
   Thread model: posix
   InstalledDir: /opt/cross/clang-e8bff9ae54/bin
   clang-15: note: diagnostic msg:
   Makefile arch include kernel nr_bisected scripts source usr


vim +/prog +4762 kernel/bpf/syscall.c

  4759	
  4760	BPF_CALL_3(bpf_sys_bpf, int, cmd, union bpf_attr *, attr, u32, attr_size)
  4761	{
> 4762		struct bpf_prog *prog;
  4763	
  4764		switch (cmd) {
  4765		case BPF_MAP_CREATE:
  4766		case BPF_MAP_UPDATE_ELEM:
  4767		case BPF_MAP_FREEZE:
  4768		case BPF_PROG_LOAD:
  4769		case BPF_BTF_LOAD:
  4770		case BPF_LINK_CREATE:
  4771		case BPF_RAW_TRACEPOINT_OPEN:
  4772			break;
  4773	#ifdef CONFIG_BPF_JIT /* __bpf_prog_enter_sleepable used by trampoline and JIT */
  4774		case BPF_PROG_TEST_RUN:
  4775			if (attr->test.data_in || attr->test.data_out ||
  4776			    attr->test.ctx_out || attr->test.duration ||
  4777			    attr->test.repeat || attr->test.flags)
  4778				return -EINVAL;
  4779	
  4780			prog = bpf_prog_get_type(attr->test.prog_fd, BPF_PROG_TYPE_SYSCALL);
  4781			if (IS_ERR(prog))
  4782				return PTR_ERR(prog);
  4783	
  4784			if (attr->test.ctx_size_in < prog->aux->max_ctx_offset ||
  4785			    attr->test.ctx_size_in > U16_MAX) {
  4786				bpf_prog_put(prog);
  4787				return -EINVAL;
  4788			}
  4789	
  4790			if (!__bpf_prog_enter_sleepable(prog)) {
  4791				/* recursion detected */
  4792				bpf_prog_put(prog);
  4793				return -EBUSY;
  4794			}
  4795			attr->test.retval = bpf_prog_run(prog, (void *) (long) attr->test.ctx_in);
  4796			__bpf_prog_exit_sleepable(prog, 0 /* bpf_prog_run does runtime stats */);
  4797			bpf_prog_put(prog);
  4798			return 0;
  4799	#endif
  4800		default:
  4801			return -EINVAL;
  4802		}
  4803		return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size);
  4804	}
  4805	EXPORT_SYMBOL(bpf_sys_bpf);
  4806	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs.
@ 2022-02-08 16:20     ` kernel test robot
  0 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2022-02-08 16:20 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 11422 bytes --]

Hi Alexei,

I love your patch! Perhaps something to improve:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Alexei-Starovoitov/bpf-Light-skeleton-for-the-kernel/20220205-071811
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: mips-buildonly-randconfig-r001-20220208 (https://download.01.org/0day-ci/archive/20220209/202202090005.4wGpcCXF-lkp(a)intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project e8bff9ae54a55b4dbfeb6ba55f723abbd81bf494)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install mips cross compiling tool for clang build
        # apt-get install binutils-mips-linux-gnu
        # https://github.com/0day-ci/linux/commit/cf2c9222692d0cb93d17ab3ff9f972b40a0b7864
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Alexei-Starovoitov/bpf-Light-skeleton-for-the-kernel/20220205-071811
        git checkout cf2c9222692d0cb93d17ab3ff9f972b40a0b7864
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=mips SHELL=/bin/bash kernel/bpf/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> kernel/bpf/syscall.c:4762:19: warning: unused variable 'prog'
   struct bpf_prog
   ^
   fatal error: error in backend: Nested variants found in inline asm string: ' .set push
   .set mips64r2
   .if ( 0x00 ) != -1)) 0x00 ) != -1)) : ($( static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = $( .func = __func__, .file = "arch/mips/include/asm/atomic.h", .line = 156, $); 0x00 ) != -1)) : $))) ) && ( 0 ); .set push; .set mips64r2; .rept 1; sync 0x00; .endr; .set pop; .else; ; .endif
   1: ll $1, $2 # atomic_sub_return
   subu $0, $1, $3
   sc $0, $2
   beqz $0, 1b
   subu $0, $1, $3
   .set pop
   '
   PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
   Stack dump:
   0. Program arguments: clang -Wp,-MMD,kernel/bpf/.syscall.o.d -nostdinc -Iarch/mips/include -I./arch/mips/include/generated -Iinclude -I./include -Iarch/mips/include/uapi -I./arch/mips/include/generated/uapi -Iinclude/uapi -I./include/generated/uapi -include include/linux/compiler-version.h -include include/linux/kconfig.h -include include/linux/compiler_types.h -D__KERNEL__ -DVMLINUX_LOAD_ADDRESS=0xffffffff80060000 -DLINKER_LOAD_ADDRESS=0x80060000 -DDATAOFFSET=0 -Qunused-arguments -fmacro-prefix-map== -DKBUILD_EXTRA_WARN1 -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 --target=mips-linux -fintegrated-as -Werror=unknown-warning-option -Werror=ignored-optimization-argument -mno-check-zero-division -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -DGAS_HAS_SET_HARDFLOAT -Wa,-msoft-float -ffreestanding -EB -fno-stack-check -march=mips32r2 -Wa,--trap -DTOOLCHAIN_SUPPORTS_VIRT -Iarch/mips/include/asm/mach-ath79 -Iarch/mips/include/asm/mach-generic -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-address-of-packed-member -O2 -Wframe-larger-than=1024 -fno-stack-protector -Wimplicit-fallthrough -Wno-gnu -mno-global-merge -Wno-unused-but-set-variable -Wno-unused-const-variable -ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang -fno-stack-clash-protection -pg -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wcast-function-type -Wno-array-bounds -fno-strict-overflow -fno-stack-check -Werror=date-time -Werror=incompatible-pointer-types -Wextra -Wunused -Wno-unused-parameter -Wmissing-declarations -Wmissing-format-attribute -Wmissing-prototypes -Wold-style-definition -Wmissing-include-dirs -Wunused-but-set-variable -Wunused-const-variable -Wno-missing-field-initializers -Wno-sign-compare -Wno-type-limits -I kernel/bpf -I ./kernel/bpf -ffunction-sections -fdata-sections -DKBUILD_MODFILE="kernel/bpf/syscall" -DKBUILD_BASENAME="syscall" -DKBUILD_MODNAME="syscall" -D__KBUILD_MODNAME=kmod_syscall -c -o kernel/bpf/syscall.o kernel/bpf/syscall.c
   1. <eof> parser at end of file
   2. Code generation
   3. Running pass 'Function Pass Manager' on module 'kernel/bpf/syscall.c'.
   4. Running pass 'Mips Assembly Printer' on function '@bpf_map_free_deferred'
   #0 0x0000564a3997132f Signals.cpp:0:0
   #1 0x0000564a3996f20c llvm::sys::CleanupOnSignal(unsigned long) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x346420c)
   #2 0x0000564a398af687 llvm::CrashRecoveryContext::HandleExit(int) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x33a4687)
   #3 0x0000564a399678be llvm::sys::Process::Exit(int, bool) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x345c8be)
   #4 0x0000564a375aee3b (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x10a3e3b)
   #5 0x0000564a398b613c llvm::report_fatal_error(llvm::Twine const&, bool) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x33ab13c)
   #6 0x0000564a3a5a55a0 llvm::AsmPrinter::emitInlineAsm(llvm::MachineInstr const (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x409a5a0)
   #7 0x0000564a3a5a14d4 llvm::AsmPrinter::emitFunctionBody() (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x40964d4)
   #8 0x0000564a38016b57 llvm::MipsAsmPrinter::runOnMachineFunction(llvm::MachineFunction&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x1b0bb57)
   #9 0x0000564a38cc85dd llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.53) MachineFunctionPass.cpp:0:0
   #10 0x0000564a39103d97 llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x2bf8d97)
   #11 0x0000564a39103f11 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x2bf8f11)
   #12 0x0000564a39104a8f llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x2bf9a8f)
   #13 0x0000564a39c88ef7 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x377def7)
   #14 0x0000564a3a8bdb63 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x43b2b63)
   #15 0x0000564a3b392e29 clang::ParseAST(clang::Sema&, bool, bool) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x4e87e29)
   #16 0x0000564a3a8bc99f clang::CodeGenAction::ExecuteAction() (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x43b199f)
   #17 0x0000564a3a2bb1e1 clang::FrontendAction::Execute() (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3db01e1)
   #18 0x0000564a3a25211a clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3d4711a)
   #19 0x0000564a3a37f85b (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3e7485b)
   #20 0x0000564a375b03ec cc1_main(llvm::ArrayRef<char char (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x10a53ec)
   #21 0x0000564a375ad0bb ExecuteCC1Tool(llvm::SmallVectorImpl<char driver.cpp:0:0
   #22 0x0000564a3a0e9c85 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> const::'lambda'()>(long) Job.cpp:0:0
   #23 0x0000564a398af543 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x33a4543)
   #24 0x0000564a3a0ea57e clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> const (.part.216) Job.cpp:0:0
   #25 0x0000564a3a0bf177 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3bb4177)
   #26 0x0000564a3a0bfb57 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command >&) const (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3bb4b57)
   #27 0x0000564a3a0c91e9 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command >&) (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x3bbe1e9)
   #28 0x0000564a374d626f main (/opt/cross/clang-e8bff9ae54/bin/clang-15+0xfcb26f)
   #29 0x00007fa3ac551d0a __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26d0a)
   #30 0x0000564a375acbda _start (/opt/cross/clang-e8bff9ae54/bin/clang-15+0x10a1bda)
   clang-15: error: clang frontend command failed with exit code 70 (use -v to see invocation)
   clang version 15.0.0 (git://gitmirror/llvm_project e8bff9ae54a55b4dbfeb6ba55f723abbd81bf494)
   Target: mips-unknown-linux
   Thread model: posix
   InstalledDir: /opt/cross/clang-e8bff9ae54/bin
   clang-15: note: diagnostic msg:
   Makefile arch include kernel nr_bisected scripts source usr


vim +/prog +4762 kernel/bpf/syscall.c

  4759	
  4760	BPF_CALL_3(bpf_sys_bpf, int, cmd, union bpf_attr *, attr, u32, attr_size)
  4761	{
> 4762		struct bpf_prog *prog;
  4763	
  4764		switch (cmd) {
  4765		case BPF_MAP_CREATE:
  4766		case BPF_MAP_UPDATE_ELEM:
  4767		case BPF_MAP_FREEZE:
  4768		case BPF_PROG_LOAD:
  4769		case BPF_BTF_LOAD:
  4770		case BPF_LINK_CREATE:
  4771		case BPF_RAW_TRACEPOINT_OPEN:
  4772			break;
  4773	#ifdef CONFIG_BPF_JIT /* __bpf_prog_enter_sleepable used by trampoline and JIT */
  4774		case BPF_PROG_TEST_RUN:
  4775			if (attr->test.data_in || attr->test.data_out ||
  4776			    attr->test.ctx_out || attr->test.duration ||
  4777			    attr->test.repeat || attr->test.flags)
  4778				return -EINVAL;
  4779	
  4780			prog = bpf_prog_get_type(attr->test.prog_fd, BPF_PROG_TYPE_SYSCALL);
  4781			if (IS_ERR(prog))
  4782				return PTR_ERR(prog);
  4783	
  4784			if (attr->test.ctx_size_in < prog->aux->max_ctx_offset ||
  4785			    attr->test.ctx_size_in > U16_MAX) {
  4786				bpf_prog_put(prog);
  4787				return -EINVAL;
  4788			}
  4789	
  4790			if (!__bpf_prog_enter_sleepable(prog)) {
  4791				/* recursion detected */
  4792				bpf_prog_put(prog);
  4793				return -EBUSY;
  4794			}
  4795			attr->test.retval = bpf_prog_run(prog, (void *) (long) attr->test.ctx_in);
  4796			__bpf_prog_exit_sleepable(prog, 0 /* bpf_prog_run does runtime stats */);
  4797			bpf_prog_put(prog);
  4798			return 0;
  4799	#endif
  4800		default:
  4801			return -EINVAL;
  4802		}
  4803		return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size);
  4804	}
  4805	EXPORT_SYMBOL(bpf_sys_bpf);
  4806	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs.
  2022-02-04 23:17 ` [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs Alexei Starovoitov
  2022-02-08 16:20     ` kernel test robot
@ 2022-02-08 17:11   ` Yonghong Song
  1 sibling, 0 replies; 12+ messages in thread
From: Yonghong Song @ 2022-02-08 17:11 UTC (permalink / raw)
  To: Alexei Starovoitov, davem; +Cc: daniel, andrii, bpf, kernel-team



On 2/4/22 3:17 PM, Alexei Starovoitov wrote:
> From: Alexei Starovoitov <ast@kernel.org>
> 
> bpf_sycall programs can be used directly by the kernel modules
> to load programs and create maps via kernel skeleton.
> . Export bpf_sys_bpf syscall wrapper to be used in kernel skeleton.
> . Export bpf_map_get to be used in kernel skeleton.
> . Allow prog_run cmd for bpf_syscall programs with recursion check.
> . Enable link_create and raw_tp_open cmds.
> 
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>

Acked-by: Yonghong Song <yhs@fb.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-02-08 17:12 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-04 23:17 [PATCH bpf-next 0/5] bpf: Light skeleton for the kernel Alexei Starovoitov
2022-02-04 23:17 ` [PATCH bpf-next 1/5] bpf: Extend sys_bpf commands for bpf_syscall programs Alexei Starovoitov
2022-02-08 16:20   ` kernel test robot
2022-02-08 16:20     ` kernel test robot
2022-02-08 17:11   ` Yonghong Song
2022-02-04 23:17 ` [PATCH bpf-next 2/5] libbpf: Prepare light skeleton for the kernel Alexei Starovoitov
2022-02-07 20:04   ` Andrii Nakryiko
2022-02-07 21:27     ` Alexei Starovoitov
2022-02-07 21:51       ` Andrii Nakryiko
2022-02-04 23:17 ` [PATCH bpf-next 3/5] bpftool: Generalize light skeleton generation Alexei Starovoitov
2022-02-04 23:17 ` [PATCH bpf-next 4/5] bpf: Update iterators.lskel.h Alexei Starovoitov
2022-02-04 23:17 ` [PATCH bpf-next 5/5] bpf: Convert bpf_preload.ko to use light skeleton Alexei Starovoitov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.