Commit 19d18fdf authored by Tao Chen's avatar Tao Chen Committed by Alexei Starovoitov
Browse files

bpf: Add struct bpf_token_info



The 'commit 35f96de0 ("bpf: Introduce BPF token object")' added
BPF token as a new kind of BPF kernel object. And BPF_OBJ_GET_INFO_BY_FD
already used to get BPF object info, so we can also get token info with
this cmd.
One usage scenario, when program runs failed with token, because of
the permission failure, we can report what BPF token is allowing with
this API for debugging.

Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarTao Chen <chen.dylane@linux.dev>
Link: https://lore.kernel.org/r/20250716134654.1162635-1-chen.dylane@linux.dev


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 8080500c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -2354,6 +2354,7 @@ extern const struct super_operations bpf_super_ops;
extern const struct file_operations bpf_map_fops;
extern const struct file_operations bpf_prog_fops;
extern const struct file_operations bpf_iter_fops;
extern const struct file_operations bpf_token_fops;

#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
	extern const struct bpf_prog_ops _name ## _prog_ops; \
@@ -2551,6 +2552,9 @@ void bpf_token_inc(struct bpf_token *token);
void bpf_token_put(struct bpf_token *token);
int bpf_token_create(union bpf_attr *attr);
struct bpf_token *bpf_token_get_from_fd(u32 ufd);
int bpf_token_get_info_by_fd(struct bpf_token *token,
			     const union bpf_attr *attr,
			     union bpf_attr __user *uattr);

bool bpf_token_allow_cmd(const struct bpf_token *token, enum bpf_cmd cmd);
bool bpf_token_allow_map_type(const struct bpf_token *token, enum bpf_map_type type);
@@ -2949,6 +2953,13 @@ static inline struct bpf_token *bpf_token_get_from_fd(u32 ufd)
	return ERR_PTR(-EOPNOTSUPP);
}

static inline int bpf_token_get_info_by_fd(struct bpf_token *token,
					   const union bpf_attr *attr,
					   union bpf_attr __user *uattr)
{
	return -EOPNOTSUPP;
}

static inline void __dev_flush(struct list_head *flush_list)
{
}
+8 −0
Original line number Diff line number Diff line
@@ -450,6 +450,7 @@ union bpf_iter_link_info {
 *		* **struct bpf_map_info**
 *		* **struct bpf_btf_info**
 *		* **struct bpf_link_info**
 *		* **struct bpf_token_info**
 *
 *	Return
 *		Returns zero on success. On error, -1 is returned and *errno*
@@ -6803,6 +6804,13 @@ struct bpf_link_info {
	};
} __attribute__((aligned(8)));

struct bpf_token_info {
	__u64 allowed_cmds;
	__u64 allowed_maps;
	__u64 allowed_progs;
	__u64 allowed_attachs;
} __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 type).
+18 −0
Original line number Diff line number Diff line
@@ -5239,6 +5239,21 @@ static int bpf_link_get_info_by_fd(struct file *file,
}


static int token_get_info_by_fd(struct file *file,
				struct bpf_token *token,
				const union bpf_attr *attr,
				union bpf_attr __user *uattr)
{
	struct bpf_token_info __user *uinfo = u64_to_user_ptr(attr->info.info);
	u32 info_len = attr->info.info_len;
	int err;

	err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(*uinfo), info_len);
	if (err)
		return err;
	return bpf_token_get_info_by_fd(token, 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,
@@ -5262,6 +5277,9 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
	else if (fd_file(f)->f_op == &bpf_link_fops || fd_file(f)->f_op == &bpf_link_fops_poll)
		return bpf_link_get_info_by_fd(fd_file(f), fd_file(f)->private_data,
					      attr, uattr);
	else if (fd_file(f)->f_op == &bpf_token_fops)
		return token_get_info_by_fd(fd_file(f), fd_file(f)->private_data,
					    attr, uattr);
	return -EINVAL;
}

+24 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ static void bpf_token_show_fdinfo(struct seq_file *m, struct file *filp)

static const struct inode_operations bpf_token_iops = { };

static const struct file_operations bpf_token_fops = {
const struct file_operations bpf_token_fops = {
	.release	= bpf_token_release,
	.show_fdinfo	= bpf_token_show_fdinfo,
};
@@ -210,6 +210,29 @@ int bpf_token_create(union bpf_attr *attr)
	return err;
}

int bpf_token_get_info_by_fd(struct bpf_token *token,
			     const union bpf_attr *attr,
			     union bpf_attr __user *uattr)
{
	struct bpf_token_info __user *uinfo = u64_to_user_ptr(attr->info.info);
	struct bpf_token_info info;
	u32 info_len = attr->info.info_len;

	info_len = min_t(u32, info_len, sizeof(info));
	memset(&info, 0, sizeof(info));

	info.allowed_cmds = token->allowed_cmds;
	info.allowed_maps = token->allowed_maps;
	info.allowed_progs = token->allowed_progs;
	info.allowed_attachs = token->allowed_attachs;

	if (copy_to_user(uinfo, &info, info_len) ||
	    put_user(info_len, &uattr->info.info_len))
		return -EFAULT;

	return 0;
}

struct bpf_token *bpf_token_get_from_fd(u32 ufd)
{
	CLASS(fd, f)(ufd);
+8 −0
Original line number Diff line number Diff line
@@ -450,6 +450,7 @@ union bpf_iter_link_info {
 *		* **struct bpf_map_info**
 *		* **struct bpf_btf_info**
 *		* **struct bpf_link_info**
 *		* **struct bpf_token_info**
 *
 *	Return
 *		Returns zero on success. On error, -1 is returned and *errno*
@@ -6803,6 +6804,13 @@ struct bpf_link_info {
	};
} __attribute__((aligned(8)));

struct bpf_token_info {
	__u64 allowed_cmds;
	__u64 allowed_maps;
	__u64 allowed_progs;
	__u64 allowed_attachs;
} __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 type).