Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60197cfb authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Daniel Borkmann
Browse files

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: default avatarMartin KaFai Lau <kafai@fb.com>
Acked-by: default avatarAlexei Starovoitov <ast@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent f56a653c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -10,9 +10,14 @@ struct btf;
struct btf_type;
union bpf_attr;

extern const struct file_operations btf_fops;

void btf_put(struct btf *btf);
int btf_new_fd(const union bpf_attr *attr);
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
 * (e.g. const), it will be resolved to find out the type with size.
 *
+16 −1
Original line number Diff line number Diff line
@@ -2002,7 +2002,7 @@ static int btf_release(struct inode *inode, struct file *filp)
	return 0;
}

static const struct file_operations btf_fops = {
const struct file_operations btf_fops = {
	.release	= btf_release,
};

@@ -2047,3 +2047,18 @@ struct btf *btf_get_by_fd(int fd)

	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;
}
+2 −0
Original line number Diff line number Diff line
@@ -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)
		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);
	else
		err = -EINVAL;