Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: btf: Add BPF_OBJ_GET_INFO_BY_FD support to BTF fd

This patch adds BPF_OBJ_GET_INFO_BY_FD support to BTF fd.
The original BTF data, which was used to create the BTF fd during
the earlier BPF_BTF_LOAD call, will be returned.

The userspace is expected to allocate buffer
to info.info and the buffer size is set to info.info_len before
calling BPF_OBJ_GET_INFO_BY_FD.

The original BTF data is copied to the userspace buffer (info.info).
Only upto the user's specified info.info_len will be copied.

The original BTF data size is set to info.info_len. The userspace
needs to check if it is bigger than its allocated buffer size.
If it is, the userspace should realloc with the kernel-returned
info.info_len and call the BPF_OBJ_GET_INFO_BY_FD again.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Martin KaFai Lau and committed by
Daniel Borkmann
60197cfb f56a653c

+23 -1
+5
include/linux/btf.h
··· 10 10 struct btf_type; 11 11 union bpf_attr; 12 12 13 + extern const struct file_operations btf_fops; 14 + 13 15 void btf_put(struct btf *btf); 14 16 int btf_new_fd(const union bpf_attr *attr); 15 17 struct btf *btf_get_by_fd(int fd); 18 + int btf_get_info_by_fd(const struct btf *btf, 19 + const union bpf_attr *attr, 20 + union bpf_attr __user *uattr); 16 21 /* Figure out the size of a type_id. If type_id is a modifier 17 22 * (e.g. const), it will be resolved to find out the type with size. 18 23 *
+16 -1
kernel/bpf/btf.c
··· 2002 2002 return 0; 2003 2003 } 2004 2004 2005 - static const struct file_operations btf_fops = { 2005 + const struct file_operations btf_fops = { 2006 2006 .release = btf_release, 2007 2007 }; 2008 2008 ··· 2046 2046 fdput(f); 2047 2047 2048 2048 return btf; 2049 + } 2050 + 2051 + int btf_get_info_by_fd(const struct btf *btf, 2052 + const union bpf_attr *attr, 2053 + union bpf_attr __user *uattr) 2054 + { 2055 + void __user *udata = u64_to_user_ptr(attr->info.info); 2056 + u32 copy_len = min_t(u32, btf->data_size, 2057 + attr->info.info_len); 2058 + 2059 + if (copy_to_user(udata, btf->data, copy_len) || 2060 + put_user(btf->data_size, &uattr->info.info_len)) 2061 + return -EFAULT; 2062 + 2063 + return 0; 2049 2064 }
+2
kernel/bpf/syscall.c
··· 2017 2017 else if (f.file->f_op == &bpf_map_fops) 2018 2018 err = bpf_map_get_info_by_fd(f.file->private_data, attr, 2019 2019 uattr); 2020 + else if (f.file->f_op == &btf_fops) 2021 + err = btf_get_info_by_fd(f.file->private_data, attr, uattr); 2020 2022 else 2021 2023 err = -EINVAL; 2022 2024