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>
This commit is contained in:
parent
f56a653c1f
commit
60197cfb6e
|
@ -10,9 +10,14 @@ struct btf;
|
||||||
struct btf_type;
|
struct btf_type;
|
||||||
union bpf_attr;
|
union bpf_attr;
|
||||||
|
|
||||||
|
extern const struct file_operations btf_fops;
|
||||||
|
|
||||||
void btf_put(struct btf *btf);
|
void btf_put(struct btf *btf);
|
||||||
int btf_new_fd(const union bpf_attr *attr);
|
int btf_new_fd(const union bpf_attr *attr);
|
||||||
struct btf *btf_get_by_fd(int fd);
|
struct btf *btf_get_by_fd(int fd);
|
||||||
|
int btf_get_info_by_fd(const struct btf *btf,
|
||||||
|
const union bpf_attr *attr,
|
||||||
|
union bpf_attr __user *uattr);
|
||||||
/* Figure out the size of a type_id. If type_id is a modifier
|
/* Figure out the size of a type_id. If type_id is a modifier
|
||||||
* (e.g. const), it will be resolved to find out the type with size.
|
* (e.g. const), it will be resolved to find out the type with size.
|
||||||
*
|
*
|
||||||
|
|
|
@ -2002,7 +2002,7 @@ static int btf_release(struct inode *inode, struct file *filp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct file_operations btf_fops = {
|
const struct file_operations btf_fops = {
|
||||||
.release = btf_release,
|
.release = btf_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2047,3 +2047,18 @@ struct btf *btf_get_by_fd(int fd)
|
||||||
|
|
||||||
return btf;
|
return btf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (copy_to_user(udata, btf->data, copy_len) ||
|
||||||
|
put_user(btf->data_size, &uattr->info.info_len))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -2017,6 +2017,8 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
|
||||||
else if (f.file->f_op == &bpf_map_fops)
|
else if (f.file->f_op == &bpf_map_fops)
|
||||||
err = bpf_map_get_info_by_fd(f.file->private_data, attr,
|
err = bpf_map_get_info_by_fd(f.file->private_data, attr,
|
||||||
uattr);
|
uattr);
|
||||||
|
else if (f.file->f_op == &btf_fops)
|
||||||
|
err = btf_get_info_by_fd(f.file->private_data, attr, uattr);
|
||||||
else
|
else
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue