Context |
Check |
Description |
netdev/series_format |
warning
|
Series does not have a cover letter
|
netdev/tree_selection |
success
|
Guessed tree name to be net-next, async
|
netdev/ynl |
success
|
Generated files up to date;
no warnings/errors;
no diff in generated;
|
netdev/fixes_present |
success
|
Fixes tag not required for -next series
|
netdev/header_inline |
success
|
No static functions without inline keyword in header files
|
netdev/build_32bit |
fail
|
Errors and warnings before: 7 this patch: 9
|
netdev/build_tools |
success
|
No tools touched, skip
|
netdev/cc_maintainers |
fail
|
12 maintainers not CCed: jolsa@kernel.org john.fastabend@gmail.com ast@kernel.org daniel@iogearbox.net martin.lau@linux.dev yonghong.song@linux.dev eddyz87@gmail.com andrii@kernel.org song@kernel.org sdf@fomichev.me kpsingh@kernel.org haoluo@google.com
|
netdev/build_clang |
success
|
Errors and warnings before: 11 this patch: 11
|
netdev/verify_signedoff |
success
|
Signed-off-by tag matches author and committer
|
netdev/deprecated_api |
success
|
None detected
|
netdev/check_selftest |
success
|
No net selftest shell script
|
netdev/verify_fixes |
success
|
No Fixes tag
|
netdev/build_allmodconfig_warn |
fail
|
Errors and warnings before: 7 this patch: 9
|
netdev/checkpatch |
warning
|
CHECK: Please don't use multiple blank lines
WARNING: line length of 100 exceeds 80 columns
WARNING: line length of 81 exceeds 80 columns
WARNING: line length of 84 exceeds 80 columns
WARNING: line length of 94 exceeds 80 columns
WARNING: line length of 97 exceeds 80 columns
WARNING: line length of 99 exceeds 80 columns
|
netdev/build_clang_rust |
success
|
No Rust files in patch. Skipping build
|
netdev/kdoc |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/source_inline |
success
|
Was 0 now: 0
|
bpf/vmtest-bpf-net-VM_Test-1 |
success
|
Logs for ShellCheck
|
bpf/vmtest-bpf-net-VM_Test-3 |
success
|
Logs for Validate matrix.py
|
bpf/vmtest-bpf-net-VM_Test-2 |
success
|
Logs for Unittests
|
bpf/vmtest-bpf-net-VM_Test-5 |
success
|
Logs for aarch64-gcc / build-release
|
bpf/vmtest-bpf-net-VM_Test-0 |
success
|
Logs for Lint
|
bpf/vmtest-bpf-net-VM_Test-4 |
success
|
Logs for aarch64-gcc / build / build for aarch64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-10 |
success
|
Logs for aarch64-gcc / veristat-kernel
|
bpf/vmtest-bpf-net-VM_Test-11 |
success
|
Logs for aarch64-gcc / veristat-meta
|
bpf/vmtest-bpf-net-VM_Test-13 |
success
|
Logs for s390x-gcc / build-release
|
bpf/vmtest-bpf-net-VM_Test-6 |
success
|
Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-9 |
success
|
Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-12 |
success
|
Logs for s390x-gcc / build / build for s390x with gcc
|
bpf/vmtest-bpf-net-VM_Test-16 |
success
|
Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
|
bpf/vmtest-bpf-net-VM_Test-17 |
success
|
Logs for s390x-gcc / veristat-kernel
|
bpf/vmtest-bpf-net-VM_Test-18 |
success
|
Logs for s390x-gcc / veristat-meta
|
bpf/vmtest-bpf-net-VM_Test-19 |
success
|
Logs for set-matrix
|
bpf/vmtest-bpf-net-VM_Test-20 |
success
|
Logs for x86_64-gcc / build / build for x86_64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-21 |
success
|
Logs for x86_64-gcc / build-release
|
bpf/vmtest-bpf-net-VM_Test-30 |
success
|
Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
|
bpf/vmtest-bpf-net-VM_Test-31 |
success
|
Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
|
bpf/vmtest-bpf-net-VM_Test-36 |
success
|
Logs for x86_64-llvm-17 / veristat-kernel
|
bpf/vmtest-bpf-net-VM_Test-37 |
success
|
Logs for x86_64-llvm-17 / veristat-meta
|
bpf/vmtest-bpf-net-VM_Test-38 |
success
|
Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
|
bpf/vmtest-bpf-net-VM_Test-39 |
success
|
Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
|
bpf/vmtest-bpf-net-VM_Test-45 |
success
|
Logs for x86_64-llvm-18 / veristat-kernel
|
bpf/vmtest-bpf-net-VM_Test-46 |
success
|
Logs for x86_64-llvm-18 / veristat-meta
|
bpf/vmtest-bpf-net-VM_Test-7 |
fail
|
Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-8 |
fail
|
Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-15 |
fail
|
Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
|
bpf/vmtest-bpf-net-VM_Test-35 |
success
|
Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
|
bpf/vmtest-bpf-net-VM_Test-14 |
fail
|
Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
|
bpf/vmtest-bpf-net-VM_Test-22 |
success
|
Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-23 |
fail
|
Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-24 |
fail
|
Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-25 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-26 |
success
|
Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-27 |
success
|
Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
|
bpf/vmtest-bpf-net-VM_Test-28 |
success
|
Logs for x86_64-gcc / veristat-kernel / x86_64-gcc veristat_kernel
|
bpf/vmtest-bpf-net-VM_Test-29 |
success
|
Logs for x86_64-gcc / veristat-meta / x86_64-gcc veristat_meta
|
bpf/vmtest-bpf-net-VM_Test-32 |
success
|
Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
|
bpf/vmtest-bpf-net-VM_Test-33 |
fail
|
Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
|
bpf/vmtest-bpf-net-VM_Test-34 |
fail
|
Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
|
bpf/vmtest-bpf-net-VM_Test-44 |
success
|
Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
|
bpf/vmtest-bpf-net-PR |
fail
|
PR summary
|
bpf/vmtest-bpf-net-VM_Test-40 |
success
|
Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
|
bpf/vmtest-bpf-net-VM_Test-41 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
|
bpf/vmtest-bpf-net-VM_Test-42 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
|
bpf/vmtest-bpf-net-VM_Test-43 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
|
@@ -6074,6 +6074,245 @@ skip_mods_and_typedefs(const struct btf *btf, u32 id, u32 *res_id)
return t;
}
+static void free_bpf_obj(struct bpf_obj *obj)
+{
+ int i;
+
+ if (!obj)
+ return;
+
+ for (i = 0; i < obj->nr_programs; i++) {
+ kfree(obj->progs[i].insn);
+ kfree(obj->progs[i].reloc_desc);
+ }
+
+ kfree(obj->progs);
+ vfree(obj->hdr);
+
+ btf_put(obj->btf);
+ btf_put(obj->btf_vmlinux);
+ btf_ext__free(obj->btf_ext);
+
+ for (i = 0; i < obj->btf_modules_cnt; i++)
+ btf_put(obj->btf_modules[i].btf);
+
+ kfree(obj->btf_modules);
+ kfree(obj->externs);
+ kfree(obj->maps);
+}
+
+#define BPF_LOADER_INODE_NAME "bpf-loader"
+
+static const struct inode_operations bpf_loader_iops = { };
+
+static int bpf_loader_release(struct inode *inode, struct file *filp)
+{
+ struct bpf_obj *obj = filp->private_data;
+
+ free_bpf_obj(obj);
+ return 0;
+}
+
+static void bpf_loader_show_fdinfo(struct seq_file *m, struct file *filp)
+{
+ int i;
+ struct bpf_obj *obj = filp->private_data;
+
+ for (i = 0; i < obj->nr_programs; i++)
+ seq_printf(m, "program: %s\n", obj->progs[i].name);
+}
+
+static const struct file_operations bpf_loader_fops = {
+ .release = bpf_loader_release,
+ .show_fdinfo = bpf_loader_show_fdinfo,
+};
+
+static int loader_create(unsigned int bpffs_fd)
+{
+ struct inode *inode;
+ struct bpf_obj *obj = NULL;
+ struct file *file;
+ struct path path;
+ struct fd f;
+ umode_t mode;
+ int err, fd;
+
+ f = fdget(bpffs_fd);
+ if (!fd_file(f))
+ return -EBADF;
+
+ path = fd_file(f)->f_path;
+ path_get(&path);
+ fdput(f);
+
+ if (path.dentry != path.mnt->mnt_sb->s_root) {
+ err = -EINVAL;
+ goto out_path;
+ }
+ if (path.mnt->mnt_sb->s_op != &bpf_super_ops) {
+ err = -EINVAL;
+ goto out_path;
+ }
+ err = path_permission(&path, MAY_ACCESS);
+ if (err)
+ goto out_path;
+
+ mode = S_IFREG | (0600 & ~current_umask());
+ inode = bpf_get_inode(path.mnt->mnt_sb, NULL, mode);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ goto out_path;
+ }
+
+ inode->i_op = &bpf_loader_iops;
+ inode->i_fop = &bpf_loader_fops;
+ clear_nlink(inode);
+
+ file = alloc_file_pseudo(inode, path.mnt, BPF_LOADER_INODE_NAME, O_RDWR, &bpf_loader_fops);
+ if (IS_ERR(file)) {
+ err = PTR_ERR(file);
+ goto out_inode;
+ }
+
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj) {
+ err = -ENOMEM;
+ goto out_inode;
+ }
+
+ fd = get_unused_fd_flags(O_CLOEXEC);
+ if (fd < 0) {
+ err = fd;
+ kfree(obj);
+ goto out_inode;
+ }
+
+ file->private_data = obj;
+ fd_install(fd, file);
+ path_put(&path);
+ return fd;
+
+out_inode:
+ iput(inode);
+ fput(file);
+out_path:
+ path_put(&path);
+ return err;
+}
+
+static int load_fd(union bpf_attr *attr)
+{
+ void *buf = NULL;
+ int len;
+ int i;
+ int obj_f;
+ struct fd obj_fd;
+ struct bpf_module_obj *modules;
+ struct bpf_obj *obj;
+ int err;
+
+ struct fd f;
+ struct fd bpffs_fd;
+
+ f = fdget(attr->load_fd.obj_fd);
+ if (!fd_file(f)) {
+ err = -EBADF;
+ goto out;
+ }
+
+ bpffs_fd = fdget(attr->load_fd.bpffs_fd);
+ if (!fd_file(bpffs_fd)) {
+ fdput(f);
+ err = -EBADF;
+ goto out;
+ }
+
+ obj_f = loader_create(attr->load_fd.bpffs_fd);
+ if (obj_f < 0) {
+ err = obj_f;
+ fdput(f);
+ fdput(bpffs_fd);
+ goto out;
+ }
+
+ obj_fd = fdget(obj_f);
+ obj = fd_file(obj_fd)->private_data;
+
+ len = kernel_read_file(fd_file(f), 0, &buf, INT_MAX, NULL, READING_EBPF);
+ if (len < 0) {
+ fdput(obj_fd);
+ err = len;
+ goto out;
+ }
+
+ obj->hdr = buf;
+ obj->len = len;
+ obj->nr_maps = attr->load_fd.map_cnt;
+ obj->maps = kmalloc_array(attr->load_fd.map_cnt, sizeof(struct bpf_map_obj), GFP_KERNEL);
+
+ if (!obj->maps) {
+ err = -ENOMEM;
+ goto free;
+ }
+
+ if (attr->load_fd.map_cnt) {
+ if (copy_from_user(obj->maps, (const void *)attr->load_fd.maps,
+ sizeof(struct bpf_map_obj) * attr->load_fd.map_cnt) != 0) {
+ err = -EFAULT;
+ goto free;
+ }
+ }
+
+ obj->kconfig_map_idx = attr->load_fd.kconfig_map_idx;
+ obj->arena_map_idx = attr->load_fd.arena_map_idx;
+ obj->btf_vmlinux = bpf_get_btf_vmlinux();
+ modules = kmalloc_array(attr->load_fd.module_cnt,
+ sizeof(struct bpf_module_obj), GFP_KERNEL);
+
+ if (!modules) {
+ err = -ENOMEM;
+ goto free;
+ }
+
+
+ if (attr->load_fd.module_cnt) {
+ if (copy_from_user(modules, (const void *)attr->load_fd.modules,
+ sizeof(struct bpf_module_obj) * attr->load_fd.module_cnt) != 0) {
+ err = -EFAULT;
+ goto free;
+ }
+ }
+
+ obj->btf_modules_cnt = attr->load_fd.module_cnt;
+ obj->btf_modules = kmalloc_array(attr->load_fd.module_cnt,
+ sizeof(struct bpf_module_btf), GFP_KERNEL);
+
+ if (!obj->btf_modules) {
+ err = -ENOMEM;
+ goto free;
+ }
+
+ for (i = 0; i < obj->btf_modules_cnt; i++) {
+ obj->btf_modules[i].fd = modules[i].fd;
+ obj->btf_modules[i].id = modules[i].id;
+ obj->btf_modules[i].fd_array_idx = modules[i].fd_array_idx;
+ obj->btf_modules[i].btf = btf_get_by_fd(obj->btf_modules[i].fd);
+ if (IS_ERR(obj->btf_modules[i].btf)) {
+ err = PTR_ERR(obj->btf_modules[i].btf);
+ kfree(modules);
+ goto free;
+ }
+ }
+ kfree(modules);
+
+ return obj_f;
+free:
+ free_bpf_obj(obj);
+ fd_file(obj_fd)->private_data = NULL;
+out:
+ return err;
+}
+
static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
{
union bpf_attr attr;
@@ -6210,6 +6449,9 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
case BPF_TOKEN_CREATE:
err = token_create(&attr);
break;
+ case BPF_LOAD_FD:
+ err = load_fd(&attr);
+ break;
default:
err = -EINVAL;
break;
The new LOAD_FD subcommand keys off of a sysfs entry file descriptor and a file descriptor pointing to a raw elf object file. After performing some sysfs bookkeeping, the object file is copied into the kernel, and with map and module metadata arrays. Userspace is expected to provide an array of file descriptors that correspond to maps, along with module information, and offsets into the map array that correspond with the arena allocator and the kconfig map if applicable. Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com> --- kernel/bpf/syscall.c | 242 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+)