Skip to content

Commit e56fdbf

Browse files
olsajirianakryiko
authored andcommitted
bpf: Add link_info support for uprobe multi link
Adding support to get uprobe_link details through bpf_link_info interface. Adding new struct uprobe_multi to struct bpf_link_info to carry the uprobe_multi link details. The uprobe_multi.count is passed from user space to denote size of array fields (offsets/ref_ctr_offsets/cookies). The actual array size is stored back to uprobe_multi.count (allowing user to find out the actual array size) and array fields are populated up to the user passed size. All the non-array fields (path/count/flags/pid) are always set. Signed-off-by: Jiri Olsa <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 4930b7f commit e56fdbf

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

include/uapi/linux/bpf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6562,6 +6562,16 @@ struct bpf_link_info {
65626562
__u32 flags;
65636563
__u64 missed;
65646564
} kprobe_multi;
6565+
struct {
6566+
__aligned_u64 path;
6567+
__aligned_u64 offsets;
6568+
__aligned_u64 ref_ctr_offsets;
6569+
__aligned_u64 cookies;
6570+
__u32 path_size; /* in/out: real path size on success, including zero byte */
6571+
__u32 count; /* in/out: uprobe_multi offsets/ref_ctr_offsets/cookies count */
6572+
__u32 flags;
6573+
__u32 pid;
6574+
} uprobe_multi;
65656575
struct {
65666576
__u32 type; /* enum bpf_perf_event_type */
65676577
__u32 :32;

kernel/trace/bpf_trace.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,6 +3042,7 @@ struct bpf_uprobe_multi_link {
30423042
struct path path;
30433043
struct bpf_link link;
30443044
u32 cnt;
3045+
u32 flags;
30453046
struct bpf_uprobe *uprobes;
30463047
struct task_struct *task;
30473048
};
@@ -3083,9 +3084,79 @@ static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link)
30833084
kfree(umulti_link);
30843085
}
30853086

3087+
static int bpf_uprobe_multi_link_fill_link_info(const struct bpf_link *link,
3088+
struct bpf_link_info *info)
3089+
{
3090+
u64 __user *uref_ctr_offsets = u64_to_user_ptr(info->uprobe_multi.ref_ctr_offsets);
3091+
u64 __user *ucookies = u64_to_user_ptr(info->uprobe_multi.cookies);
3092+
u64 __user *uoffsets = u64_to_user_ptr(info->uprobe_multi.offsets);
3093+
u64 __user *upath = u64_to_user_ptr(info->uprobe_multi.path);
3094+
u32 upath_size = info->uprobe_multi.path_size;
3095+
struct bpf_uprobe_multi_link *umulti_link;
3096+
u32 ucount = info->uprobe_multi.count;
3097+
int err = 0, i;
3098+
long left;
3099+
3100+
if (!upath ^ !upath_size)
3101+
return -EINVAL;
3102+
3103+
if ((uoffsets || uref_ctr_offsets || ucookies) && !ucount)
3104+
return -EINVAL;
3105+
3106+
umulti_link = container_of(link, struct bpf_uprobe_multi_link, link);
3107+
info->uprobe_multi.count = umulti_link->cnt;
3108+
info->uprobe_multi.flags = umulti_link->flags;
3109+
info->uprobe_multi.pid = umulti_link->task ?
3110+
task_pid_nr_ns(umulti_link->task, task_active_pid_ns(current)) : 0;
3111+
3112+
if (upath) {
3113+
char *p, *buf;
3114+
3115+
upath_size = min_t(u32, upath_size, PATH_MAX);
3116+
3117+
buf = kmalloc(upath_size, GFP_KERNEL);
3118+
if (!buf)
3119+
return -ENOMEM;
3120+
p = d_path(&umulti_link->path, buf, upath_size);
3121+
if (IS_ERR(p)) {
3122+
kfree(buf);
3123+
return PTR_ERR(p);
3124+
}
3125+
upath_size = buf + upath_size - p;
3126+
left = copy_to_user(upath, p, upath_size);
3127+
kfree(buf);
3128+
if (left)
3129+
return -EFAULT;
3130+
info->uprobe_multi.path_size = upath_size;
3131+
}
3132+
3133+
if (!uoffsets && !ucookies && !uref_ctr_offsets)
3134+
return 0;
3135+
3136+
if (ucount < umulti_link->cnt)
3137+
err = -ENOSPC;
3138+
else
3139+
ucount = umulti_link->cnt;
3140+
3141+
for (i = 0; i < ucount; i++) {
3142+
if (uoffsets &&
3143+
put_user(umulti_link->uprobes[i].offset, uoffsets + i))
3144+
return -EFAULT;
3145+
if (uref_ctr_offsets &&
3146+
put_user(umulti_link->uprobes[i].ref_ctr_offset, uref_ctr_offsets + i))
3147+
return -EFAULT;
3148+
if (ucookies &&
3149+
put_user(umulti_link->uprobes[i].cookie, ucookies + i))
3150+
return -EFAULT;
3151+
}
3152+
3153+
return err;
3154+
}
3155+
30863156
static const struct bpf_link_ops bpf_uprobe_multi_link_lops = {
30873157
.release = bpf_uprobe_multi_link_release,
30883158
.dealloc = bpf_uprobe_multi_link_dealloc,
3159+
.fill_link_info = bpf_uprobe_multi_link_fill_link_info,
30893160
};
30903161

30913162
static int uprobe_prog_run(struct bpf_uprobe *uprobe,
@@ -3274,6 +3345,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
32743345
link->uprobes = uprobes;
32753346
link->path = path;
32763347
link->task = task;
3348+
link->flags = flags;
32773349

32783350
bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI,
32793351
&bpf_uprobe_multi_link_lops, prog);

tools/include/uapi/linux/bpf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6562,6 +6562,16 @@ struct bpf_link_info {
65626562
__u32 flags;
65636563
__u64 missed;
65646564
} kprobe_multi;
6565+
struct {
6566+
__aligned_u64 path;
6567+
__aligned_u64 offsets;
6568+
__aligned_u64 ref_ctr_offsets;
6569+
__aligned_u64 cookies;
6570+
__u32 path_size; /* in/out: real path size on success, including zero byte */
6571+
__u32 count; /* in/out: uprobe_multi offsets/ref_ctr_offsets/cookies count */
6572+
__u32 flags;
6573+
__u32 pid;
6574+
} uprobe_multi;
65656575
struct {
65666576
__u32 type; /* enum bpf_perf_event_type */
65676577
__u32 :32;

0 commit comments

Comments
 (0)