History

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.

Jiri Olsa committed 2 years ago

Commit e56fdbf1 parent 4930b7f3 files · +92 −0Browse files

Unified · Split

3 files
  1. include/uapi/linux/bpf.h +10 −0
  2. kernel/trace/bpf_trace.c +72 −0
  3. tools/include/uapi/linux/bpf.h +10 −0
include/uapi/linux/bpf.h+10−0
@@ -6562,6 +6562,16 @@ struct bpf_link_info { · 6561 unmodified lines
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+72−0
@@ -3042,6 +3042,7 @@ struct bpf_uprobe_multi_link { · 3041 unmodified lines
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) · 35 unmodified lines
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 · 182 unmodified lines
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+10−0
@@ -6562,6 +6562,16 @@ struct bpf_link_info { · 6561 unmodified lines
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;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t