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.
Unified · Split
| @@ -10,9 +10,14 @@ struct btf; · 9 unmodified lines | ||
| 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 | * |
| @@ -2002,7 +2002,7 @@ static int btf_release(struct inode *inode, struct file *filp) · 2001 unmodified lines | ||
| 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 | |
| @@ -2047,3 +2047,18 @@ struct btf *btf_get_by_fd(int fd) · 38 unmodified lines | ||
| 2047 | 2047 | |
| 2048 | 2048 | return btf; |
| 2049 | 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; | |
| 2064 | +} | |
| @@ -2017,6 +2017,8 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, · 2016 unmodified lines | ||
| 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 | |