> On May 4, 2018, at 2:49 PM, Martin KaFai Lau <ka...@fb.com> wrote: > > During BPF_OBJ_GET_INFO_BY_FD on a btf_fd, the current bpf_attr's > info.info is directly filled with the BTF binary data. It is > not extensible. In this case, we want to add BTF ID. > > This patch adds "struct bpf_btf_info" which has the BTF ID as > one of its member. The BTF binary data itself is exposed through > the "btf" and "btf_size" members. > > Signed-off-by: Martin KaFai Lau <ka...@fb.com> > Acked-by: Alexei Starovoitov <a...@fb.com> > --- > include/uapi/linux/bpf.h | 6 ++++++ > kernel/bpf/btf.c | 26 +++++++++++++++++++++----- > kernel/bpf/syscall.c | 17 ++++++++++++++++- > 3 files changed, 43 insertions(+), 6 deletions(-) > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index 6106f23a9a8a..d615c777b573 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -2137,6 +2137,12 @@ struct bpf_map_info { > __u32 btf_value_id; > } __attribute__((aligned(8))); > > +struct bpf_btf_info { > + __aligned_u64 btf; > + __u32 btf_size; > + __u32 id; > +} __attribute__((aligned(8))); > + > /* User bpf_sock_addr struct to access socket fields and sockaddr struct > passed > * by user and intended to be used by socket (e.g. to bind to, depends on > * attach attach type). > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c > index 40950b6bf395..ded10ab47b8a 100644 > --- a/kernel/bpf/btf.c > +++ b/kernel/bpf/btf.c > @@ -2114,12 +2114,28 @@ int btf_get_info_by_fd(const struct btf *btf, > const union bpf_attr *attr, > union bpf_attr __user *uattr) > { > - void __user *udata = u64_to_user_ptr(attr->info.info); > - u32 copy_len = min_t(u32, btf->data_size, > - attr->info.info_len); > + struct bpf_btf_info __user *uinfo; > + struct bpf_btf_info info = {}; > + u32 info_copy, btf_copy; > + void __user *ubtf; > + u32 uinfo_len; > > - if (copy_to_user(udata, btf->data, copy_len) || > - put_user(btf->data_size, &uattr->info.info_len)) > + uinfo = u64_to_user_ptr(attr->info.info); > + uinfo_len = attr->info.info_len; > + > + info_copy = min_t(u32, uinfo_len, sizeof(info)); > + if (copy_from_user(&info, uinfo, info_copy)) > + return -EFAULT; > + > + info.id = btf->id; > + ubtf = u64_to_user_ptr(info.btf); > + btf_copy = min_t(u32, btf->data_size, info.btf_size); > + if (copy_to_user(ubtf, btf->data, btf_copy)) > + return -EFAULT; > + info.btf_size = btf->data_size; > + > + if (copy_to_user(uinfo, &info, info_copy) || > + put_user(info_copy, &uattr->info.info_len)) > return -EFAULT; > > return 0; > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c > index 8b0a45d65454..d2895e3e5cbf 100644 > --- a/kernel/bpf/syscall.c > +++ b/kernel/bpf/syscall.c > @@ -2019,6 +2019,21 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, > return 0; > } > > +static int bpf_btf_get_info_by_fd(struct btf *btf, > + const union bpf_attr *attr, > + union bpf_attr __user *uattr) > +{ > + struct bpf_btf_info __user *uinfo = u64_to_user_ptr(attr->info.info); > + u32 info_len = attr->info.info_len; > + int err; > + > + err = check_uarg_tail_zero(uinfo, sizeof(*uinfo), info_len); > + if (err) > + return err; > + > + return btf_get_info_by_fd(btf, attr, uattr); > +} > + > #define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info > > static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, > @@ -2042,7 +2057,7 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr > *attr, > err = bpf_map_get_info_by_fd(f.file->private_data, attr, > uattr); > else if (f.file->f_op == &btf_fops) > - err = btf_get_info_by_fd(f.file->private_data, attr, uattr); > + err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr); > else > err = -EINVAL; > > -- > 2.9.5 >
Acked-by: Song Liu <songliubrav...@fb.com>