On Fri, Jun 30, 2023 at 1:34 AM Jiri Olsa <jolsa@xxxxxxxxxx> wrote: > > Adding new multi uprobe link that allows to attach bpf program > to multiple uprobes. > > Uprobes to attach are specified via new link_create uprobe_multi > union: > > struct { > __u32 flags; > __u32 cnt; > __aligned_u64 path; > __aligned_u64 offsets; > __aligned_u64 ref_ctr_offsets; > } uprobe_multi; > > Uprobes are defined for single binary specified in path and multiple > calling sites specified in offsets array with optional reference > counters specified in ref_ctr_offsets array. All specified arrays > have length of 'cnt'. > > The 'flags' supports single bit for now that marks the uprobe as > return probe. > > Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx> > --- > include/linux/trace_events.h | 6 + > include/uapi/linux/bpf.h | 14 ++ > kernel/bpf/syscall.c | 14 +- > kernel/trace/bpf_trace.c | 237 +++++++++++++++++++++++++++++++++ > tools/include/uapi/linux/bpf.h | 14 ++ > 5 files changed, 282 insertions(+), 3 deletions(-) > [...] > + flags = attr->link_create.uprobe_multi.flags; > + if (flags & ~BPF_F_UPROBE_MULTI_RETURN) > + return -EINVAL; > + > + /* > + * path, offsets and cnt are mandatory, > + * ref_ctr_offsets is optional > + */ > + upath = u64_to_user_ptr(attr->link_create.uprobe_multi.path); > + uoffsets = u64_to_user_ptr(attr->link_create.uprobe_multi.offsets); > + cnt = attr->link_create.uprobe_multi.cnt; > + > + if (!upath || !uoffsets || !cnt) > + return -EINVAL; see below for -EBADF, but we can also, additionally, return -EPROTO here, for example? > + > + uref_ctr_offsets = u64_to_user_ptr(attr->link_create.uprobe_multi.ref_ctr_offsets); > + > + name = strndup_user(upath, PATH_MAX); > + if (IS_ERR(name)) { > + err = PTR_ERR(name); > + return err; > + } > + > + err = kern_path(name, LOOKUP_FOLLOW, &path); > + kfree(name); > + if (err) > + return err; > + > + if (!d_is_reg(path.dentry)) { > + err = -EINVAL; as I mentioned in another patch, -EBADF here for feature detection (and it makes sense by itself, probably) > + goto error_path_put; > + } > + > + err = -ENOMEM; > + > + link = kzalloc(sizeof(*link), GFP_KERNEL); > + uprobes = kvcalloc(cnt, sizeof(*uprobes), GFP_KERNEL); > + > + if (!uprobes || !link) > + goto error_free; > + > + if (uref_ctr_offsets) { > + ref_ctr_offsets = kvcalloc(cnt, sizeof(*ref_ctr_offsets), GFP_KERNEL); > + if (!ref_ctr_offsets) > + goto error_free; > + } > + [...]