Commit 7ac8d0d2 authored by Yafang Shao's avatar Yafang Shao Committed by Alexei Starovoitov
Browse files

bpf: Support ->fill_link_info for kprobe_multi



With the addition of support for fill_link_info to the kprobe_multi link,
users will gain the ability to inspect it conveniently using the
`bpftool link show`. This enhancement provides valuable information to the
user, including the count of probed functions and their respective
addresses. It's important to note that if the kptr_restrict setting is not
permitted, the probed address will not be exposed, ensuring security.

Signed-off-by: default avatarYafang Shao <laoar.shao@gmail.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20230709025630.3735-2-laoar.shao@gmail.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 07018b57
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -6439,6 +6439,11 @@ struct bpf_link_info {
			__s32 priority;
			__u32 flags;
		} netfilter;
		struct {
			__aligned_u64 addrs;
			__u32 count; /* in/out: kprobe_multi function count */
			__u32 flags;
		} kprobe_multi;
	};
} __attribute__((aligned(8)));

+37 −0
Original line number Diff line number Diff line
@@ -2469,6 +2469,7 @@ struct bpf_kprobe_multi_link {
	u32 cnt;
	u32 mods_cnt;
	struct module **mods;
	u32 flags;
};

struct bpf_kprobe_multi_run_ctx {
@@ -2558,9 +2559,44 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
	kfree(kmulti_link);
}

static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
						struct bpf_link_info *info)
{
	u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
	struct bpf_kprobe_multi_link *kmulti_link;
	u32 ucount = info->kprobe_multi.count;
	int err = 0, i;

	if (!uaddrs ^ !ucount)
		return -EINVAL;

	kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
	info->kprobe_multi.count = kmulti_link->cnt;
	info->kprobe_multi.flags = kmulti_link->flags;

	if (!uaddrs)
		return 0;
	if (ucount < kmulti_link->cnt)
		err = -ENOSPC;
	else
		ucount = kmulti_link->cnt;

	if (kallsyms_show_value(current_cred())) {
		if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
			return -EFAULT;
	} else {
		for (i = 0; i < ucount; i++) {
			if (put_user(0, uaddrs + i))
				return -EFAULT;
		}
	}
	return err;
}

static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
	.release = bpf_kprobe_multi_link_release,
	.dealloc = bpf_kprobe_multi_link_dealloc,
	.fill_link_info = bpf_kprobe_multi_link_fill_link_info,
};

static void bpf_kprobe_multi_cookie_swap(void *a, void *b, int size, const void *priv)
@@ -2872,6 +2908,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
	link->addrs = addrs;
	link->cookies = cookies;
	link->cnt = cnt;
	link->flags = flags;

	if (cookies) {
		/*
+5 −0
Original line number Diff line number Diff line
@@ -6439,6 +6439,11 @@ struct bpf_link_info {
			__s32 priority;
			__u32 flags;
		} netfilter;
		struct {
			__aligned_u64 addrs;
			__u32 count; /* in/out: kprobe_multi function count */
			__u32 flags;
		} kprobe_multi;
	};
} __attribute__((aligned(8)));