Given a fd representing a bpfdump target, user can retrieve the target_proto name which represents the bpf program prototype. Given a fd representing a file dumper, user can retrieve the bpf_prog id associated with that dumper. Signed-off-by: Yonghong Song <yhs@xxxxxx> --- include/linux/bpf.h | 1 + include/uapi/linux/bpf.h | 13 +++++++++ kernel/bpf/dump.c | 51 ++++++++++++++++++++++++++++++++++ kernel/bpf/syscall.c | 14 ++++++++++ tools/include/uapi/linux/bpf.h | 13 +++++++++ 5 files changed, 92 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index f7d4269d77b8..c9aec3b02dfa 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1120,6 +1120,7 @@ int bpf_dump_create(u32 prog_fd, const char __user *dumper_name); struct bpf_prog *bpf_dump_get_prog(struct seq_file *seq, u32 priv_data_size, u64 *seq_num); int bpf_dump_run_prog(struct bpf_prog *prog, void *ctx); +int bpf_dump_query(const union bpf_attr *attr, union bpf_attr __user *uattr); int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value); int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index a245f0df53c4..fc2157e319f1 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -113,6 +113,7 @@ enum bpf_cmd { BPF_MAP_DELETE_BATCH, BPF_LINK_CREATE, BPF_LINK_UPDATE, + BPF_DUMP_QUERY, }; enum bpf_map_type { @@ -594,6 +595,18 @@ union bpf_attr { __u32 old_prog_fd; } link_update; + struct { + __u32 query_fd; + __u32 flags; + union { + struct { + __aligned_u64 target_proto; + __u32 proto_buf_len; + }; + __u32 prog_id; + }; + } dump_query; + } __attribute__((aligned(8))); /* The description below is an attempt at providing documentation to eBPF diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c index 4e009b2612c2..f3041b362057 100644 --- a/kernel/bpf/dump.c +++ b/kernel/bpf/dump.c @@ -86,6 +86,57 @@ static void *get_extra_priv_dptr(void *old_ptr, u32 old_size) return old_ptr + roundup(old_size, 8); } +int bpf_dump_query(const union bpf_attr *attr, union bpf_attr __user *uattr) +{ + struct bpfdump_target_info *tinfo; + struct dumper_inode_info *i_info; + const char *target_proto; + void * __user proto_buf; + struct file *filp; + u32 proto_len; + struct fd qfd; + int err = 0; + + if (attr->dump_query.flags != 0) + return -EINVAL; + + qfd = fdget(attr->dump_query.query_fd); + filp = qfd.file; + if (!filp) + return -EBADF; + + if (filp->f_op != &bpf_dumper_ops && + filp->f_inode->i_op != &bpf_dir_iops) { + err = -EINVAL; + goto done; + } + + if (filp->f_op == &bpf_dumper_ops) { + i_info = filp->f_inode->i_private; + if (put_user(i_info->prog->aux->id, &uattr->dump_query.prog_id)) + err = -EFAULT; + + goto done; + } + + tinfo = filp->f_inode->i_private; + target_proto = tinfo->target_proto; + + proto_len = strlen(target_proto) + 1; + if (attr->dump_query.proto_buf_len < proto_len) { + err = -ENOSPC; + goto done; + } + + proto_buf = u64_to_user_ptr(attr->dump_query.target_proto); + if (copy_to_user(proto_buf, target_proto, proto_len)) + err = -EFAULT; + +done: + fdput(qfd); + return err; +} + #ifdef CONFIG_PROC_FS static void dumper_show_fdinfo(struct seq_file *m, struct file *filp) { diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 62a872a406ca..46b58f1f2d75 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3673,6 +3673,17 @@ static int link_update(union bpf_attr *attr) return ret; } +#define BPF_DUMP_QUERY_LAST_FIELD dump_query.proto_buf_len + +static int bpf_dump_do_query(const union bpf_attr *attr, + union bpf_attr __user *uattr) +{ + if (CHECK_ATTR(BPF_DUMP_QUERY)) + return -EINVAL; + + return bpf_dump_query(attr, uattr); +} + SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) { union bpf_attr attr; @@ -3790,6 +3801,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz case BPF_LINK_UPDATE: err = link_update(&attr); break; + case BPF_DUMP_QUERY: + err = bpf_dump_do_query(&attr, uattr); + break; default: err = -EINVAL; break; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index a245f0df53c4..fc2157e319f1 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -113,6 +113,7 @@ enum bpf_cmd { BPF_MAP_DELETE_BATCH, BPF_LINK_CREATE, BPF_LINK_UPDATE, + BPF_DUMP_QUERY, }; enum bpf_map_type { @@ -594,6 +595,18 @@ union bpf_attr { __u32 old_prog_fd; } link_update; + struct { + __u32 query_fd; + __u32 flags; + union { + struct { + __aligned_u64 target_proto; + __u32 proto_buf_len; + }; + __u32 prog_id; + }; + } dump_query; + } __attribute__((aligned(8))); /* The description below is an attempt at providing documentation to eBPF -- 2.24.1