From patchwork Tue Jun 20 08:35:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285332 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2210EAD48 for ; Tue, 20 Jun 2023 08:36:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 33F55C433C8; Tue, 20 Jun 2023 08:36:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250164; bh=8o3UKWpW7XacEVg3k9OJXjCKgmWSwdm9wEffUSUaOls=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HOJRCdskDkc5NE1vDw2FNOpyb/Zx3gtzwFUvbpBgizhBrvzo3OwKUdbgCIsQOwgR0 ZXwegQjURsyOaGzjC83oHgKwnlUM4WzIqFB6bL/KdoINQZhOzkcR7RZOLafL+wHrRm 9m+8FFHv5xGtNnT6yMp4BHdoLBK3p109QmxsuI7uQwh8gp5fD26LcKeZx/sPNgRnOJ mwCMMXHBQv3v7D2jb7B0/5fD5lD8uMCKcHmOLorCgCXewogMFsKkIJs+Cu1J0E0OE0 kXG/DIWTkngyCqrkyzQ0F/cxqklPe1/MyoMNMAy9mUsPCv9C04n5q36RGnuX5uKxno qtHtgb7W7JkNw== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 01/24] bpf: Add multi uprobe link Date: Tue, 20 Jun 2023 10:35:27 +0200 Message-ID: <20230620083550.690426-2-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net 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 --- include/linux/trace_events.h | 6 + include/uapi/linux/bpf.h | 14 ++ kernel/bpf/syscall.c | 12 +- kernel/trace/bpf_trace.c | 237 +++++++++++++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 14 ++ 5 files changed, 281 insertions(+), 2 deletions(-) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 0e373222a6df..b0db245fc0f5 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -749,6 +749,7 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id, u32 *fd_type, const char **buf, u64 *probe_offset, u64 *probe_addr); int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog); +int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog); #else static inline unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx) { @@ -795,6 +796,11 @@ bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) { return -EOPNOTSUPP; } +static inline int +bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) +{ + return -EOPNOTSUPP; +} #endif enum { diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index a7b5e91dd768..bfbc1246b220 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1035,6 +1035,7 @@ enum bpf_attach_type { BPF_TRACE_KPROBE_MULTI, BPF_LSM_CGROUP, BPF_STRUCT_OPS, + BPF_TRACE_UPROBE_MULTI, __MAX_BPF_ATTACH_TYPE }; @@ -1052,6 +1053,7 @@ enum bpf_link_type { BPF_LINK_TYPE_KPROBE_MULTI = 8, BPF_LINK_TYPE_STRUCT_OPS = 9, BPF_LINK_TYPE_NETFILTER = 10, + BPF_LINK_TYPE_UPROBE_MULTI = 11, MAX_BPF_LINK_TYPE, }; @@ -1169,6 +1171,11 @@ enum bpf_link_type { */ #define BPF_F_KPROBE_MULTI_RETURN (1U << 0) +/* link_create.uprobe_multi.flags used in LINK_CREATE command for + * BPF_TRACE_UPROBE_MULTI attach type to create return probe. + */ +#define BPF_F_UPROBE_MULTI_RETURN (1U << 0) + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have * the following extensions: * @@ -1578,6 +1585,13 @@ union bpf_attr { __s32 priority; __u32 flags; } netfilter; + struct { + __u32 flags; + __u32 cnt; + __aligned_u64 path; + __aligned_u64 offsets; + __aligned_u64 ref_ctr_offsets; + } uprobe_multi; }; } link_create; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index a75c54b6f8a3..a96e46cd407e 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3516,6 +3516,11 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog, return prog->enforce_expected_attach_type && prog->expected_attach_type != attach_type ? -EINVAL : 0; + case BPF_PROG_TYPE_KPROBE: + if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI && + attach_type != BPF_TRACE_KPROBE_MULTI) + return -EINVAL; + fallthrough; default: return 0; } @@ -4681,7 +4686,8 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) break; case BPF_PROG_TYPE_KPROBE: if (attr->link_create.attach_type != BPF_PERF_EVENT && - attr->link_create.attach_type != BPF_TRACE_KPROBE_MULTI) { + attr->link_create.attach_type != BPF_TRACE_KPROBE_MULTI && + attr->link_create.attach_type != BPF_TRACE_UPROBE_MULTI) { ret = -EINVAL; goto out; } @@ -4748,8 +4754,10 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr) case BPF_PROG_TYPE_KPROBE: if (attr->link_create.attach_type == BPF_PERF_EVENT) ret = bpf_perf_link_attach(attr, prog); - else + else if (attr->link_create.attach_type == BPF_TRACE_KPROBE_MULTI) ret = bpf_kprobe_multi_link_attach(attr, prog); + else if (attr->link_create.attach_type == BPF_TRACE_UPROBE_MULTI) + ret = bpf_uprobe_multi_link_attach(attr, prog); break; default: ret = -EINVAL; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 2bc41e6ac9fe..806ea9fd210d 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -2912,3 +2913,239 @@ static u64 bpf_kprobe_multi_entry_ip(struct bpf_run_ctx *ctx) return 0; } #endif + +#ifdef CONFIG_UPROBES +struct bpf_uprobe_multi_link; + +struct bpf_uprobe { + struct bpf_uprobe_multi_link *link; + loff_t offset; + struct uprobe_consumer consumer; +}; + +struct bpf_uprobe_multi_link { + struct path path; + struct bpf_link link; + u32 cnt; + struct bpf_uprobe *uprobes; +}; + +struct bpf_uprobe_multi_run_ctx { + struct bpf_run_ctx run_ctx; + unsigned long entry_ip; +}; + +static void bpf_uprobe_unregister(struct path *path, struct bpf_uprobe *uprobes, + u32 cnt) +{ + u32 i; + + for (i = 0; i < cnt; i++) { + uprobe_unregister(d_real_inode(path->dentry), uprobes[i].offset, + &uprobes[i].consumer); + } +} + +static void bpf_uprobe_multi_link_release(struct bpf_link *link) +{ + struct bpf_uprobe_multi_link *umulti_link; + + umulti_link = container_of(link, struct bpf_uprobe_multi_link, link); + bpf_uprobe_unregister(&umulti_link->path, umulti_link->uprobes, umulti_link->cnt); + path_put(&umulti_link->path); +} + +static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link) +{ + struct bpf_uprobe_multi_link *umulti_link; + + umulti_link = container_of(link, struct bpf_uprobe_multi_link, link); + kvfree(umulti_link->uprobes); + kfree(umulti_link); +} + +static const struct bpf_link_ops bpf_uprobe_multi_link_lops = { + .release = bpf_uprobe_multi_link_release, + .dealloc = bpf_uprobe_multi_link_dealloc, +}; + +static int uprobe_prog_run(struct bpf_uprobe *uprobe, + unsigned long entry_ip, + struct pt_regs *regs) +{ + struct bpf_uprobe_multi_link *link = uprobe->link; + struct bpf_uprobe_multi_run_ctx run_ctx = { + .entry_ip = entry_ip, + }; + struct bpf_prog *prog = link->link.prog; + struct bpf_run_ctx *old_run_ctx; + int err = 0; + + might_fault(); + + rcu_read_lock_trace(); + migrate_disable(); + + if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) + goto out; + + old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx); + + if (!prog->aux->sleepable) + rcu_read_lock(); + + err = bpf_prog_run(link->link.prog, regs); + + if (!prog->aux->sleepable) + rcu_read_unlock(); + + bpf_reset_run_ctx(old_run_ctx); + +out: + __this_cpu_dec(bpf_prog_active); + migrate_enable(); + rcu_read_unlock_trace(); + return err; +} + +static int +uprobe_multi_link_handler(struct uprobe_consumer *con, struct pt_regs *regs) +{ + struct bpf_uprobe *uprobe; + + uprobe = container_of(con, struct bpf_uprobe, consumer); + return uprobe_prog_run(uprobe, instruction_pointer(regs), regs); +} + +static int +uprobe_multi_link_ret_handler(struct uprobe_consumer *con, unsigned long func, struct pt_regs *regs) +{ + struct bpf_uprobe *uprobe; + + uprobe = container_of(con, struct bpf_uprobe, consumer); + return uprobe_prog_run(uprobe, func, regs); +} + +int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) +{ + unsigned long __user *uref_ctr_offsets, ref_ctr_offset = 0; + struct bpf_uprobe_multi_link *link = NULL; + unsigned long __user *uoffsets, offset; + unsigned long *ref_ctr_offsets = NULL; + struct bpf_link_primer link_primer; + struct bpf_uprobe *uprobes = NULL; + void __user *upath; + u32 flags, cnt, i; + struct path path; + char *name; + int err; + + /* no support for 32bit archs yet */ + if (sizeof(u64) != sizeof(void *)) + return -EOPNOTSUPP; + + if (prog->expected_attach_type != BPF_TRACE_UPROBE_MULTI) + return -EINVAL; + + 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; + + 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; + goto error_path_put; + } + + err = -ENOMEM; + + link = kzalloc(sizeof(*link), GFP_KERNEL); + uprobes = kvcalloc(cnt, sizeof(*uprobes), GFP_KERNEL); + ref_ctr_offsets = kvcalloc(cnt, sizeof(*ref_ctr_offsets), GFP_KERNEL); + + if (!uprobes || !ref_ctr_offsets || !link) + goto error_free; + + for (i = 0; i < cnt; i++) { + if (uref_ctr_offsets && __get_user(ref_ctr_offset, uref_ctr_offsets + i)) { + err = -EFAULT; + goto error_free; + } + if (__get_user(offset, uoffsets + i)) { + err = -EFAULT; + goto error_free; + } + + uprobes[i].offset = offset; + uprobes[i].link = link; + + if (flags & BPF_F_UPROBE_MULTI_RETURN) + uprobes[i].consumer.ret_handler = uprobe_multi_link_ret_handler; + else + uprobes[i].consumer.handler = uprobe_multi_link_handler; + + ref_ctr_offsets[i] = ref_ctr_offset; + } + + link->cnt = cnt; + link->uprobes = uprobes; + link->path = path; + + bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI, + &bpf_uprobe_multi_link_lops, prog); + + err = bpf_link_prime(&link->link, &link_primer); + if (err) + goto error_free; + + for (i = 0; i < cnt; i++) { + err = uprobe_register_refctr(d_real_inode(link->path.dentry), + uprobes[i].offset, ref_ctr_offsets[i], + &uprobes[i].consumer); + if (err) { + bpf_uprobe_unregister(&path, uprobes, i); + bpf_link_cleanup(&link_primer); + kvfree(ref_ctr_offsets); + return err; + } + } + + kvfree(ref_ctr_offsets); + return bpf_link_settle(&link_primer); + +error_free: + kvfree(ref_ctr_offsets); + kvfree(uprobes); + kfree(link); +error_path_put: + path_put(&path); + return err; +} +#else /* !CONFIG_UPROBES */ +int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) +{ + return -EOPNOTSUPP; +} +#endif /* CONFIG_UPROBES */ diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index a7b5e91dd768..bfbc1246b220 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1035,6 +1035,7 @@ enum bpf_attach_type { BPF_TRACE_KPROBE_MULTI, BPF_LSM_CGROUP, BPF_STRUCT_OPS, + BPF_TRACE_UPROBE_MULTI, __MAX_BPF_ATTACH_TYPE }; @@ -1052,6 +1053,7 @@ enum bpf_link_type { BPF_LINK_TYPE_KPROBE_MULTI = 8, BPF_LINK_TYPE_STRUCT_OPS = 9, BPF_LINK_TYPE_NETFILTER = 10, + BPF_LINK_TYPE_UPROBE_MULTI = 11, MAX_BPF_LINK_TYPE, }; @@ -1169,6 +1171,11 @@ enum bpf_link_type { */ #define BPF_F_KPROBE_MULTI_RETURN (1U << 0) +/* link_create.uprobe_multi.flags used in LINK_CREATE command for + * BPF_TRACE_UPROBE_MULTI attach type to create return probe. + */ +#define BPF_F_UPROBE_MULTI_RETURN (1U << 0) + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have * the following extensions: * @@ -1578,6 +1585,13 @@ union bpf_attr { __s32 priority; __u32 flags; } netfilter; + struct { + __u32 flags; + __u32 cnt; + __aligned_u64 path; + __aligned_u64 offsets; + __aligned_u64 ref_ctr_offsets; + } uprobe_multi; }; } link_create; From patchwork Tue Jun 20 08:35:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285333 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D650DAD48 for ; Tue, 20 Jun 2023 08:36:14 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2DD47C433C0; Tue, 20 Jun 2023 08:36:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250174; bh=sySKb4Ev6ELu3Ea540K+o88gaaVbxK9cLOEE5AzbNFY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oj8PnGEXj0E1rWnVwQJr6+e7qgfZvaUby27wQ5TqCZiq6s++zrRDZMxS5nhTQXyvc DLfleIt6LY+CI9XfpPFJ84Tc94Nwq2SMaBGiNy5WHgU3RKdgqiwyHo8cxkA3VUYpbz C2oMOhZU5nQv4zqOhtV/wuDZsQPj/xBR+B4iA0JztqXg95OG3k4oqJk044UOi0KIyg vc3NoV7wauOu2MXmAA/VpEnyDiWTmmF67voxE1PkyiQf2ikhI3Z5azxJn1ZSShwj1r V8PxNWJ1WsPnNdhZv0qF+ORznmQmG37M2h4jLWU59CfYXqoMXgLFjbP2HiM6N7a1ks j3Jc5Jk2VY81w== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 02/24] bpf: Add cookies support for uprobe_multi link Date: Tue, 20 Jun 2023 10:35:28 +0200 Message-ID: <20230620083550.690426-3-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding support to specify cookies array for uprobe_multi link. The cookies array share indexes and length with other uprobe_multi arrays (offsets/ref_ctr_offsets). The cookies[i] value defines cookie for i-the uprobe and will be returned by bpf_get_attach_cookie helper when called from ebpf program hooked to that specific uprobe. Acked-by: Andrii Nakryiko Signed-off-by: Jiri Olsa --- include/uapi/linux/bpf.h | 1 + kernel/bpf/syscall.c | 2 +- kernel/trace/bpf_trace.c | 48 +++++++++++++++++++++++++++++++--- tools/include/uapi/linux/bpf.h | 1 + 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index bfbc1246b220..12d4174fce8f 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1591,6 +1591,7 @@ union bpf_attr { __aligned_u64 path; __aligned_u64 offsets; __aligned_u64 ref_ctr_offsets; + __aligned_u64 cookies; } uprobe_multi; }; } link_create; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index a96e46cd407e..3ae444898c15 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -4651,7 +4651,7 @@ static int bpf_map_do_batch(const union bpf_attr *attr, return err; } -#define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies +#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.cookies static int link_create(union bpf_attr *attr, bpfptr_t uattr) { enum bpf_prog_type ptype; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 806ea9fd210d..f9cd7d283426 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -87,6 +87,8 @@ static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size, static u64 bpf_kprobe_multi_cookie(struct bpf_run_ctx *ctx); static u64 bpf_kprobe_multi_entry_ip(struct bpf_run_ctx *ctx); +static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx); + /** * trace_call_bpf - invoke BPF program * @call: tracepoint event @@ -1089,6 +1091,18 @@ static const struct bpf_func_proto bpf_get_attach_cookie_proto_kmulti = { .arg1_type = ARG_PTR_TO_CTX, }; +BPF_CALL_1(bpf_get_attach_cookie_uprobe_multi, struct pt_regs *, regs) +{ + return bpf_uprobe_multi_cookie(current->bpf_ctx); +} + +static const struct bpf_func_proto bpf_get_attach_cookie_proto_umulti = { + .func = bpf_get_attach_cookie_uprobe_multi, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +}; + BPF_CALL_1(bpf_get_attach_cookie_trace, void *, ctx) { struct bpf_trace_run_ctx *run_ctx; @@ -1535,9 +1549,11 @@ kprobe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) &bpf_get_func_ip_proto_kprobe_multi : &bpf_get_func_ip_proto_kprobe; case BPF_FUNC_get_attach_cookie: - return prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI ? - &bpf_get_attach_cookie_proto_kmulti : - &bpf_get_attach_cookie_proto_trace; + if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI) + return &bpf_get_attach_cookie_proto_kmulti; + if (prog->expected_attach_type == BPF_TRACE_UPROBE_MULTI) + return &bpf_get_attach_cookie_proto_umulti; + return &bpf_get_attach_cookie_proto_trace; default: return bpf_tracing_func_proto(func_id, prog); } @@ -2920,6 +2936,7 @@ struct bpf_uprobe_multi_link; struct bpf_uprobe { struct bpf_uprobe_multi_link *link; loff_t offset; + u64 cookie; struct uprobe_consumer consumer; }; @@ -2933,6 +2950,7 @@ struct bpf_uprobe_multi_link { struct bpf_uprobe_multi_run_ctx { struct bpf_run_ctx run_ctx; unsigned long entry_ip; + struct bpf_uprobe *uprobe; }; static void bpf_uprobe_unregister(struct path *path, struct bpf_uprobe *uprobes, @@ -2976,6 +2994,7 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, struct bpf_uprobe_multi_link *link = uprobe->link; struct bpf_uprobe_multi_run_ctx run_ctx = { .entry_ip = entry_ip, + .uprobe = uprobe, }; struct bpf_prog *prog = link->link.prog; struct bpf_run_ctx *old_run_ctx; @@ -3026,6 +3045,16 @@ uprobe_multi_link_ret_handler(struct uprobe_consumer *con, unsigned long func, s return uprobe_prog_run(uprobe, func, regs); } +static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) +{ + struct bpf_uprobe_multi_run_ctx *run_ctx; + + if (!ctx) + return 0; + run_ctx = container_of(current->bpf_ctx, struct bpf_uprobe_multi_run_ctx, run_ctx); + return run_ctx->uprobe->cookie; +} + int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) { unsigned long __user *uref_ctr_offsets, ref_ctr_offset = 0; @@ -3034,6 +3063,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr unsigned long *ref_ctr_offsets = NULL; struct bpf_link_primer link_primer; struct bpf_uprobe *uprobes = NULL; + u64 __user *ucookies, cookie = 0; void __user *upath; u32 flags, cnt, i; struct path path; @@ -3053,7 +3083,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr /* * path, offsets and cnt are mandatory, - * ref_ctr_offsets is optional + * ref_ctr_offsets and cookies are optional */ upath = u64_to_user_ptr(attr->link_create.uprobe_multi.path); uoffsets = u64_to_user_ptr(attr->link_create.uprobe_multi.offsets); @@ -3062,6 +3092,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr return -EINVAL; uref_ctr_offsets = u64_to_user_ptr(attr->link_create.uprobe_multi.ref_ctr_offsets); + ucookies = u64_to_user_ptr(attr->link_create.uprobe_multi.cookies); name = strndup_user(upath, PATH_MAX); if (IS_ERR(name)) { @@ -3089,6 +3120,10 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr goto error_free; for (i = 0; i < cnt; i++) { + if (ucookies && __get_user(cookie, ucookies + i)) { + err = -EFAULT; + goto error_free; + } if (uref_ctr_offsets && __get_user(ref_ctr_offset, uref_ctr_offsets + i)) { err = -EFAULT; goto error_free; @@ -3099,6 +3134,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr } uprobes[i].offset = offset; + uprobes[i].cookie = cookie; uprobes[i].link = link; if (flags & BPF_F_UPROBE_MULTI_RETURN) @@ -3148,4 +3184,8 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr { return -EOPNOTSUPP; } +static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) +{ + return 0; +} #endif /* CONFIG_UPROBES */ diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index bfbc1246b220..12d4174fce8f 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1591,6 +1591,7 @@ union bpf_attr { __aligned_u64 path; __aligned_u64 offsets; __aligned_u64 ref_ctr_offsets; + __aligned_u64 cookies; } uprobe_multi; }; } link_create; From patchwork Tue Jun 20 08:35:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285334 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13DED4400 for ; Tue, 20 Jun 2023 08:36:25 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25E10C433C0; Tue, 20 Jun 2023 08:36:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250184; bh=XPt4D40Gg/8SfYdRvptF6aJm7+mRLT92BufL7JpLUzI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bymWWX3fOq2hzRRS9rQF0PxmIAYf9YeJkk/EfU/CiCRdkVV7pQKf7XUfhkmM7bpdE o+4xY+zSV02l37u+nYESF8JaVk5eEynfkTDA/KuRjlNub7gf94f3ruTe1WgO4G5/p7 bo0DUy/+ic03MO20qq06u5TFYlIIcV3f5JuH1y4BphJtOsdE4/zJdgK/ezgP+te3KF eMR2t5SQaHlcNQw5tL6fzKoEtDcsMbm8DbsqG+c753JJ4LOXdq9468SJTh+eGjiwIm 9u7u0b+PW4YKe4SoCWmUKL+MiCGiZUmH9lvGP60gBr2j7XSw0tdC7Ua0qjOV8+rbZT L7S1Fuhfn/zZA== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: Oleg Nesterov , bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 03/24] bpf: Add pid filter support for uprobe_multi link Date: Tue, 20 Jun 2023 10:35:29 +0200 Message-ID: <20230620083550.690426-4-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding support to specify pid for uprobe_multi link and the uprobes are created only for task with given pid value. Using the consumer.filter filter callback for that, so the task gets filtered during the uprobe installation. We still need to check the task during runtime in the uprobe handler, because the handler could get executed if there's another system wide consumer on the same uprobe (thanks Oleg for the insight). Cc: Oleg Nesterov Signed-off-by: Jiri Olsa Reviewed-by: Oleg Nesterov --- include/uapi/linux/bpf.h | 1 + kernel/bpf/syscall.c | 2 +- kernel/trace/bpf_trace.c | 33 +++++++++++++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 1 + 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 12d4174fce8f..117acca838f1 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1592,6 +1592,7 @@ union bpf_attr { __aligned_u64 offsets; __aligned_u64 ref_ctr_offsets; __aligned_u64 cookies; + __u32 pid; } uprobe_multi; }; } link_create; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 3ae444898c15..b871f0eb8a05 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -4651,7 +4651,7 @@ static int bpf_map_do_batch(const union bpf_attr *attr, return err; } -#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.cookies +#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.pid static int link_create(union bpf_attr *attr, bpfptr_t uattr) { enum bpf_prog_type ptype; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index f9cd7d283426..5c5b543d7d03 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2945,6 +2945,7 @@ struct bpf_uprobe_multi_link { struct bpf_link link; u32 cnt; struct bpf_uprobe *uprobes; + struct task_struct *task; }; struct bpf_uprobe_multi_run_ctx { @@ -2971,6 +2972,8 @@ static void bpf_uprobe_multi_link_release(struct bpf_link *link) umulti_link = container_of(link, struct bpf_uprobe_multi_link, link); bpf_uprobe_unregister(&umulti_link->path, umulti_link->uprobes, umulti_link->cnt); path_put(&umulti_link->path); + if (umulti_link->task) + put_task_struct(umulti_link->task); } static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link) @@ -3000,6 +3003,9 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, struct bpf_run_ctx *old_run_ctx; int err = 0; + if (link->task && current != link->task) + return 0; + might_fault(); rcu_read_lock_trace(); @@ -3027,6 +3033,16 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe, return err; } +static bool +uprobe_multi_link_filter(struct uprobe_consumer *con, enum uprobe_filter_ctx ctx, + struct mm_struct *mm) +{ + struct bpf_uprobe *uprobe; + + uprobe = container_of(con, struct bpf_uprobe, consumer); + return uprobe->link->task->mm == mm; +} + static int uprobe_multi_link_handler(struct uprobe_consumer *con, struct pt_regs *regs) { @@ -3064,10 +3080,12 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr struct bpf_link_primer link_primer; struct bpf_uprobe *uprobes = NULL; u64 __user *ucookies, cookie = 0; + struct task_struct *task = NULL; void __user *upath; u32 flags, cnt, i; struct path path; char *name; + pid_t pid; int err; /* no support for 32bit archs yet */ @@ -3110,6 +3128,15 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr goto error_path_put; } + pid = attr->link_create.uprobe_multi.pid; + if (pid) { + rcu_read_lock(); + task = get_pid_task(find_vpid(pid), PIDTYPE_PID); + rcu_read_unlock(); + if (!task) + goto error_path_put; + } + err = -ENOMEM; link = kzalloc(sizeof(*link), GFP_KERNEL); @@ -3143,11 +3170,15 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr uprobes[i].consumer.handler = uprobe_multi_link_handler; ref_ctr_offsets[i] = ref_ctr_offset; + + if (pid) + uprobes[i].consumer.filter = uprobe_multi_link_filter; } link->cnt = cnt; link->uprobes = uprobes; link->path = path; + link->task = task; bpf_link_init(&link->link, BPF_LINK_TYPE_UPROBE_MULTI, &bpf_uprobe_multi_link_lops, prog); @@ -3175,6 +3206,8 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr kvfree(ref_ctr_offsets); kvfree(uprobes); kfree(link); + if (task) + put_task_struct(task); error_path_put: path_put(&path); return err; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 12d4174fce8f..117acca838f1 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1592,6 +1592,7 @@ union bpf_attr { __aligned_u64 offsets; __aligned_u64 ref_ctr_offsets; __aligned_u64 cookies; + __u32 pid; } uprobe_multi; }; } link_create; From patchwork Tue Jun 20 08:35:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285335 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A95D1AD56 for ; Tue, 20 Jun 2023 08:36:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED4D5C433C0; Tue, 20 Jun 2023 08:36:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250194; bh=ZO8e7ZUuCYow+86JgR3lAD3XBHgd7dwTCkhXMwpkdsU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vPs+BE0+DzQpAZZv+vgAs2X8p6zccoH+rGAvG1gt7hVnK8zynSUy9gAMHiJviODYC dutVAXQjBX3WSGvih5IJKicSBHm1Ajvq8iRhMATt2gtrA/wrK8/G1NDVilkH+BSmNY NCur1aZ2rqc+rqjrQbopzcPN0H51tfhygTJn38xWnddQJdSjSIzb8Z9HjHkqZLLgxy lPstbAMK1IlD+3Lazy6MVR5ffiT525xKKwewsKWFSrhh3zmQ1TsVeVg+LpQb+8WmHD cE+tEtTwAMgmOgHtJKD5rJnIsEE9BAbq7Pugkz43RVHV0HheX69plWEvgNreY1kVL7 MzPu5Ghj/NzMA== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 04/24] bpf: Add bpf_get_func_ip helper support for uprobe link Date: Tue, 20 Jun 2023 10:35:30 +0200 Message-ID: <20230620083550.690426-5-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding support for bpf_get_func_ip helper being called from ebpf program attached by uprobe_multi link. It returns the ip of the uprobe. Acked-by: Andrii Nakryiko Signed-off-by: Jiri Olsa --- kernel/trace/bpf_trace.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 5c5b543d7d03..dfba0bb479a2 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -88,6 +88,7 @@ static u64 bpf_kprobe_multi_cookie(struct bpf_run_ctx *ctx); static u64 bpf_kprobe_multi_entry_ip(struct bpf_run_ctx *ctx); static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx); +static u64 bpf_uprobe_multi_entry_ip(struct bpf_run_ctx *ctx); /** * trace_call_bpf - invoke BPF program @@ -1091,6 +1092,18 @@ static const struct bpf_func_proto bpf_get_attach_cookie_proto_kmulti = { .arg1_type = ARG_PTR_TO_CTX, }; +BPF_CALL_1(bpf_get_func_ip_uprobe_multi, struct pt_regs *, regs) +{ + return bpf_uprobe_multi_entry_ip(current->bpf_ctx); +} + +static const struct bpf_func_proto bpf_get_func_ip_proto_uprobe_multi = { + .func = bpf_get_func_ip_uprobe_multi, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, +}; + BPF_CALL_1(bpf_get_attach_cookie_uprobe_multi, struct pt_regs *, regs) { return bpf_uprobe_multi_cookie(current->bpf_ctx); @@ -1545,9 +1558,11 @@ kprobe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_override_return_proto; #endif case BPF_FUNC_get_func_ip: - return prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI ? - &bpf_get_func_ip_proto_kprobe_multi : - &bpf_get_func_ip_proto_kprobe; + if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI) + return &bpf_get_func_ip_proto_kprobe_multi; + if (prog->expected_attach_type == BPF_TRACE_UPROBE_MULTI) + return &bpf_get_func_ip_proto_uprobe_multi; + return &bpf_get_func_ip_proto_kprobe; case BPF_FUNC_get_attach_cookie: if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI) return &bpf_get_attach_cookie_proto_kmulti; @@ -3061,6 +3076,14 @@ uprobe_multi_link_ret_handler(struct uprobe_consumer *con, unsigned long func, s return uprobe_prog_run(uprobe, func, regs); } +static u64 bpf_uprobe_multi_entry_ip(struct bpf_run_ctx *ctx) +{ + struct bpf_uprobe_multi_run_ctx *run_ctx; + + run_ctx = container_of(current->bpf_ctx, struct bpf_uprobe_multi_run_ctx, run_ctx); + return run_ctx->entry_ip; +} + static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) { struct bpf_uprobe_multi_run_ctx *run_ctx; @@ -3221,4 +3244,8 @@ static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) { return 0; } +static u64 bpf_uprobe_multi_entry_ip(struct bpf_run_ctx *ctx) +{ + return 0; +} #endif /* CONFIG_UPROBES */ From patchwork Tue Jun 20 08:35:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285336 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B9A6AD56 for ; Tue, 20 Jun 2023 08:36:44 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E1877C433C0; Tue, 20 Jun 2023 08:36:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250204; bh=h//siKybRBzMTZgE+8dt4NYeHULN+9EGiD1YACvFZDU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MPAK2AzzmGcS73XYJqKszO4y8q13fFVoahcpij8v0zLRmhdEFzxTWzsJzo1H7cxVC cPL162TRhJCJr8tmsjokx2wQ80wjoS9bS4O6AS7JgSOiZYTTklxS4p3r3i4vKGSmNW J1ba1Y5lrGN1TdWeJWrtpPKkaiJMTGw/21ZjTrpPa4/N8B2+6O00h8pwwkmVEjrQbm 4gcZXZn5bxXjq4fP2MA1X9GREIPViLmSL7fP6Va6Z024VB5nT99NRsJPkVKR2iPEAS 3aas/3Avkb0Kqzz0ZhF2tqiI8FP942CelPl5kDvNaaW2ku9KiMCRJx4wl07hpimOIz tNvlA0tlAG5VQ== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 05/24] libbpf: Add uprobe_multi attach type and link names Date: Tue, 20 Jun 2023 10:35:31 +0200 Message-ID: <20230620083550.690426-6-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding new uprobe_multi attach type and link names, so the functions can resolve the new values. Acked-by: Andrii Nakryiko Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 47632606b06d..af52188daa80 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -117,6 +117,7 @@ static const char * const attach_type_name[] = { [BPF_PERF_EVENT] = "perf_event", [BPF_TRACE_KPROBE_MULTI] = "trace_kprobe_multi", [BPF_STRUCT_OPS] = "struct_ops", + [BPF_TRACE_UPROBE_MULTI] = "trace_uprobe_multi", }; static const char * const link_type_name[] = { @@ -131,6 +132,7 @@ static const char * const link_type_name[] = { [BPF_LINK_TYPE_KPROBE_MULTI] = "kprobe_multi", [BPF_LINK_TYPE_STRUCT_OPS] = "struct_ops", [BPF_LINK_TYPE_NETFILTER] = "netfilter", + [BPF_LINK_TYPE_UPROBE_MULTI] = "uprobe_multi", }; static const char * const map_type_name[] = { From patchwork Tue Jun 20 08:35:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285337 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8CDC6A92D for ; Tue, 20 Jun 2023 08:36:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 88662C433C0; Tue, 20 Jun 2023 08:36:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250214; bh=06oeXnl0kz7cJxQhrJIMD+OV+KR3HkftQMs7oAY3JQQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bpY2RhsXiviTjXoV6dFpk3/hVJF0SCXEcowYAkS6IJgjxLiagI6zyOwmmmxs/pV9P EShy9+Z9TkUpkEcRN7EBP0fjGWfmQbHOQYmAr0A3VmMGeHYNaB1tCz/vdYjMVdBy5U tH6bLsWMumfMTJg5he3MrS6Ry8DqMv5/jV3jKqElbQ7D7+RtI3gxKPxelqlCBvuRtO iSDpyREIv3lIHc1BHXxFqOgQw1Mvv+tvsnXAgDJPJ5/abCZES5giRNLIeYFA/zZgYE qMufnzZk/3D0q9emZMbWMs4oTlUd5Z8XfiF9OZQkq7o01ZjtbtUJxIZO7nRoWvrwSW IxyXlpVHSlq/g== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 06/24] libbpf: Add elf symbol iterator Date: Tue, 20 Jun 2023 10:35:32 +0200 Message-ID: <20230620083550.690426-7-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding elf symbol iterator object (and some functions) that follow open-coded iterator pattern and some functions to ease up iterating elf object symbols. The idea is to iterate single symbol section with: struct elf_symbol_iter iter; struct elf_symbol *sym; if (elf_symbol_iter_new(&iter, elf, binary_path, SHT_DYNSYM)) goto error; while ((sym = elf_symbol_iter_next(&iter))) { ... } I considered opening the elf inside the iterator and iterate all symbol sections, but then it gets more complicated wrt user checks for when the next section is processed. Plus side is the we don't need 'exit' function, because caller/user is in charge of that. The returned iterated symbol object from elf_symbol_iter_next function is placed inside the struct elf_symbol_iter, so no extra allocation or argument is needed. Suggested-by: Andrii Nakryiko Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 179 ++++++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 65 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index af52188daa80..cdac368c7ce1 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -10824,6 +10824,109 @@ static Elf_Scn *elf_find_next_scn_by_type(Elf *elf, int sh_type, Elf_Scn *scn) return NULL; } +struct elf_symbol { + const char *name; + unsigned long offset; + int bind; +}; + +struct elf_symbol_iter { + Elf *elf; + Elf_Data *symbols; + size_t nr_syms; + size_t strtabidx; + size_t idx; + struct elf_symbol sym; +}; + +static int elf_symbol_iter_new(struct elf_symbol_iter *iter, + Elf *elf, const char *binary_path, + int sh_type) +{ + Elf_Scn *scn = NULL; + GElf_Ehdr ehdr; + GElf_Shdr sh; + + memset(iter, 0, sizeof(*iter)); + + if (!gelf_getehdr(elf, &ehdr)) { + pr_warn("elf: failed to get ehdr from %s: %s\n", binary_path, elf_errmsg(-1)); + return -LIBBPF_ERRNO__FORMAT; + } + + scn = elf_find_next_scn_by_type(elf, sh_type, NULL); + if (!scn) { + pr_debug("elf: failed to find symbol table ELF sections in '%s'\n", + binary_path); + return -EINVAL; + } + + if (!gelf_getshdr(scn, &sh)) + return -EINVAL; + + iter->strtabidx = sh.sh_link; + iter->symbols = elf_getdata(scn, 0); + if (!iter->symbols) { + pr_warn("elf: failed to get symbols for symtab section in '%s': %s\n", + binary_path, elf_errmsg(-1)); + return -LIBBPF_ERRNO__FORMAT; + } + iter->nr_syms = iter->symbols->d_size / sh.sh_entsize; + iter->elf = elf; + return 0; +} + +static struct elf_symbol *elf_symbol_iter_next(struct elf_symbol_iter *iter) +{ + struct elf_symbol *ret = &iter->sym; + unsigned long offset = 0; + const char *name = NULL; + GElf_Shdr sym_sh; + Elf_Scn *sym_scn; + GElf_Sym sym; + size_t idx; + + for (idx = iter->idx; idx < iter->nr_syms; idx++) { + if (!gelf_getsym(iter->symbols, idx, &sym)) + continue; + if (GELF_ST_TYPE(sym.st_info) != STT_FUNC) + continue; + name = elf_strptr(iter->elf, iter->strtabidx, sym.st_name); + if (!name) + continue; + + /* Transform symbol's virtual address (absolute for + * binaries and relative for shared libs) into file + * offset, which is what kernel is expecting for + * uprobe/uretprobe attachment. + * See Documentation/trace/uprobetracer.rst for more + * details. + * This is done by looking up symbol's containing + * section's header and using iter's virtual address + * (sh_addr) and corresponding file offset (sh_offset) + * to transform sym.st_value (virtual address) into + * desired final file offset. + */ + sym_scn = elf_getscn(iter->elf, sym.st_shndx); + if (!sym_scn) + continue; + if (!gelf_getshdr(sym_scn, &sym_sh)) + continue; + + offset = sym.st_value - sym_sh.sh_addr + sym_sh.sh_offset; + break; + } + + /* we reached the last symbol */ + if (idx == iter->nr_syms) + return NULL; + iter->idx = idx + 1; + ret->name = name; + ret->bind = GELF_ST_BIND(sym.st_info); + ret->offset = offset; + return ret; +} + /* Find offset of function name in the provided ELF object. "binary_path" is * the path to the ELF binary represented by "elf", and only used for error * reporting matters. "name" matches symbol name or name@@LIB for library @@ -10855,94 +10958,40 @@ static long elf_find_func_offset(Elf *elf, const char *binary_path, const char * * reported as a warning/error. */ for (i = 0; i < ARRAY_SIZE(sh_types); i++) { - size_t nr_syms, strtabidx, idx; - Elf_Data *symbols = NULL; - Elf_Scn *scn = NULL; + struct elf_symbol_iter iter; + struct elf_symbol *sym; int last_bind = -1; - const char *sname; - GElf_Shdr sh; - scn = elf_find_next_scn_by_type(elf, sh_types[i], NULL); - if (!scn) { - pr_debug("elf: failed to find symbol table ELF sections in '%s'\n", - binary_path); + if (elf_symbol_iter_new(&iter, elf, binary_path, sh_types[i])) continue; - } - if (!gelf_getshdr(scn, &sh)) - continue; - strtabidx = sh.sh_link; - symbols = elf_getdata(scn, 0); - if (!symbols) { - pr_warn("elf: failed to get symbols for symtab section in '%s': %s\n", - binary_path, elf_errmsg(-1)); - ret = -LIBBPF_ERRNO__FORMAT; - goto out; - } - nr_syms = symbols->d_size / sh.sh_entsize; - - for (idx = 0; idx < nr_syms; idx++) { - int curr_bind; - GElf_Sym sym; - Elf_Scn *sym_scn; - GElf_Shdr sym_sh; - - if (!gelf_getsym(symbols, idx, &sym)) - continue; - - if (GELF_ST_TYPE(sym.st_info) != STT_FUNC) - continue; - - sname = elf_strptr(elf, strtabidx, sym.st_name); - if (!sname) - continue; - - curr_bind = GELF_ST_BIND(sym.st_info); + while ((sym = elf_symbol_iter_next(&iter))) { /* User can specify func, func@@LIB or func@@LIB_VERSION. */ - if (strncmp(sname, name, name_len) != 0) + if (strncmp(sym->name, name, name_len) != 0) continue; /* ...but we don't want a search for "foo" to match 'foo2" also, so any * additional characters in sname should be of the form "@@LIB". */ - if (!is_name_qualified && sname[name_len] != '\0' && sname[name_len] != '@') + if (!is_name_qualified && sym->name[name_len] != '\0' && sym->name[name_len] != '@') continue; if (ret >= 0) { /* handle multiple matches */ - if (last_bind != STB_WEAK && curr_bind != STB_WEAK) { + if (last_bind != STB_WEAK && sym->bind != STB_WEAK) { /* Only accept one non-weak bind. */ pr_warn("elf: ambiguous match for '%s', '%s' in '%s'\n", - sname, name, binary_path); + sym->name, name, binary_path); ret = -LIBBPF_ERRNO__FORMAT; goto out; - } else if (curr_bind == STB_WEAK) { + } else if (sym->bind == STB_WEAK) { /* already have a non-weak bind, and * this is a weak bind, so ignore. */ continue; } } - - /* Transform symbol's virtual address (absolute for - * binaries and relative for shared libs) into file - * offset, which is what kernel is expecting for - * uprobe/uretprobe attachment. - * See Documentation/trace/uprobetracer.rst for more - * details. - * This is done by looking up symbol's containing - * section's header and using it's virtual address - * (sh_addr) and corresponding file offset (sh_offset) - * to transform sym.st_value (virtual address) into - * desired final file offset. - */ - sym_scn = elf_getscn(elf, sym.st_shndx); - if (!sym_scn) - continue; - if (!gelf_getshdr(sym_scn, &sym_sh)) - continue; - - ret = sym.st_value - sym_sh.sh_addr + sym_sh.sh_offset; - last_bind = curr_bind; + last_bind = sym->bind; + ret = sym->offset; } if (ret > 0) break; From patchwork Tue Jun 20 08:35:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285338 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C3D710E5 for ; Tue, 20 Jun 2023 08:37:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 299E5C433C0; Tue, 20 Jun 2023 08:37:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250223; bh=8ua+Vb1NBWxPO1vcvFFz5SuVB5fzhHEUcxqQCECigXA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PDrrX2UnlZs0vKAan8vQ/CR+sAKVUsuKoWwUQk27m8umQeEITC3DYaGUs50vSe3z4 dFWxSCuP6UXC+Tqm1g1b72i8jKzddcoeo9oHniNEmR12ADcb/m1nCHGzmfVRBOwPSP z41XsZqs9HcJuprHZ+xri57q4RUHGQD8n7kKzBm49t/qdKUzXhU/iqiwcTzha57JI1 vr2qWKunkjGr7Bjo/Tw19ZaR+JbxYevpgBnmpvpmEYG/ZWZUwwMImuksl2Zytfa1bR 0KuoLz1Xvuays6XnaGhZaa6esdh1a59Qeo9WiaVug98ufIlDkog1zjBkvK/zINa88G QGRWT7G8B9pBA== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 07/24] libbpf: Add open_elf/close_elf functions Date: Tue, 20 Jun 2023 10:35:33 +0200 Message-ID: <20230620083550.690426-8-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding open_elf/close_elf functions and using it in elf_find_func_offset_from_file function. It will be used in following changes to save some code. Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 62 ++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index cdac368c7ce1..30d9e3b69114 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -10927,6 +10927,45 @@ static struct elf_symbol *elf_symbol_iter_next(struct elf_symbol_iter *iter) return ret; } +struct elf_fd { + Elf *elf; + int fd; +}; + +static int open_elf(const char *binary_path, struct elf_fd *elf_fd) +{ + char errmsg[STRERR_BUFSIZE]; + int fd, ret; + Elf *elf; + + if (elf_version(EV_CURRENT) == EV_NONE) { + pr_warn("failed to init libelf for %s\n", binary_path); + return -LIBBPF_ERRNO__LIBELF; + } + fd = open(binary_path, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + ret = -errno; + pr_warn("failed to open %s: %s\n", binary_path, + libbpf_strerror_r(ret, errmsg, sizeof(errmsg))); + return ret; + } + elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); + if (!elf) { + pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1)); + close(fd); + return -LIBBPF_ERRNO__FORMAT; + } + elf_fd->fd = fd; + elf_fd->elf = elf; + return 0; +} + +static void close_elf(struct elf_fd *elf_fd) +{ + elf_end(elf_fd->elf); + close(elf_fd->fd); +} + /* Find offset of function name in the provided ELF object. "binary_path" is * the path to the ELF binary represented by "elf", and only used for error * reporting matters. "name" matches symbol name or name@@LIB for library @@ -11019,28 +11058,15 @@ static long elf_find_func_offset(Elf *elf, const char *binary_path, const char * */ static long elf_find_func_offset_from_file(const char *binary_path, const char *name) { - char errmsg[STRERR_BUFSIZE]; + struct elf_fd elf_fd = {}; long ret = -ENOENT; - Elf *elf; - int fd; - fd = open(binary_path, O_RDONLY | O_CLOEXEC); - if (fd < 0) { - ret = -errno; - pr_warn("failed to open %s: %s\n", binary_path, - libbpf_strerror_r(ret, errmsg, sizeof(errmsg))); + ret = open_elf(binary_path, &elf_fd); + if (ret) return ret; - } - elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); - if (!elf) { - pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1)); - close(fd); - return -LIBBPF_ERRNO__FORMAT; - } - ret = elf_find_func_offset(elf, binary_path, name); - elf_end(elf); - close(fd); + ret = elf_find_func_offset(elf_fd.elf, binary_path, name); + close_elf(&elf_fd); return ret; } From patchwork Tue Jun 20 08:35:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285339 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB17FBE79 for ; Tue, 20 Jun 2023 08:37:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 08D0CC433C0; Tue, 20 Jun 2023 08:37:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250233; bh=WnIiyyCdWJBV8qamKYIlo+hki/XDjwGmeQAnAigmTZ8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z7hUTvodA9VoQdwkCHdYOlrydwWu2/iSrb+HgNM7+K4vo4NrBTrxs2hZA4SEb6MR3 PDQfXnLQIqcXDFWkjxJ/AjQaEYMD92vY23bZFClmhGeuhCbf4GeSlp2Fjz5TMpIgcb lsP3Yqq1ErwxzfguWvS3yhpoODD+DJKhThqUKVwozZmh308HoJ46PsyrFdj74cNA4t 609r5xgLxiO/YtcsnUgK0uOO2JDuTFp+pU5xVBYfEnnpjC0Q0B5ZXib21FVtJLit+k 7IFSRMqoBVkTGZJtCRyGokkHoYCQoMxJku4CWNqJsfrIPNymNX14KSQ7dthKz5jf2R i5RSmD7QfBedQ== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 08/24] libbpf: Add elf_find_multi_func_offset function Date: Tue, 20 Jun 2023 10:35:34 +0200 Message-ID: <20230620083550.690426-9-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding elf_find_multi_func_offset function that looks up offsets for symbols specified in syms array argument. Offsets are returned in allocated array with the 'cnt' size, that needs to be released by the caller. Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 112 ++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf_internal.h | 2 + 2 files changed, 114 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 30d9e3b69114..1c310b718961 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -11053,6 +11053,118 @@ static long elf_find_func_offset(Elf *elf, const char *binary_path, const char * return ret; } +struct elf_symbol_offset { + const char *name; + unsigned long offset; + int bind; + int idx; +}; + +static int cmp_func_offset(const void *_a, const void *_b) +{ + const struct elf_symbol_offset *a = _a; + const struct elf_symbol_offset *b = _b; + + return strcmp(a->name, b->name); +} + +static int +__elf_find_multi_func_offset(Elf *elf, const char *binary_path, int cnt, + const char **syms, unsigned long **poffsets) +{ + int sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB }; + struct elf_symbol_offset *func_offs; + int err = 0, i, idx, cnt_done = 0; + unsigned long *offsets = NULL; + + func_offs = calloc(cnt, sizeof(*func_offs)); + if (!func_offs) + return -ENOMEM; + + for (i = 0; i < cnt; i++) { + func_offs[i].name = syms[i]; + func_offs[i].idx = i; + } + + qsort(func_offs, cnt, sizeof(*func_offs), cmp_func_offset); + + for (i = 0; i < ARRAY_SIZE(sh_types); i++) { + struct elf_symbol_iter iter; + struct elf_symbol *sym; + + if (elf_symbol_iter_new(&iter, elf, binary_path, sh_types[i])) + continue; + + while ((sym = elf_symbol_iter_next(&iter))) { + struct elf_symbol_offset *fo, tmp = { + .name = sym->name, + }; + + fo = bsearch(&tmp, func_offs, cnt, sizeof(*func_offs), + cmp_func_offset); + if (!fo) + continue; + + if (fo->offset > 0) { + /* same offset, no problem */ + if (fo->offset == sym->offset) + continue; + /* handle multiple matches */ + if (fo->bind != STB_WEAK && sym->bind != STB_WEAK) { + /* Only accept one non-weak bind. */ + pr_warn("elf: ambiguous match for '%s', '%s' in '%s'\n", + sym->name, fo->name, binary_path); + err = -LIBBPF_ERRNO__FORMAT; + goto out; + } else if (sym->bind == STB_WEAK) { + /* already have a non-weak bind, and + * this is a weak bind, so ignore. + */ + continue; + } + } + if (!fo->offset) + cnt_done++; + fo->offset = sym->offset; + fo->bind = sym->bind; + } + } + + if (cnt != cnt_done) { + err = -ENOENT; + goto out; + } + offsets = calloc(cnt, sizeof(*offsets)); + if (!offsets) { + err = -ENOMEM; + goto out; + } + for (i = 0; i < cnt; i++) { + idx = func_offs[i].idx; + offsets[idx] = func_offs[i].offset; + } + +out: + *poffsets = offsets; + free(func_offs); + return err; +} + +int elf_find_multi_func_offset(const char *binary_path, int cnt, + const char **syms, unsigned long **poffsets) +{ + struct elf_fd elf_fd = {}; + long ret = -ENOENT; + + ret = open_elf(binary_path, &elf_fd); + if (ret) + return ret; + + ret = __elf_find_multi_func_offset(elf_fd.elf, binary_path, cnt, syms, poffsets); + close_elf(&elf_fd); + return ret; +} + /* Find offset of function name in ELF object specified by path. "name" matches * symbol name or name@@LIB for library functions. */ diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index e4d05662a96c..13d5c12fbd0b 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -577,4 +577,6 @@ static inline bool is_pow_of_2(size_t x) #define PROG_LOAD_ATTEMPTS 5 int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts); +int elf_find_multi_func_offset(const char *binary_path, int cnt, + const char **syms, unsigned long **poffsets); #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ From patchwork Tue Jun 20 08:35:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285340 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7479D848A for ; Tue, 20 Jun 2023 08:37:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BDB89C433C8; Tue, 20 Jun 2023 08:37:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250243; bh=87ltz8OFoHjN13nhur6YjnSHECjD0n5EokxPHu4lJSw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LtKx6enx80yuG4RJ8mcO7Q+8/c3q0hJRIOFNAISBB/zH1YW1IQky/Z8SRtwEZp9/O 65PnMGoBkwdknRV9AhVvf1OzwIATo94Nlt5OxrhvjJMOa8zeSMgx4ltf75UrdrAQLX lll81hGJ33oNefT3IqeGODHBUIe4SqvneKAVLG9n68lv6YNL/jbxA+OksMiOU992Q8 EWxKB+5NiMihu/crIo2p7BwNNBrLhRx2tiFM6fRqyuD6g4OJYutLc0x3AVQnrif193 aZnR+VRRGD2bWSG4pdlBypO61Pmhhjwa5qMhAukbEy0WF150uQt3/KSG8jjFaxfavx 3Itlfo/UazVwg== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 09/24] libbpf: Add elf_find_pattern_func_offset function Date: Tue, 20 Jun 2023 10:35:35 +0200 Message-ID: <20230620083550.690426-10-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding elf_find_pattern_func_offset function that looks up offsets for symbols specified by pattern argument. The 'pattern' argument allows wildcards (*?' supported). Offsets are returned in allocated array together with its size and needs to be released by the caller. Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 78 +++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf_internal.h | 3 ++ 2 files changed, 81 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 1c310b718961..3e5c88caf5d5 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -11165,6 +11165,84 @@ int elf_find_multi_func_offset(const char *binary_path, int cnt, return ret; } +static int +__elf_find_pattern_func_offset(Elf *elf, const char *binary_path, const char *pattern, + const char ***pnames, unsigned long **poffsets, size_t *pcnt) +{ + int sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB }; + struct elf_symbol_offset *func_offs = NULL; + unsigned long *offsets = NULL; + const char **names = NULL; + size_t func_offs_cnt = 0; + size_t func_offs_cap = 0; + int err = 0, i; + + for (i = 0; i < ARRAY_SIZE(sh_types); i++) { + struct elf_symbol_iter iter; + struct elf_symbol *sym; + + if (elf_symbol_iter_new(&iter, elf, binary_path, sh_types[i])) + continue; + + while ((sym = elf_symbol_iter_next(&iter))) { + if (!glob_match(sym->name, pattern)) + continue; + + err = libbpf_ensure_mem((void **) &func_offs, &func_offs_cap, + sizeof(*func_offs), func_offs_cnt + 1); + if (err) + goto out; + + func_offs[func_offs_cnt].offset = sym->offset; + func_offs[func_offs_cnt].name = strdup(sym->name); + func_offs_cnt++; + } + + /* If we found anything in the first symbol section, + * do not search others to avoid duplicates. + */ + if (func_offs_cnt) + break; + } + + offsets = calloc(func_offs_cnt, sizeof(*offsets)); + names = calloc(func_offs_cnt, sizeof(*names)); + if (!offsets || !names) { + free(offsets); + free(names); + err = -ENOMEM; + goto out; + } + + for (i = 0; i < func_offs_cnt; i++) { + offsets[i] = func_offs[i].offset; + names[i] = func_offs[i].name; + } + + *pnames = names; + *poffsets = offsets; + *pcnt = func_offs_cnt; +out: + free(func_offs); + return err; +} + +int elf_find_pattern_func_offset(const char *binary_path, const char *pattern, + const char ***pnames, unsigned long **poffsets, + size_t *pcnt) +{ + struct elf_fd elf_fd = {}; + long ret = -ENOENT; + + ret = open_elf(binary_path, &elf_fd); + if (ret) + return ret; + + ret = __elf_find_pattern_func_offset(elf_fd.elf, binary_path, pattern, pnames, poffsets, pcnt); + close_elf(&elf_fd); + return ret; +} + /* Find offset of function name in ELF object specified by path. "name" matches * symbol name or name@@LIB for library functions. */ diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 13d5c12fbd0b..22b0834e7fe1 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -579,4 +579,7 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts); int elf_find_multi_func_offset(const char *binary_path, int cnt, const char **syms, unsigned long **poffsets); +int elf_find_pattern_func_offset(const char *binary_path, const char *pattern, + const char ***pnames, unsigned long **poffsets, + size_t *pcnt); #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ From patchwork Tue Jun 20 08:35:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285341 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A9D5A92D for ; Tue, 20 Jun 2023 08:37:33 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 92E92C433C8; Tue, 20 Jun 2023 08:37:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250253; bh=A2Jx8O/za5xOv/x7nAQNjLOaUfH7Kx/T6Bd6yMcIq90=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t7FR0jcXiYN1nB3xlzCLkZmqtLMzsDjvnpsv++ZqR1kVgtFssshuKIb98ReGwuNpL /ejfAoIOSXIh/odA6TrsioOm4W3ePm9o2oLsUREul9/ob4Un+rfbWHORiQZ3feRYa0 lMRnT6Q5jmC48bShkxBlYtGq/EAgOc4gXcC36xhSkadTFJ8j1oeNKms4ql+7ylaZ2T Oyy4YQTalJilcBRL3GMenxCXcmky2uOR+Hq8LGK5li50RcA32abmpQw/IZSUQs9DbJ F2N/mCVjl8w/0hHyaHhGR4vA/RKuzKKqIdCpdljy/sxx+nJNb+93Qq91YbaeL1xBVd ihdCQSKyVbQhw== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 10/24] libbpf: Add bpf_link_create support for multi uprobes Date: Tue, 20 Jun 2023 10:35:36 +0200 Message-ID: <20230620083550.690426-11-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding new uprobe_multi struct to bpf_link_create_opts object to pass multiple uprobe data to link_create attr uapi. Signed-off-by: Jiri Olsa Acked-by: Andrii Nakryiko --- tools/lib/bpf/bpf.c | 11 +++++++++++ tools/lib/bpf/bpf.h | 11 ++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index ed86b37d8024..0fd35c91f50c 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -733,6 +733,17 @@ int bpf_link_create(int prog_fd, int target_fd, if (!OPTS_ZEROED(opts, kprobe_multi)) return libbpf_err(-EINVAL); break; + case BPF_TRACE_UPROBE_MULTI: + attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0); + attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0); + attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0)); + attr.link_create.uprobe_multi.offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.offsets, 0)); + attr.link_create.uprobe_multi.ref_ctr_offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.ref_ctr_offsets, 0)); + attr.link_create.uprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, uprobe_multi.cookies, 0)); + attr.link_create.uprobe_multi.pid = OPTS_GET(opts, uprobe_multi.pid, 0); + if (!OPTS_ZEROED(opts, uprobe_multi)) + return libbpf_err(-EINVAL); + break; case BPF_TRACE_FENTRY: case BPF_TRACE_FEXIT: case BPF_MODIFY_RETURN: diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 9aa0ee473754..82979b4f2769 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -346,13 +346,22 @@ struct bpf_link_create_opts { const unsigned long *addrs; const __u64 *cookies; } kprobe_multi; + struct { + __u32 flags; + __u32 cnt; + const char *path; + const unsigned long *offsets; + const unsigned long *ref_ctr_offsets; + const __u64 *cookies; + __u32 pid; + } uprobe_multi; struct { __u64 cookie; } tracing; }; size_t :0; }; -#define bpf_link_create_opts__last_field kprobe_multi.cookies +#define bpf_link_create_opts__last_field uprobe_multi.pid LIBBPF_API int bpf_link_create(int prog_fd, int target_fd, enum bpf_attach_type attach_type, From patchwork Tue Jun 20 08:35:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285342 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EAA5FA92D for ; Tue, 20 Jun 2023 08:37:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 48665C433C8; Tue, 20 Jun 2023 08:37:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250262; bh=FktqRvEKOQuxcgLuyn2EXyM9kfljvnXA9PSx8mLls3c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=U7j3MCDaFWl1044ISgiogCYF0mqMfbHa9I3hI5i7z5Ifjf/vHtl8XDyiBQfJ5sfgV SYYx4UfkrGQdL3gOKU3iWXQSsoLIVtWYIDjyA56pODYmAtRiCXD0IeM3j/x/1/et7H RG8iSRdEOai8vsh1H9hSi03lsXwV3xkUSSsPlXXigneTqKH5+V8DS6oZeCFtiAvjPq l7D9GmbienLlgcOpvvhvfnmAo93UOa95oYkvFxvYDiaF1zIQqDUsQvCE67m7NW7cVS I/ccybOvSr34/9Et7bf7ivVdLoCpYXi57W2QydAH9psp+WOuHoN0gwbwuEi2DUcf3b VTeuVNzvSMe7g== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 11/24] libbpf: Add bpf_program__attach_uprobe_multi_opts function Date: Tue, 20 Jun 2023 10:35:37 +0200 Message-ID: <20230620083550.690426-12-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding bpf_program__attach_uprobe_multi_opts function that allows to attach multiple uprobes with uprobe_multi link. The user can specify uprobes with direct arguments: binary_path/func_pattern or with struct bpf_uprobe_multi_opts opts argument fields: const char *path; const char **syms; const unsigned long *offsets; const unsigned long *ref_ctr_offsets; User can specify 3 mutually exclusive set of incputs: 1) use only binary_path/func_pattern aruments 2) use only opts argument with allowed combinations of: path/offsets/ref_ctr_offsets/cookies/cnt 3) use binary_path with allowed combinations of: syms/offsets/ref_ctr_offsets/cookies/cnt Any other usage results in error. Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 131 +++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 31 +++++++++ tools/lib/bpf/libbpf.map | 1 + 3 files changed, 163 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 3e5c88caf5d5..d972cea4c658 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -11402,6 +11402,137 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz) return -ENOENT; } +struct bpf_link * +bpf_program__attach_uprobe_multi_opts(const struct bpf_program *prog, + pid_t pid, + const char *binary_path, + const char *func_pattern, + const struct bpf_uprobe_multi_opts *opts) +{ + const unsigned long *ref_ctr_offsets = NULL, *offsets = NULL; + LIBBPF_OPTS(bpf_link_create_opts, lopts); + unsigned long *resolved_offsets = NULL; + const char **resolved_symbols = NULL; + int err = 0, link_fd, prog_fd; + struct bpf_link *link = NULL; + char errmsg[STRERR_BUFSIZE]; + const char *path, **syms; + char full_path[PATH_MAX]; + const __u64 *cookies; + bool has_pattern; + bool retprobe; + size_t cnt; + + if (!OPTS_VALID(opts, bpf_uprobe_multi_opts)) + return libbpf_err_ptr(-EINVAL); + + path = OPTS_GET(opts, path, NULL); + syms = OPTS_GET(opts, syms, NULL); + offsets = OPTS_GET(opts, offsets, NULL); + ref_ctr_offsets = OPTS_GET(opts, ref_ctr_offsets, NULL); + cookies = OPTS_GET(opts, cookies, NULL); + cnt = OPTS_GET(opts, cnt, 0); + + /* + * User can specify 3 mutually exclusive set of incputs: + * + * 1) use only binary_path/func_pattern aruments + * + * 2) use only opts argument with allowed combinations of: + * path/offsets/ref_ctr_offsets/cookies/cnt + * + * 3) use binary_path with allowed combinations of: + * syms/offsets/ref_ctr_offsets/cookies/cnt + * + * Any other usage results in error. + */ + + if (!binary_path && !func_pattern && !cnt) + return libbpf_err_ptr(-EINVAL); + if (func_pattern && !binary_path) + return libbpf_err_ptr(-EINVAL); + + has_pattern = binary_path && func_pattern; + + if (has_pattern) { + if (path || syms || offsets || ref_ctr_offsets || cookies || cnt) + return libbpf_err_ptr(-EINVAL); + } else { + if (!cnt) + return libbpf_err_ptr(-EINVAL); + if (!!path == !!binary_path) + return libbpf_err_ptr(-EINVAL); + if (!!syms == !!offsets) + return libbpf_err_ptr(-EINVAL); + if (path && syms) + return libbpf_err_ptr(-EINVAL); + } + + if (has_pattern) { + if (!strchr(binary_path, '/')) { + err = resolve_full_path(binary_path, full_path, sizeof(full_path)); + if (err) { + pr_warn("prog '%s': failed to resolve full path for '%s': %d\n", + prog->name, binary_path, err); + return libbpf_err_ptr(err); + } + binary_path = full_path; + } + + err = elf_find_pattern_func_offset(binary_path, func_pattern, + &resolved_symbols, &resolved_offsets, + &cnt); + if (err < 0) + return libbpf_err_ptr(err); + offsets = resolved_offsets; + } else if (syms) { + err = elf_find_multi_func_offset(binary_path, cnt, syms, &resolved_offsets); + if (err < 0) + return libbpf_err_ptr(err); + offsets = resolved_offsets; + } + + retprobe = OPTS_GET(opts, retprobe, false); + + lopts.uprobe_multi.path = path ?: binary_path; + lopts.uprobe_multi.offsets = offsets; + lopts.uprobe_multi.ref_ctr_offsets = ref_ctr_offsets; + lopts.uprobe_multi.cookies = cookies; + lopts.uprobe_multi.cnt = cnt; + lopts.uprobe_multi.flags = retprobe ? BPF_F_UPROBE_MULTI_RETURN : 0; + + if (pid == 0) + pid = getpid(); + if (pid > 0) + lopts.uprobe_multi.pid = pid; + + link = calloc(1, sizeof(*link)); + if (!link) { + err = -ENOMEM; + goto error; + } + link->detach = &bpf_link__detach_fd; + + prog_fd = bpf_program__fd(prog); + link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &lopts); + if (link_fd < 0) { + err = -errno; + pr_warn("prog '%s': failed to attach: %s\n", + prog->name, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); + goto error; + } + link->fd = link_fd; + free(resolved_offsets); + free(resolved_symbols); + return link; + +error: + free(resolved_offsets); + free(resolved_symbols); + free(link); + return libbpf_err_ptr(err); +} + LIBBPF_API struct bpf_link * bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid, const char *binary_path, size_t func_offset, diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 754da73c643b..b6ff7d69a1d7 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -529,6 +529,37 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog, const char *pattern, const struct bpf_kprobe_multi_opts *opts); +struct bpf_uprobe_multi_opts { + /* size of this struct, for forward/backward compatibility */ + size_t sz; + /* path to attach */ + const char *path; + /* array of function symbols to attach */ + const char **syms; + /* array of function addresses to attach */ + const unsigned long *offsets; + /* array of refctr offsets to attach */ + const unsigned long *ref_ctr_offsets; + /* array of user-provided values fetchable through bpf_get_attach_cookie */ + const __u64 *cookies; + /* number of elements in syms/addrs/cookies arrays */ + size_t cnt; + /* create return uprobes */ + bool retprobe; + /* pid filter */ + int pid; + size_t :0; +}; + +#define bpf_uprobe_multi_opts__last_field pid + +LIBBPF_API struct bpf_link * +bpf_program__attach_uprobe_multi_opts(const struct bpf_program *prog, + pid_t pid, + const char *binary_path, + const char *func_pattern, + const struct bpf_uprobe_multi_opts *opts); + struct bpf_ksyscall_opts { /* size of this struct, for forward/backward compatibility */ size_t sz; diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 7521a2fb7626..81558ef1bc38 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -390,6 +390,7 @@ LIBBPF_1.2.0 { bpf_link_get_info_by_fd; bpf_map_get_info_by_fd; bpf_prog_get_info_by_fd; + bpf_program__attach_uprobe_multi_opts; } LIBBPF_1.1.0; LIBBPF_1.3.0 { From patchwork Tue Jun 20 08:35:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285343 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD28EA92D for ; Tue, 20 Jun 2023 08:37:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DEA7FC433C8; Tue, 20 Jun 2023 08:37:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250272; bh=He9DsUYtpOl3ySXBGF7rzUxoRYpxIWH1lg3O5a+kdDY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uzCx1VS3K+BsiTMmQzZ1y5SSMT9GWGAVP1Uv5FGjVAXsxPoZ+SuzU1RACegg/xN3K fOPz4RybiORrny+1EKEYR+Y7E2FK1J0xghs4ySSXY+yl066cfHPOoqw6xt3QlULOkB AoWFT5b4JOsOu47aNIMAzWiixrUCt2GeYwfBPpZaRG3hjFNYS8NJOBYNR8zNifZ627 Q7T0lSj87iht7lUnzw6m54kgz+XdNjpj3zyQmro/NWHogsDXvku6bPflskBh8d2pWF Lr2SLHOQneLHbNlqA0UfJRXksy3oUl0pHeAd/Sxn5H6bIdztAHn5lg9IX+INk1vETn o/9z7vuP5/34g== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 12/24] libbpf: Add support for u[ret]probe.multi[.s] program sections Date: Tue, 20 Jun 2023 10:35:38 +0200 Message-ID: <20230620083550.690426-13-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding support for several uprobe_multi program sections to allow auto attach of multi_uprobe programs. Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index d972cea4c658..e42080258ec7 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -8652,6 +8652,7 @@ static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_lin static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link); static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_link **link); static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link); +static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link); static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link); static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link); @@ -8667,6 +8668,10 @@ static const struct bpf_sec_def section_defs[] = { SEC_DEF("uretprobe.s+", KPROBE, 0, SEC_SLEEPABLE, attach_uprobe), SEC_DEF("kprobe.multi+", KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi), SEC_DEF("kretprobe.multi+", KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi), + SEC_DEF("uprobe.multi+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi), + SEC_DEF("uretprobe.multi+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi), + SEC_DEF("uprobe.multi.s+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi), + SEC_DEF("uretprobe.multi.s+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi), SEC_DEF("ksyscall+", KPROBE, 0, SEC_NONE, attach_ksyscall), SEC_DEF("kretsyscall+", KPROBE, 0, SEC_NONE, attach_ksyscall), SEC_DEF("usdt+", KPROBE, 0, SEC_NONE, attach_usdt), @@ -10728,6 +10733,41 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru return libbpf_get_error(*link); } +static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link) +{ + char *probe_type = NULL, *binary_path = NULL, *func_name = NULL; + LIBBPF_OPTS(bpf_uprobe_multi_opts, opts); + int n, ret = -EINVAL; + + *link = NULL; + + n = sscanf(prog->sec_name, "%m[^/]/%m[^:]:%ms", + &probe_type, &binary_path, &func_name); + switch (n) { + case 1: + /* handle SEC("u[ret]probe") - format is valid, but auto-attach is impossible. */ + ret = 0; + break; + case 2: + pr_warn("prog '%s': section '%s' missing ':function[+offset]' specification\n", + prog->name, prog->sec_name); + break; + case 3: + opts.retprobe = strcmp(probe_type, "uretprobe.multi"); + *link = bpf_program__attach_uprobe_multi_opts(prog, -1, binary_path, func_name, &opts); + ret = libbpf_get_error(*link); + break; + default: + pr_warn("prog '%s': invalid format of section definition '%s'\n", prog->name, + prog->sec_name); + break; + } + free(probe_type); + free(binary_path); + free(func_name); + return ret; +} + static void gen_uprobe_legacy_event_name(char *buf, size_t buf_sz, const char *binary_path, uint64_t offset) { From patchwork Tue Jun 20 08:35:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285344 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40B7C4400 for ; Tue, 20 Jun 2023 08:38:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 934AFC433C8; Tue, 20 Jun 2023 08:37:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250282; bh=uO+8Th2NqoNTdu0300lnGgBvDFBT0ANoSG5DGFrGOcg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t1HQzxPmS9cbji+aj9d/KLmEhOTFpBwssEb8nBl19RirOsioX7To2cQPNX39QWkb+ FrT3WMrgzqtqHtgWjWQmoFNoL4EHRRTf6otiRw88WT18a+iQMU2QE++QdSGIqlXybM BG/JNuw6M6FHHnf6ndq4QGbBjHr0wjvhnj3QvbiC3qKIMb0sfm78FmQrgv3AKYX2+N rUgVKzl2QSOVuRJoRl6wpxAbR7R5Va9AoEgjn1Tb0/1IXKKrWcFx5xDdpywx62d6J4 nxs6ncBODDil4d4/8BBZ/Ttx5GrpI7wIq3+5SbzAUzDtznCvcGr37OXVNO1UZiyyrf xg2bxmCMwuOqA== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 13/24] libbpf: Add uprobe multi link detection Date: Tue, 20 Jun 2023 10:35:39 +0200 Message-ID: <20230620083550.690426-14-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding uprobe-multi link detection. It will be used later in bpf_program__attach_usdt function to check and use uprobe_multi link over standard uprobe links. Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 29 +++++++++++++++++++++++++++++ tools/lib/bpf/libbpf_internal.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index e42080258ec7..3d570898459e 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -4815,6 +4815,32 @@ static int probe_perf_link(void) return link_fd < 0 && err == -EBADF; } +static int probe_uprobe_multi_link(void) +{ + struct bpf_insn insns[] = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }; + int prog_fd, link_fd, err; + + prog_fd = bpf_prog_load(BPF_PROG_TYPE_KPROBE, NULL, "GPL", + insns, ARRAY_SIZE(insns), NULL); + if (prog_fd < 0) + return -errno; + + /* No need to specify attach function. If the link is not supported + * we will get -EOPNOTSUPP error before any other check is performed. + */ + link_fd = bpf_link_create(prog_fd, -1, BPF_TRACE_UPROBE_MULTI, NULL); + err = -errno; /* close() can clobber errno */ + + if (link_fd >= 0) + close(link_fd); + close(prog_fd); + + return link_fd < 0 && err != -EOPNOTSUPP; +} + static int probe_kern_bpf_cookie(void) { struct bpf_insn insns[] = { @@ -4911,6 +4937,9 @@ static struct kern_feature_desc { [FEAT_SYSCALL_WRAPPER] = { "Kernel using syscall wrapper", probe_kern_syscall_wrapper, }, + [FEAT_UPROBE_LINK] = { + "BPF uprobe multi link support", probe_uprobe_multi_link, + }, }; bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id) diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 22b0834e7fe1..a257eb81af25 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -354,6 +354,8 @@ enum kern_feature_id { FEAT_BTF_ENUM64, /* Kernel uses syscall wrapper (CONFIG_ARCH_HAS_SYSCALL_WRAPPER) */ FEAT_SYSCALL_WRAPPER, + /* BPF uprobe_multi link support */ + FEAT_UPROBE_LINK, __FEAT_CNT, }; From patchwork Tue Jun 20 08:35:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285345 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43D60BE68 for ; Tue, 20 Jun 2023 08:38:11 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 33238C433C8; Tue, 20 Jun 2023 08:38:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250291; bh=tI02N+zdwXIpS7egsOVkAi/cl+6VnbmyodziglFpAe8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KBlD02SbrMWo9+AwYuyLICOwSXW/ziwFR0z+TGVwQjTEng0vfZlJPbLCVAgXhnZlo g77bR/Ty5coWIHTrQD7H7SGiI/B6cPglhaLJAWXiB+xcflg8ZcFWSGCBlx+HLBNbWV qeQKi5tjERrFOcHMcrLCxyofqvhia/mXSKiz1vEcy20h6fZ1Jd2EGQp0eNi64zHqdS cTM/sL1o8tCMcuRuDHSlWDmN6j1ocRgOKZLynodaAN47jE5PnuTovUKrMKQbERON6J d2X+b2N7PsfXF0YghQf4gK2D+zN4TXt3UffHV/QugDX84QW8zeIlAQGRYDB3Rrfot1 fYtdsChsA2pmg== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 14/24] libbpf: Add uprobe multi link support to bpf_program__attach_usdt Date: Tue, 20 Jun 2023 10:35:40 +0200 Message-ID: <20230620083550.690426-15-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding support for usdt_manager_attach_usdt to use uprobe_multi link to attach to usdt probes. The uprobe_multi support is detected before the usdt program is loaded and its expected_attach_type is set accordingly. If uprobe_multi support is detected the usdt_manager_attach_usdt gathers uprobes info and calls bpf_program__attach_uprobe_opts to create all needed uprobes. If uprobe_multi support is not detected the old behaviour stays. Signed-off-by: Jiri Olsa --- tools/lib/bpf/libbpf.c | 12 ++++- tools/lib/bpf/usdt.c | 120 ++++++++++++++++++++++++++++++----------- 2 files changed, 99 insertions(+), 33 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 3d570898459e..9c7a67c5cbe8 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -363,6 +363,8 @@ enum sec_def_flags { SEC_SLEEPABLE = 8, /* BPF program support non-linear XDP buffer */ SEC_XDP_FRAGS = 16, + /* Setup proper attach type for usdt probes. */ + SEC_USDT = 32, }; struct bpf_sec_def { @@ -6799,6 +6801,10 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog, if (prog->type == BPF_PROG_TYPE_XDP && (def & SEC_XDP_FRAGS)) opts->prog_flags |= BPF_F_XDP_HAS_FRAGS; + /* special check for usdt to use uprobe_multi link */ + if ((def & SEC_USDT) && kernel_supports(NULL, FEAT_UPROBE_LINK)) + prog->expected_attach_type = BPF_TRACE_UPROBE_MULTI; + if ((def & SEC_ATTACH_BTF) && !prog->attach_btf_id) { int btf_obj_fd = 0, btf_type_id = 0, err; const char *attach_name; @@ -6867,7 +6873,6 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog if (!insns || !insns_cnt) return -EINVAL; - load_attr.expected_attach_type = prog->expected_attach_type; if (kernel_supports(obj, FEAT_PROG_NAME)) prog_name = prog->name; load_attr.attach_prog_fd = prog->attach_prog_fd; @@ -6903,6 +6908,9 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog insns_cnt = prog->insns_cnt; } + /* allow prog_prepare_load_fn to change expected_attach_type */ + load_attr.expected_attach_type = prog->expected_attach_type; + if (obj->gen_loader) { bpf_gen__prog_load(obj->gen_loader, prog->type, prog->name, license, insns, insns_cnt, &load_attr, @@ -8703,7 +8711,7 @@ static const struct bpf_sec_def section_defs[] = { SEC_DEF("uretprobe.multi.s+", KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi), SEC_DEF("ksyscall+", KPROBE, 0, SEC_NONE, attach_ksyscall), SEC_DEF("kretsyscall+", KPROBE, 0, SEC_NONE, attach_ksyscall), - SEC_DEF("usdt+", KPROBE, 0, SEC_NONE, attach_usdt), + SEC_DEF("usdt+", KPROBE, 0, SEC_USDT, attach_usdt), SEC_DEF("tc", SCHED_CLS, 0, SEC_NONE), SEC_DEF("classifier", SCHED_CLS, 0, SEC_NONE), SEC_DEF("action", SCHED_ACT, 0, SEC_NONE), diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c index f1a141555f08..33f0a2b4cc1c 100644 --- a/tools/lib/bpf/usdt.c +++ b/tools/lib/bpf/usdt.c @@ -808,6 +808,16 @@ struct bpf_link_usdt { long abs_ip; struct bpf_link *link; } *uprobes; + + bool has_uprobe_multi; + + struct { + char *path; + unsigned long *offsets; + unsigned long *ref_ctr_offsets; + __u64 *cookies; + struct bpf_link *link; + } uprobe_multi; }; static int bpf_link_usdt_detach(struct bpf_link *link) @@ -816,19 +826,23 @@ static int bpf_link_usdt_detach(struct bpf_link *link) struct usdt_manager *man = usdt_link->usdt_man; int i; - for (i = 0; i < usdt_link->uprobe_cnt; i++) { - /* detach underlying uprobe link */ - bpf_link__destroy(usdt_link->uprobes[i].link); - /* there is no need to update specs map because it will be - * unconditionally overwritten on subsequent USDT attaches, - * but if BPF cookies are not used we need to remove entry - * from ip_to_spec_id map, otherwise we'll run into false - * conflicting IP errors - */ - if (!man->has_bpf_cookie) { - /* not much we can do about errors here */ - (void)bpf_map_delete_elem(bpf_map__fd(man->ip_to_spec_id_map), - &usdt_link->uprobes[i].abs_ip); + if (usdt_link->has_uprobe_multi) { + bpf_link__destroy(usdt_link->uprobe_multi.link); + } else { + for (i = 0; i < usdt_link->uprobe_cnt; i++) { + /* detach underlying uprobe link */ + bpf_link__destroy(usdt_link->uprobes[i].link); + /* there is no need to update specs map because it will be + * unconditionally overwritten on subsequent USDT attaches, + * but if BPF cookies are not used we need to remove entry + * from ip_to_spec_id map, otherwise we'll run into false + * conflicting IP errors + */ + if (!man->has_bpf_cookie) { + /* not much we can do about errors here */ + (void)bpf_map_delete_elem(bpf_map__fd(man->ip_to_spec_id_map), + &usdt_link->uprobes[i].abs_ip); + } } } @@ -868,9 +882,15 @@ static void bpf_link_usdt_dealloc(struct bpf_link *link) { struct bpf_link_usdt *usdt_link = container_of(link, struct bpf_link_usdt, link); - free(usdt_link->spec_ids); - free(usdt_link->uprobes); - free(usdt_link); + if (usdt_link->has_uprobe_multi) { + free(usdt_link->uprobe_multi.offsets); + free(usdt_link->uprobe_multi.ref_ctr_offsets); + free(usdt_link->uprobe_multi.cookies); + } else { + free(usdt_link->spec_ids); + free(usdt_link->uprobes); + free(usdt_link); + } } static size_t specs_hash_fn(long key, void *ctx) @@ -943,11 +963,13 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct const char *usdt_provider, const char *usdt_name, __u64 usdt_cookie) { + LIBBPF_OPTS(bpf_uprobe_multi_opts, opts_multi); int i, fd, err, spec_map_fd, ip_map_fd; LIBBPF_OPTS(bpf_uprobe_opts, opts); struct hashmap *specs_hash = NULL; struct bpf_link_usdt *link = NULL; struct usdt_target *targets = NULL; + struct bpf_link *uprobe_link; size_t target_cnt; Elf *elf; @@ -1003,16 +1025,29 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct link->usdt_man = man; link->link.detach = &bpf_link_usdt_detach; link->link.dealloc = &bpf_link_usdt_dealloc; + link->has_uprobe_multi = bpf_program__expected_attach_type(prog) == BPF_TRACE_UPROBE_MULTI; - link->uprobes = calloc(target_cnt, sizeof(*link->uprobes)); - if (!link->uprobes) { - err = -ENOMEM; - goto err_out; + if (link->has_uprobe_multi) { + link->uprobe_multi.offsets = calloc(target_cnt, sizeof(*link->uprobe_multi.offsets)); + link->uprobe_multi.ref_ctr_offsets = calloc(target_cnt, sizeof(*link->uprobe_multi.ref_ctr_offsets)); + link->uprobe_multi.cookies = calloc(target_cnt, sizeof(*link->uprobe_multi.cookies)); + + if (!link->uprobe_multi.offsets || + !link->uprobe_multi.ref_ctr_offsets || + !link->uprobe_multi.cookies) { + err = -ENOMEM; + goto err_out; + } + } else { + link->uprobes = calloc(target_cnt, sizeof(*link->uprobes)); + if (!link->uprobes) { + err = -ENOMEM; + goto err_out; + } } for (i = 0; i < target_cnt; i++) { struct usdt_target *target = &targets[i]; - struct bpf_link *uprobe_link; bool is_new; int spec_id; @@ -1048,20 +1083,43 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct goto err_out; } - opts.ref_ctr_offset = target->sema_off; - opts.bpf_cookie = man->has_bpf_cookie ? spec_id : 0; - uprobe_link = bpf_program__attach_uprobe_opts(prog, pid, path, - target->rel_ip, &opts); + if (link->has_uprobe_multi) { + link->uprobe_multi.offsets[i] = target->rel_ip; + link->uprobe_multi.ref_ctr_offsets[i] = target->sema_off; + link->uprobe_multi.cookies[i] = spec_id; + } else { + opts.ref_ctr_offset = target->sema_off; + opts.bpf_cookie = man->has_bpf_cookie ? spec_id : 0; + uprobe_link = bpf_program__attach_uprobe_opts(prog, pid, path, + target->rel_ip, &opts); + err = libbpf_get_error(uprobe_link); + if (err) { + pr_warn("usdt: failed to attach uprobe #%d for '%s:%s' in '%s': %d\n", + i, usdt_provider, usdt_name, path, err); + goto err_out; + } + + link->uprobes[i].link = uprobe_link; + link->uprobes[i].abs_ip = target->abs_ip; + link->uprobe_cnt++; + } + } + + if (link->has_uprobe_multi) { + opts_multi.cnt = target_cnt; + opts_multi.path = path; + opts_multi.offsets = link->uprobe_multi.offsets; + opts_multi.ref_ctr_offsets = link->uprobe_multi.ref_ctr_offsets; + opts_multi.cookies = link->uprobe_multi.cookies; + + uprobe_link = bpf_program__attach_uprobe_multi_opts(prog, pid, NULL, NULL, &opts_multi); err = libbpf_get_error(uprobe_link); if (err) { - pr_warn("usdt: failed to attach uprobe #%d for '%s:%s' in '%s': %d\n", - i, usdt_provider, usdt_name, path, err); + pr_warn("usdt: failed to attach uprobe multi for '%s:%s' in '%s': %d\n", + usdt_provider, usdt_name, path, err); goto err_out; } - - link->uprobes[i].link = uprobe_link; - link->uprobes[i].abs_ip = target->abs_ip; - link->uprobe_cnt++; + link->uprobe_multi.link = uprobe_link; } free(targets); From patchwork Tue Jun 20 08:35:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285346 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F8DEAD2B for ; Tue, 20 Jun 2023 08:38:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CFC5CC433C0; Tue, 20 Jun 2023 08:38:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250301; bh=r/qCypdLDUAiuSd7OKqIYDN+uJTDFtEUejCrOrITWug=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y/fP81T0RI9Hz+5RyZYnWOa8+LW/9W4e6/MucrHEBko6Yc42z+fBt8JwOyTc0U1d9 oNdzs6WrEkG+H/kW8u3DqSRApLIslom15FEuAUIA2foYGfaf1k+UfD4kWfq50R96xe 1ukcwMXJ2h+T7U8LCQd1TTCgZX9ChZnSf95d0cvAldlu6BRcxPYSNVW92t6MURJED6 JP0Fvu4LACw5JAf4MWRxiTwv4XImjRyv2D18wexAmocYFFOiPoe+F1MlAeHTT0fdJN ePO7SxSGBu8YWDwxqEhAfmKCN6uWpi1C9MggEzKb10tc0xnrSJAYqAT41ohVsUegQN gLB9IkK5nG0VA== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 15/24] selftests/bpf: Add uprobe_multi skel test Date: Tue, 20 Jun 2023 10:35:41 +0200 Message-ID: <20230620083550.690426-16-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding uprobe_multi test for skeleton load/attach functions, to test skeleton auto attach for uprobe_multi link. Test that bpf_get_func_ip works properly for uprobe_multi attachment. Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c | 76 ++++++++++++++++ .../selftests/bpf/progs/uprobe_multi.c | 91 +++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c create mode 100644 tools/testing/selftests/bpf/progs/uprobe_multi.c diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c new file mode 100644 index 000000000000..5cd1116bbb62 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include "uprobe_multi.skel.h" + +static char test_data[] = "test_data"; + +noinline void uprobe_multi_func_1(void) +{ + asm volatile (""); +} + +noinline void uprobe_multi_func_2(void) +{ + asm volatile (""); +} + +noinline void uprobe_multi_func_3(void) +{ + asm volatile (""); +} + +static void uprobe_multi_test_run(struct uprobe_multi *skel) +{ + skel->bss->uprobe_multi_func_1_addr = (__u64) uprobe_multi_func_1; + skel->bss->uprobe_multi_func_2_addr = (__u64) uprobe_multi_func_2; + skel->bss->uprobe_multi_func_3_addr = (__u64) uprobe_multi_func_3; + + skel->bss->user_ptr = test_data; + skel->bss->pid = getpid(); + + /* trigger all probes */ + uprobe_multi_func_1(); + uprobe_multi_func_2(); + uprobe_multi_func_3(); + + /* + * There are 2 entry and 2 exit probe called for each uprobe_multi_func_[123] + * function and each slepable probe (6) increments uprobe_multi_sleep_result. + */ + ASSERT_EQ(skel->bss->uprobe_multi_func_1_result, 2, "uprobe_multi_func_1_result"); + ASSERT_EQ(skel->bss->uprobe_multi_func_2_result, 2, "uprobe_multi_func_2_result"); + ASSERT_EQ(skel->bss->uprobe_multi_func_3_result, 2, "uprobe_multi_func_3_result"); + + ASSERT_EQ(skel->bss->uretprobe_multi_func_1_result, 2, "uretprobe_multi_func_1_result"); + ASSERT_EQ(skel->bss->uretprobe_multi_func_2_result, 2, "uretprobe_multi_func_2_result"); + ASSERT_EQ(skel->bss->uretprobe_multi_func_3_result, 2, "uretprobe_multi_func_3_result"); + + ASSERT_EQ(skel->bss->uprobe_multi_sleep_result, 6, "uprobe_multi_sleep_result"); +} + +static void test_skel_api(void) +{ + struct uprobe_multi *skel = NULL; + int err; + + skel = uprobe_multi__open_and_load(); + if (!ASSERT_OK_PTR(skel, "uprobe_multi__open_and_load")) + goto cleanup; + + err = uprobe_multi__attach(skel); + if (!ASSERT_OK(err, "uprobe_multi__attach")) + goto cleanup; + + uprobe_multi_test_run(skel); + +cleanup: + uprobe_multi__destroy(skel); +} + +void test_uprobe_multi_test(void) +{ + if (test__start_subtest("skel_api")) + test_skel_api(); +} diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi.c b/tools/testing/selftests/bpf/progs/uprobe_multi.c new file mode 100644 index 000000000000..1eeb9b7b9cad --- /dev/null +++ b/tools/testing/selftests/bpf/progs/uprobe_multi.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +__u64 uprobe_multi_func_1_addr = 0; +__u64 uprobe_multi_func_2_addr = 0; +__u64 uprobe_multi_func_3_addr = 0; + +__u64 uprobe_multi_func_1_result = 0; +__u64 uprobe_multi_func_2_result = 0; +__u64 uprobe_multi_func_3_result = 0; + +__u64 uretprobe_multi_func_1_result = 0; +__u64 uretprobe_multi_func_2_result = 0; +__u64 uretprobe_multi_func_3_result = 0; + +__u64 uprobe_multi_sleep_result = 0; + +int pid = 0; +bool test_cookie = false; +void *user_ptr = 0; + +static __always_inline bool verify_sleepable_user_copy(void) +{ + char data[9]; + + bpf_copy_from_user(data, sizeof(data), user_ptr); + return bpf_strncmp(data, sizeof(data), "test_data") == 0; +} + +static void uprobe_multi_check(void *ctx, bool is_return, bool is_sleep) +{ + if (bpf_get_current_pid_tgid() >> 32 != pid) + return; + + __u64 cookie = test_cookie ? bpf_get_attach_cookie(ctx) : 0; + __u64 addr = bpf_get_func_ip(ctx); + +#define SET(__var, __addr, __cookie) ({ \ + if (addr == __addr && \ + (!test_cookie || (cookie == __cookie))) \ + __var += 1; \ +}) + + if (is_return) { + SET(uretprobe_multi_func_1_result, uprobe_multi_func_1_addr, 2); + SET(uretprobe_multi_func_2_result, uprobe_multi_func_2_addr, 3); + SET(uretprobe_multi_func_3_result, uprobe_multi_func_3_addr, 1); + } else { + SET(uprobe_multi_func_1_result, uprobe_multi_func_1_addr, 3); + SET(uprobe_multi_func_2_result, uprobe_multi_func_2_addr, 1); + SET(uprobe_multi_func_3_result, uprobe_multi_func_3_addr, 2); + } + +#undef SET + + if (is_sleep && verify_sleepable_user_copy()) + uprobe_multi_sleep_result += 1; +} + +SEC("uprobe.multi//proc/self/exe:uprobe_multi_func_*") +int test_uprobe(struct pt_regs *ctx) +{ + uprobe_multi_check(ctx, false, false); + return 0; +} + +SEC("uretprobe.multi//proc/self/exe:uprobe_multi_func_*") +int test_uretprobe(struct pt_regs *ctx) +{ + uprobe_multi_check(ctx, true, false); + return 0; +} + +SEC("uprobe.multi.s//proc/self/exe:uprobe_multi_func_*") +int test_uprobe_sleep(struct pt_regs *ctx) +{ + uprobe_multi_check(ctx, false, true); + return 0; +} + +SEC("uretprobe.multi.s//proc/self/exe:uprobe_multi_func_*") +int test_uretprobe_sleep(struct pt_regs *ctx) +{ + uprobe_multi_check(ctx, true, true); + return 0; +} From patchwork Tue Jun 20 08:35:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285347 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2486BA92D for ; Tue, 20 Jun 2023 08:38:31 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 75B1BC433C0; Tue, 20 Jun 2023 08:38:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250311; bh=0Unlua6hzVhXFpprqGf3cymjRZWdbiFNWGCDic36H/U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dm+xGBSUuktF2U9xjhIx4h4KxYZCf/nns8Nykk6TMKAAhbSZcdYASJJ/eZYWu4GVQ kmo0QOdYJoXHDv6NIkOPhezbXYtwMRnXy9hW1Rfy1RfpdNVNU1yg1grhGbAMM8dRfD xzq6C892JkjKZvlkbHUIy0/73F3FYMFDSRIpMqbRLkwBptrlDBuX602AP4ybMuZ6Zh 1mQg7ByPFHOi0N4IJ78qAF8LdV6YbIS1P6YqvZsDWYTtqEPVsEb0pTbCAKo7C0yAB8 TxYnOL5/wNihfsAtaEmrJus3S7nqE3wTlVZcH1+ZuTptJwoESwqxQbzFLDNPVdiZWr GOCgk6g7m0ovQ== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 16/24] selftests/bpf: Add uprobe_multi api test Date: Tue, 20 Jun 2023 10:35:42 +0200 Message-ID: <20230620083550.690426-17-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding uprobe_multi test for bpf_program__attach_uprobe_multi_opts attach function. Testing attachment using glob patterns and via bpf_uprobe_multi_opts paths/syms fields. Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c index 5cd1116bbb62..28b8e8d451fb 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -69,8 +69,79 @@ static void test_skel_api(void) uprobe_multi__destroy(skel); } +static void +test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi_opts *opts) +{ + struct bpf_link *link1 = NULL, *link2 = NULL; + struct bpf_link *link3 = NULL, *link4 = NULL; + struct uprobe_multi *skel = NULL; + + skel = uprobe_multi__open_and_load(); + if (!ASSERT_OK_PTR(skel, "uprobe_multi__open_and_load")) + goto cleanup; + + opts->retprobe = false; + link1 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe, -1, + binary, pattern, opts); + if (!ASSERT_OK_PTR(link1, "bpf_program__attach_uprobe_multi_opts")) + goto cleanup; + + opts->retprobe = true; + link2 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uretprobe, -1, + binary, pattern, opts); + if (!ASSERT_OK_PTR(link2, "bpf_program__attach_uprobe_multi_opts_retprobe")) + goto cleanup; + + opts->retprobe = false; + link3 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe_sleep, -1, + binary, pattern, opts); + if (!ASSERT_OK_PTR(link1, "bpf_program__attach_uprobe_multi_opts")) + goto cleanup; + + opts->retprobe = true; + link4 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uretprobe_sleep, -1, + binary, pattern, opts); + if (!ASSERT_OK_PTR(link2, "bpf_program__attach_uprobe_multi_opts_retprobe")) + goto cleanup; + + uprobe_multi_test_run(skel); + +cleanup: + bpf_link__destroy(link4); + bpf_link__destroy(link3); + bpf_link__destroy(link2); + bpf_link__destroy(link1); + uprobe_multi__destroy(skel); +} + +static void test_attach_api_pattern(void) +{ + LIBBPF_OPTS(bpf_uprobe_multi_opts, opts); + + test_attach_api("/proc/self/exe", "uprobe_multi_func_*", &opts); + test_attach_api("/proc/self/exe", "uprobe_multi_func_?", &opts); +} + +static void test_attach_api_syms(void) +{ + LIBBPF_OPTS(bpf_uprobe_multi_opts, opts); + const char *syms[3] = { + "uprobe_multi_func_1", + "uprobe_multi_func_2", + "uprobe_multi_func_3", + }; + + opts.syms = syms; + opts.cnt = ARRAY_SIZE(syms); + test_attach_api("/proc/self/exe", NULL, &opts); +} + void test_uprobe_multi_test(void) { if (test__start_subtest("skel_api")) test_skel_api(); + if (test__start_subtest("attach_api_pattern")) + test_attach_api_pattern(); + if (test__start_subtest("attach_api_syms")) + test_attach_api_syms(); } From patchwork Tue Jun 20 08:35:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285348 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B6F2D10E5 for ; Tue, 20 Jun 2023 08:38:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 15E14C433C8; Tue, 20 Jun 2023 08:38:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250320; bh=EnCd4HGqaecttdTETsz4c4GV/EFd/kNZLvgsLPAASxw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=s3hvILlSuNNEuHLXaYers9Yj+o3spz1sMMvZu3aAvzse9GLPlVQOc9kzlpKGj/zne nSj0HyntnH0a5pE78JHHHjiJ7nlzPztaeX7OVuuzSAsFCf5ud7U5PRHg1+adevZDk2 DGyf68TJ5N/HIU1zs3FoqkOVDJlfF/FJlEj7wKahgTIy9BnKrJjPVZmfaCkqfKlaH6 eVjMl9JIaS7cekXQZZr+Zm1xYFjHZ/DgT8RY/IMElB0I7OoRdBq2xHlYEGArKPQWj3 mNSZFWBGmAzaq1MLd9elbTNCKlFbwfH/kBEMwbuvkHAwjbZS9p1b6aTUkFyCcEIUth c2yq8sfBPhjBw== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 17/24] selftests/bpf: Add uprobe_multi link test Date: Tue, 20 Jun 2023 10:35:43 +0200 Message-ID: <20230620083550.690426-18-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding uprobe_multi test for bpf_link_create attach function. Testing attachment using the struct bpf_link_create_opts. Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c index 28b8e8d451fb..fb5247a86559 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -3,6 +3,7 @@ #include #include #include "uprobe_multi.skel.h" +#include "bpf/libbpf_internal.h" static char test_data[] = "test_data"; @@ -136,6 +137,71 @@ static void test_attach_api_syms(void) test_attach_api("/proc/self/exe", NULL, &opts); } +static void test_link_api(void) +{ + int prog_fd, link1_fd = -1, link2_fd = -1, link3_fd = -1, link4_fd = -1; + LIBBPF_OPTS(bpf_link_create_opts, opts); + const char *path = "/proc/self/exe"; + struct uprobe_multi *skel = NULL; + unsigned long *offsets = NULL; + const char *syms[3] = { + "uprobe_multi_func_1", + "uprobe_multi_func_2", + "uprobe_multi_func_3", + }; + int err; + + err = elf_find_multi_func_offset(path, 3, syms, (unsigned long **) &offsets); + if (!ASSERT_OK(err, "elf_find_multi_func_offset")) + return; + + opts.uprobe_multi.path = path; + opts.uprobe_multi.offsets = offsets; + opts.uprobe_multi.cnt = ARRAY_SIZE(syms); + + skel = uprobe_multi__open_and_load(); + if (!ASSERT_OK_PTR(skel, "uprobe_multi__open_and_load")) + goto cleanup; + + opts.kprobe_multi.flags = 0; + prog_fd = bpf_program__fd(skel->progs.test_uprobe); + link1_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts); + if (!ASSERT_GE(link1_fd, 0, "link1_fd")) + goto cleanup; + + opts.kprobe_multi.flags = BPF_F_UPROBE_MULTI_RETURN; + prog_fd = bpf_program__fd(skel->progs.test_uretprobe); + link2_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts); + if (!ASSERT_GE(link2_fd, 0, "link2_fd")) + goto cleanup; + + opts.kprobe_multi.flags = 0; + prog_fd = bpf_program__fd(skel->progs.test_uprobe_sleep); + link3_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts); + if (!ASSERT_GE(link1_fd, 0, "link3_fd")) + goto cleanup; + + opts.kprobe_multi.flags = BPF_F_UPROBE_MULTI_RETURN; + prog_fd = bpf_program__fd(skel->progs.test_uretprobe_sleep); + link4_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts); + if (!ASSERT_GE(link2_fd, 0, "link4_fd")) + goto cleanup; + uprobe_multi_test_run(skel); + +cleanup: + if (link1_fd >= 0) + close(link1_fd); + if (link2_fd >= 0) + close(link2_fd); + if (link3_fd >= 0) + close(link3_fd); + if (link4_fd >= 0) + close(link4_fd); + + uprobe_multi__destroy(skel); + free(offsets); +} + void test_uprobe_multi_test(void) { if (test__start_subtest("skel_api")) @@ -144,4 +210,6 @@ void test_uprobe_multi_test(void) test_attach_api_pattern(); if (test__start_subtest("attach_api_syms")) test_attach_api_syms(); + if (test__start_subtest("link_api")) + test_link_api(); } From patchwork Tue Jun 20 08:35:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285349 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61CE64400 for ; Tue, 20 Jun 2023 08:38:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B5001C433C8; Tue, 20 Jun 2023 08:38:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250330; bh=312L5F6cdVsRkgnYrkxOgjWdtvKQGM5SNUZWfdSMF+k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EnyF1yLFSCxyMz1ChDsUzI1o71JA3lhY3kJVSwcMKQHKXssKATItoSMd4+yjYapee 3cdaPIOr1n3bodtK4XyMbKTiTSqQ/zS75l2ZSvI6qvo/ihooejmm8YlFohP8n3TXes DDQr2fjpvWsyBmpSYL/yUi/WNzenAsLSfQ3RpCgfmGjkd6ofQTC6UTxH98pki6Aidm 3XV+hasj9XPLMim2x/jmhix5rlT0QAUFuZkrMxr+WdrW+iL+eaQVOuHuzGFYKUQAuM HqTKh5nkF+UdmfB1wVLjfNo3MRwSrRovU6R7Nf39P7RGZ88MLx5HUpX70p/m9YBb4+ mHNkgkgGvgMfg== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 18/24] selftests/bpf: Add uprobe_multi test program Date: Tue, 20 Jun 2023 10:35:44 +0200 Message-ID: <20230620083550.690426-19-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding uprobe_multi test program that defines 50k uprobe_multi_func_* functions and will serve as attach point for uprobe_multi bench test in following patch. Signed-off-by: Jiri Olsa --- tools/testing/selftests/bpf/Makefile | 5 ++ tools/testing/selftests/bpf/uprobe_multi.c | 53 ++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tools/testing/selftests/bpf/uprobe_multi.c diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 538df8fb8c42..26ecdd117f71 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -567,6 +567,7 @@ TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \ $(OUTPUT)/liburandom_read.so \ $(OUTPUT)/xdp_synproxy \ $(OUTPUT)/sign-file \ + $(OUTPUT)/uprobe_multi \ ima_setup.sh \ verify_sig_setup.sh \ $(wildcard progs/btf_dump_test_case_*.c) \ @@ -670,6 +671,10 @@ $(OUTPUT)/veristat: $(OUTPUT)/veristat.o $(call msg,BINARY,,$@) $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@ +$(OUTPUT)/uprobe_multi: uprobe_multi.c + $(call msg,BINARY,,$@) + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ + EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ prog_tests/tests.h map_tests/tests.h verifier/tests.h \ feature bpftool \ diff --git a/tools/testing/selftests/bpf/uprobe_multi.c b/tools/testing/selftests/bpf/uprobe_multi.c new file mode 100644 index 000000000000..115a7f6cebfa --- /dev/null +++ b/tools/testing/selftests/bpf/uprobe_multi.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#define __PASTE(a, b) a##b +#define PASTE(a, b) __PASTE(a, b) + +#define NAME(name, idx) PASTE(name, idx) + +#define DEF(name, idx) int NAME(name, idx)(void) { return 0; } +#define CALL(name, idx) NAME(name, idx)(); + +#define F(body, name, idx) body(name, idx) + +#define F10(body, name, idx) \ + F(body, PASTE(name, idx), 0) F(body, PASTE(name, idx), 1) F(body, PASTE(name, idx), 2) \ + F(body, PASTE(name, idx), 3) F(body, PASTE(name, idx), 4) F(body, PASTE(name, idx), 5) \ + F(body, PASTE(name, idx), 6) F(body, PASTE(name, idx), 7) F(body, PASTE(name, idx), 8) \ + F(body, PASTE(name, idx), 9) + +#define F100(body, name, idx) \ + F10(body, PASTE(name, idx), 0) F10(body, PASTE(name, idx), 1) F10(body, PASTE(name, idx), 2) \ + F10(body, PASTE(name, idx), 3) F10(body, PASTE(name, idx), 4) F10(body, PASTE(name, idx), 5) \ + F10(body, PASTE(name, idx), 6) F10(body, PASTE(name, idx), 7) F10(body, PASTE(name, idx), 8) \ + F10(body, PASTE(name, idx), 9) + +#define F1000(body, name, idx) \ + F100(body, PASTE(name, idx), 0) F100(body, PASTE(name, idx), 1) F100(body, PASTE(name, idx), 2) \ + F100(body, PASTE(name, idx), 3) F100(body, PASTE(name, idx), 4) F100(body, PASTE(name, idx), 5) \ + F100(body, PASTE(name, idx), 6) F100(body, PASTE(name, idx), 7) F100(body, PASTE(name, idx), 8) \ + F100(body, PASTE(name, idx), 9) + +#define F10000(body, name, idx) \ + F1000(body, PASTE(name, idx), 0) F1000(body, PASTE(name, idx), 1) F1000(body, PASTE(name, idx), 2) \ + F1000(body, PASTE(name, idx), 3) F1000(body, PASTE(name, idx), 4) F1000(body, PASTE(name, idx), 5) \ + F1000(body, PASTE(name, idx), 6) F1000(body, PASTE(name, idx), 7) F1000(body, PASTE(name, idx), 8) \ + F1000(body, PASTE(name, idx), 9) + +F10000(DEF, uprobe_multi_func_, 0) +F10000(DEF, uprobe_multi_func_, 1) +F10000(DEF, uprobe_multi_func_, 2) +F10000(DEF, uprobe_multi_func_, 3) +F10000(DEF, uprobe_multi_func_, 4) + +int main(void) +{ + F10000(CALL, uprobe_multi_func_, 0) + F10000(CALL, uprobe_multi_func_, 1) + F10000(CALL, uprobe_multi_func_, 2) + F10000(CALL, uprobe_multi_func_, 3) + F10000(CALL, uprobe_multi_func_, 4) + return 0; +} From patchwork Tue Jun 20 08:35:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285350 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B30E4400 for ; Tue, 20 Jun 2023 08:39:00 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6A7EAC433C8; Tue, 20 Jun 2023 08:38:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250339; bh=mXFoVKa6sHZeOCEruN48i74RWoq+omOMYLWIsZrOiN8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y0TARv1//4gsyTqH+OPWX05YvvuEgy/B0hBF+hOCnPasavDT6LooAGkufpgMSWsZ2 yBB96e/VzOftDsuL9loSMVQZ3iwOZibS+TUp6/h5dk2Ief5n4+J9kVt1QiHDZ1+nXU EZrNjVIkzTpNeJjbyMg2o+XVp8dGoHRICx7wDSvmHBykgoWFfV8LKwg3qoVteQF668 VNZASMCD/Imzl1WF5YqiCZJ+aUuAODBbhyZJpHmhmrhz4of9R2kd8ICUCFtiPquUlD Et3O3/GCjKiBvozjEQbSBw/5cj8yGXjxZ4MMLKPmc7pPaM9BgTKK2JvUFxFCV3QvdJ MqvGA2fii4i9A== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 19/24] selftests/bpf: Add uprobe_multi bench test Date: Tue, 20 Jun 2023 10:35:45 +0200 Message-ID: <20230620083550.690426-20-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding test that attaches 50k uprobes in uprobe_multi binary. After the attach is done we run the binary and make sure we get proper amount of hits. Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c | 56 +++++++++++++++++++ .../selftests/bpf/progs/uprobe_multi.c | 9 +++ 2 files changed, 65 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c index fb5247a86559..9a34c754f1ad 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -202,6 +202,60 @@ static void test_link_api(void) free(offsets); } +static inline __u64 get_time_ns(void) +{ + struct timespec t; + + clock_gettime(CLOCK_MONOTONIC, &t); + return (__u64) t.tv_sec * 1000000000 + t.tv_nsec; +} + +static void test_bench_attach_uprobe(void) +{ + long attach_start_ns, attach_end_ns; + long detach_start_ns, detach_end_ns; + double attach_delta, detach_delta; + struct uprobe_multi *skel = NULL; + struct bpf_program *prog; + int err; + + skel = uprobe_multi__open(); + if (!ASSERT_OK_PTR(skel, "uprobe_multi__open")) + goto cleanup; + + bpf_object__for_each_program(prog, skel->obj) + bpf_program__set_autoload(prog, false); + + bpf_program__set_autoload(skel->progs.test_uprobe_bench, true); + + err = uprobe_multi__load(skel); + if (!ASSERT_EQ(err, 0, "uprobe_multi__load")) + goto cleanup; + + attach_start_ns = get_time_ns(); + + err = uprobe_multi__attach(skel); + if (!ASSERT_OK(err, "uprobe_multi__attach")) + goto cleanup; + + attach_end_ns = get_time_ns(); + + system("./uprobe_multi"); + + ASSERT_EQ(skel->bss->count, 50000, "uprobes_count"); + +cleanup: + detach_start_ns = get_time_ns(); + uprobe_multi__destroy(skel); + detach_end_ns = get_time_ns(); + + attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0; + detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0; + + printf("%s: attached in %7.3lfs\n", __func__, attach_delta); + printf("%s: detached in %7.3lfs\n", __func__, detach_delta); +} + void test_uprobe_multi_test(void) { if (test__start_subtest("skel_api")) @@ -212,4 +266,6 @@ void test_uprobe_multi_test(void) test_attach_api_syms(); if (test__start_subtest("link_api")) test_link_api(); + if (test__start_subtest("bench_uprobe")) + test_bench_attach_uprobe(); } diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi.c b/tools/testing/selftests/bpf/progs/uprobe_multi.c index 1eeb9b7b9cad..cd73139dc881 100644 --- a/tools/testing/selftests/bpf/progs/uprobe_multi.c +++ b/tools/testing/selftests/bpf/progs/uprobe_multi.c @@ -89,3 +89,12 @@ int test_uretprobe_sleep(struct pt_regs *ctx) uprobe_multi_check(ctx, true, true); return 0; } + +int count; + +SEC("?uprobe.multi/./uprobe_multi:uprobe_multi_func_*") +int test_uprobe_bench(struct pt_regs *ctx) +{ + count++; + return 0; +} From patchwork Tue Jun 20 08:35:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285351 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A93E4400 for ; Tue, 20 Jun 2023 08:39:09 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 37B78C433C0; Tue, 20 Jun 2023 08:39:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250349; bh=OZBoXrZysK4B99fKBzHRD2cWEURhqsOHDKaQrdMhFHE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Wf0ozX25wrktBMYJB0x4EDfMXV8ukgx46BQxfjGGKcYwRLTH6Q8DnWqFBeHQrGqQ3 xfpYBHSFl4k7svlb6+sYaRVclgX+w+w6qBKb/e0BvQzmwyuphzgvFKzxrI2TQXMyds t1lUgvHqsjqIildqW7xf8bqwYvaDitXdNzL/rGJ+UKkIZvaTX1aP73lAK79yLUfL0O FnnG48bH8J85B4hqQ1A8iGI77uHdEXP28zWGbBJuRbBvhbl8RGcbbMb9jeX321l3KI 2siAULYOJZqxnsfASBn9QnR77ZItj0A7D0sqtoPMzwKSj2vs5ZtkEyH4xcdTzmwtE8 3dphGdTKqlY5Q== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 20/24] selftests/bpf: Add usdt_multi test program Date: Tue, 20 Jun 2023 10:35:46 +0200 Message-ID: <20230620083550.690426-21-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding usdt_multi test program that defines 50k usdts and will serve as attach point for uprobe_multi usdt bench test in following patch. Signed-off-by: Jiri Olsa --- tools/testing/selftests/bpf/Makefile | 5 +++++ tools/testing/selftests/bpf/usdt_multi.c | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tools/testing/selftests/bpf/usdt_multi.c diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 26ecdd117f71..135b909f7bc9 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -568,6 +568,7 @@ TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \ $(OUTPUT)/xdp_synproxy \ $(OUTPUT)/sign-file \ $(OUTPUT)/uprobe_multi \ + $(OUTPUT)/usdt_multi \ ima_setup.sh \ verify_sig_setup.sh \ $(wildcard progs/btf_dump_test_case_*.c) \ @@ -675,6 +676,10 @@ $(OUTPUT)/uprobe_multi: uprobe_multi.c $(call msg,BINARY,,$@) $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ +$(OUTPUT)/usdt_multi: usdt_multi.c + $(call msg,BINARY,,$@) + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ + EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ prog_tests/tests.h map_tests/tests.h verifier/tests.h \ feature bpftool \ diff --git a/tools/testing/selftests/bpf/usdt_multi.c b/tools/testing/selftests/bpf/usdt_multi.c new file mode 100644 index 000000000000..fedf856bad2b --- /dev/null +++ b/tools/testing/selftests/bpf/usdt_multi.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#define PROBE STAP_PROBE(test, usdt); + +#define PROBE10 PROBE PROBE PROBE PROBE PROBE \ + PROBE PROBE PROBE PROBE PROBE +#define PROBE100 PROBE10 PROBE10 PROBE10 PROBE10 PROBE10 \ + PROBE10 PROBE10 PROBE10 PROBE10 PROBE10 +#define PROBE1000 PROBE100 PROBE100 PROBE100 PROBE100 PROBE100 \ + PROBE100 PROBE100 PROBE100 PROBE100 PROBE100 +#define PROBE10000 PROBE1000 PROBE1000 PROBE1000 PROBE1000 PROBE1000 \ + PROBE1000 PROBE1000 PROBE1000 PROBE1000 PROBE1000 + +int main(void) +{ + PROBE10000 + PROBE10000 + PROBE10000 + PROBE10000 + PROBE10000 + return 0; +} From patchwork Tue Jun 20 08:35:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285352 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 876B84400 for ; Tue, 20 Jun 2023 08:39:19 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4839C433C8; Tue, 20 Jun 2023 08:39:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250359; bh=BfNxy5P13iMbE7Fn3YYIfXUnUos/78zl3tKv+nobwYM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Gmla9RqpTj236Js133DeDX4/3Eblw6mp9Gt6NNBGJWp01/Mn/DRCG4Q+TEHpHL9Xj aJ4IgtCciK110o4RVb4kZ70nBI2U132NMSKee7dav/AyjYnmxFjOjSj4S+HQKzG6so zFzyM8maqazfWw55k39N90GsYn8vLlP+9Hsl9Wv3VoFoQPMcaANaEE/YdSZKdoIsOC PC7vjrkUM9z/pcuoq5pYkIddNUAHYpAirejW0hgWrjdwJCjXT5yC+SOjaV+fzWZMZ5 PEdJto+u5Cz5dCSLEEMzS6mHSSujHRft9nsh+v0sN6v561VuaA7Hkfpx4GH7c5LJaa +UC2UDMmWfVSQ== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 21/24] selftests/bpf: Add usdt_multi bench test Date: Tue, 20 Jun 2023 10:35:47 +0200 Message-ID: <20230620083550.690426-22-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding test that attaches 50k usdt probes in usdt_multi binary. After the attach is done we run the binary and make sure we get proper amount of hits. With current uprobes: # perf stat --null ./test_progs -n 254/6 #254/6 uprobe_multi_test/bench_usdt:OK #254 uprobe_multi_test:OK Summary: 1/1 PASSED, 0 SKIPPED, 0 FAILED Performance counter stats for './test_progs -n 254/6': 1353.659680562 seconds time elapsed With uprobe_multi link: # perf stat --null ./test_progs -n 254/6 #254/6 uprobe_multi_test/bench_usdt:OK #254 uprobe_multi_test:OK Summary: 1/1 PASSED, 0 SKIPPED, 0 FAILED Performance counter stats for './test_progs -n 254/6': 0.322046364 seconds time elapsed Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c | 50 +++++++++++++++++++ .../selftests/bpf/progs/uprobe_multi_usdt.c | 16 ++++++ 2 files changed, 66 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/uprobe_multi_usdt.c diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c index 9a34c754f1ad..a9d5a1773407 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -4,6 +4,7 @@ #include #include "uprobe_multi.skel.h" #include "bpf/libbpf_internal.h" +#include "uprobe_multi_usdt.skel.h" static char test_data[] = "test_data"; @@ -256,6 +257,53 @@ static void test_bench_attach_uprobe(void) printf("%s: detached in %7.3lfs\n", __func__, detach_delta); } +static void test_bench_attach_usdt(void) +{ + struct uprobe_multi_usdt *skel = NULL; + long attach_start_ns, attach_end_ns; + long detach_start_ns, detach_end_ns; + double attach_delta, detach_delta; + struct bpf_program *prog; + int err; + + skel = uprobe_multi_usdt__open(); + if (!ASSERT_OK_PTR(skel, "uprobe_multi__open")) + goto cleanup; + + bpf_object__for_each_program(prog, skel->obj) + bpf_program__set_autoload(prog, false); + + bpf_program__set_autoload(skel->progs.usdt0, true); + + err = uprobe_multi_usdt__load(skel); + if (!ASSERT_EQ(err, 0, "uprobe_multi_usdt__load")) + goto cleanup; + + attach_start_ns = get_time_ns(); + + skel->links.usdt0 = bpf_program__attach_usdt(skel->progs.usdt0, -1, "./usdt_multi", + "test", "usdt", NULL); + if (!ASSERT_OK_PTR(skel->links.usdt0, "bpf_program__attach_usdt")) + goto cleanup; + + attach_end_ns = get_time_ns(); + + system("./usdt_multi"); + + ASSERT_EQ(skel->bss->count, 50000, "usdt_count"); + +cleanup: + detach_start_ns = get_time_ns(); + uprobe_multi_usdt__destroy(skel); + detach_end_ns = get_time_ns(); + + attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0; + detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0; + + printf("%s: attached in %7.3lfs\n", __func__, attach_delta); + printf("%s: detached in %7.3lfs\n", __func__, detach_delta); +} + void test_uprobe_multi_test(void) { if (test__start_subtest("skel_api")) @@ -268,4 +316,6 @@ void test_uprobe_multi_test(void) test_link_api(); if (test__start_subtest("bench_uprobe")) test_bench_attach_uprobe(); + if (test__start_subtest("bench_usdt")) + test_bench_attach_usdt(); } diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi_usdt.c b/tools/testing/selftests/bpf/progs/uprobe_multi_usdt.c new file mode 100644 index 000000000000..9e1c33d0bd2f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/uprobe_multi_usdt.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" +#include +#include + +char _license[] SEC("license") = "GPL"; + +int count; + +SEC("usdt") +int usdt0(struct pt_regs *ctx) +{ + count++; + return 0; +} From patchwork Tue Jun 20 08:35:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285353 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96F054400 for ; Tue, 20 Jun 2023 08:39:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 93143C433C0; Tue, 20 Jun 2023 08:39:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250369; bh=kZy5bTsbbvLVgAHgZbnAdm5n4EFCVtfh0fohPp/Ix+4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lhdEH0NdaP2fTsgpEo7cRSCaRt9MbAx/V6ZCNjFQlQeaktmDf7OQp99wbQw4p499t wAuExOT6ejEO5VM0qw4Is+2iMqhEBhOI+cW8XTF+Sz32TG7Q64mHKWRfAWkJVYo0Uq lMwgwzI9uKDmfa5+OXAOAy22nJrcyjTSYwiEj1vzp7TbvsUIpeRvwdUscLaRTKDaoF E0A1oUPZfF1KHQLi2RBtnHtgfUVe8veW05Jhynqht4Bz4JExjLqYMDHQlbxRQjbI5k zgT8A1o3NNCQ7qE34oaLCzG0Vl25nwYubP75krvN511Kd43dAikgSovIs1zMLfYwS+ iGEoTuBmk++hA== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 22/24] selftests/bpf: Add uprobe_multi cookie test Date: Tue, 20 Jun 2023 10:35:48 +0200 Message-ID: <20230620083550.690426-23-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Adding test for cookies setup/retrieval in uprobe_link uprobes and making sure bpf_get_attach_cookie works properly. Signed-off-by: Jiri Olsa --- .../selftests/bpf/prog_tests/bpf_cookie.c | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c b/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c index 26b2d1bffdfd..47f692a64cef 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c @@ -11,6 +11,7 @@ #include #include "test_bpf_cookie.skel.h" #include "kprobe_multi.skel.h" +#include "uprobe_multi.skel.h" /* uprobe attach point */ static noinline void trigger_func(void) @@ -239,6 +240,81 @@ static void kprobe_multi_attach_api_subtest(void) bpf_link__destroy(link1); kprobe_multi__destroy(skel); } + +/* defined in prog_tests/uprobe_multi_test.c */ +void uprobe_multi_func_1(void); +void uprobe_multi_func_2(void); +void uprobe_multi_func_3(void); + +static void uprobe_multi_test_run(struct uprobe_multi *skel) +{ + skel->bss->uprobe_multi_func_1_addr = (__u64) uprobe_multi_func_1; + skel->bss->uprobe_multi_func_2_addr = (__u64) uprobe_multi_func_2; + skel->bss->uprobe_multi_func_3_addr = (__u64) uprobe_multi_func_3; + + skel->bss->pid = getpid(); + skel->bss->test_cookie = true; + + uprobe_multi_func_1(); + uprobe_multi_func_2(); + uprobe_multi_func_3(); + + ASSERT_EQ(skel->bss->uprobe_multi_func_1_result, 1, "uprobe_multi_func_1_result"); + ASSERT_EQ(skel->bss->uprobe_multi_func_2_result, 1, "uprobe_multi_func_2_result"); + ASSERT_EQ(skel->bss->uprobe_multi_func_3_result, 1, "uprobe_multi_func_3_result"); + + ASSERT_EQ(skel->bss->uretprobe_multi_func_1_result, 1, "uretprobe_multi_func_1_result"); + ASSERT_EQ(skel->bss->uretprobe_multi_func_2_result, 1, "uretprobe_multi_func_2_result"); + ASSERT_EQ(skel->bss->uretprobe_multi_func_3_result, 1, "uretprobe_multi_func_3_result"); +} + +static void uprobe_multi_attach_api_subtest(void) +{ + struct bpf_link *link1 = NULL, *link2 = NULL; + struct uprobe_multi *skel = NULL; + LIBBPF_OPTS(bpf_uprobe_multi_opts, opts); + const char *syms[3] = { + "uprobe_multi_func_1", + "uprobe_multi_func_2", + "uprobe_multi_func_3", + }; + __u64 cookies[3]; + + cookies[0] = 3; /* uprobe_multi_func_1 */ + cookies[1] = 1; /* uprobe_multi_func_2 */ + cookies[2] = 2; /* uprobe_multi_func_3 */ + + opts.syms = syms; + opts.cnt = ARRAY_SIZE(syms); + opts.cookies = &cookies[0]; + + skel = uprobe_multi__open_and_load(); + if (!ASSERT_OK_PTR(skel, "uprobe_multi")) + goto cleanup; + + link1 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe, -1, + "/proc/self/exe", NULL, &opts); + if (!ASSERT_OK_PTR(link1, "bpf_program__attach_uprobe_multi_opts")) + goto cleanup; + + cookies[0] = 2; /* uprobe_multi_func_1 */ + cookies[1] = 3; /* uprobe_multi_func_2 */ + cookies[2] = 1; /* uprobe_multi_func_3 */ + + opts.retprobe = true; + link2 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uretprobe, -1, + "/proc/self/exe", NULL, &opts); + if (!ASSERT_OK_PTR(link2, "bpf_program__attach_uprobe_multi_opts_retprobe")) + goto cleanup; + + uprobe_multi_test_run(skel); + +cleanup: + bpf_link__destroy(link2); + bpf_link__destroy(link1); + uprobe_multi__destroy(skel); +} + static void uprobe_subtest(struct test_bpf_cookie *skel) { DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts); @@ -515,6 +591,8 @@ void test_bpf_cookie(void) kprobe_multi_attach_api_subtest(); if (test__start_subtest("uprobe")) uprobe_subtest(skel); + if (test__start_subtest("multi_uprobe_attach_api")) + uprobe_multi_attach_api_subtest(); if (test__start_subtest("tracepoint")) tp_subtest(skel); if (test__start_subtest("perf_event")) From patchwork Tue Jun 20 08:35:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285354 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B538BA5E for ; Tue, 20 Jun 2023 08:39:39 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5125CC433C0; Tue, 20 Jun 2023 08:39:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250378; bh=C9fj0XTGA3jjWVIvAT6IjRtMLUYrz6Od3vyBHjYLMPg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QFgB+jj/MdYVUXjLlmfKug6hpzdamkDvC+GsKslVnMWOnu6a+Jr9GgCtzV2j8AokZ T51QAEpoduwZDBaJxqW078GslCV9xwIu21PVt2b9UGcTT0UZb7YVzyGPheZbrHfEjS Tf4uVuFORZF6bLpxQHtTPDX5HUEnxD5Prcv+KPG+Jm56MrxnHs1t5VrlghYYI/oI38 HCsf55XNrRlFO4deZGhJhdI3YevmJPQ4909zjp770pdXe3m2slrrFF1y57QAsp92Am goa3xefirYltUPmXBDLgzWg7AuWTFUKoDvl3QcLRJll6a9abI+AoIKFBta1Ala/EPr Km/8QDezkOHsA== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 23/24] selftests/bpf: Add uprobe_multi pid filter tests Date: Tue, 20 Jun 2023 10:35:49 +0200 Message-ID: <20230620083550.690426-24-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Running api and link tests also with pid filter and checking the probe gets executed only for specific pid. Spawning extra process to trigger attached uprobes and checking we get correct counts from executed programs. Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c | 131 ++++++++++++++++-- .../selftests/bpf/progs/uprobe_multi.c | 6 +- 2 files changed, 125 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c index a9d5a1773407..efa7b5d49940 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -23,14 +23,86 @@ noinline void uprobe_multi_func_3(void) asm volatile (""); } -static void uprobe_multi_test_run(struct uprobe_multi *skel) +struct child { + int go[2]; + int pid; +}; + +static void release_child(struct child *child) +{ + int child_status; + + if (!child) + return; + close(child->go[1]); + close(child->go[0]); + if (child->pid > 0) + waitpid(child->pid, &child_status, 0); +} + +static void kick_child(struct child *child) +{ + char c = 1; + + if (child) { + write(child->go[1], &c, 1); + release_child(child); + } + fflush(NULL); +} + +static struct child *spawn_child(void) +{ + static struct child child; + int err; + int c; + + /* pid filter */ + if (!ASSERT_OK(pipe(child.go), "pipe")) + return NULL; + + child.pid = fork(); + if (child.pid < 0) { + release_child(&child); + return NULL; + } + + /* child */ + if (child.pid == 0) { + close(child.go[1]); + fflush(NULL); + /* wait for parent's kick */ + err = read(child.go[0], &c, 1); + if (!ASSERT_EQ(err, 1, "child_read_pipe")) + exit(err); + + uprobe_multi_func_1(); + uprobe_multi_func_2(); + uprobe_multi_func_3(); + + exit(errno); + } + + return &child; +} + +static void uprobe_multi_test_run(struct uprobe_multi *skel, struct child *child) { skel->bss->uprobe_multi_func_1_addr = (__u64) uprobe_multi_func_1; skel->bss->uprobe_multi_func_2_addr = (__u64) uprobe_multi_func_2; skel->bss->uprobe_multi_func_3_addr = (__u64) uprobe_multi_func_3; skel->bss->user_ptr = test_data; - skel->bss->pid = getpid(); + + /* + * Disable pid check in bpf program if we are pid filter test, + * because the probe should be executed only by child->pid + * passed at the probe attach. + */ + skel->bss->pid = child ? 0 : getpid(); + + if (child) + kick_child(child); /* trigger all probes */ uprobe_multi_func_1(); @@ -50,6 +122,9 @@ static void uprobe_multi_test_run(struct uprobe_multi *skel) ASSERT_EQ(skel->bss->uretprobe_multi_func_3_result, 2, "uretprobe_multi_func_3_result"); ASSERT_EQ(skel->bss->uprobe_multi_sleep_result, 6, "uprobe_multi_sleep_result"); + + if (child) + ASSERT_EQ(skel->bss->child_pid, child->pid, "uprobe_multi_child_pid"); } static void test_skel_api(void) @@ -65,17 +140,19 @@ static void test_skel_api(void) if (!ASSERT_OK(err, "uprobe_multi__attach")) goto cleanup; - uprobe_multi_test_run(skel); + uprobe_multi_test_run(skel, NULL); cleanup: uprobe_multi__destroy(skel); } static void -test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi_opts *opts) +__test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi_opts *opts, + struct child *child) { struct bpf_link *link1 = NULL, *link2 = NULL; struct bpf_link *link3 = NULL, *link4 = NULL; + pid_t pid = child ? child->pid : -1; struct uprobe_multi *skel = NULL; skel = uprobe_multi__open_and_load(); @@ -83,30 +160,30 @@ test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi goto cleanup; opts->retprobe = false; - link1 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe, -1, + link1 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe, pid, binary, pattern, opts); if (!ASSERT_OK_PTR(link1, "bpf_program__attach_uprobe_multi_opts")) goto cleanup; opts->retprobe = true; - link2 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uretprobe, -1, + link2 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uretprobe, pid, binary, pattern, opts); if (!ASSERT_OK_PTR(link2, "bpf_program__attach_uprobe_multi_opts_retprobe")) goto cleanup; opts->retprobe = false; - link3 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe_sleep, -1, + link3 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe_sleep, pid, binary, pattern, opts); if (!ASSERT_OK_PTR(link1, "bpf_program__attach_uprobe_multi_opts")) goto cleanup; opts->retprobe = true; - link4 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uretprobe_sleep, -1, + link4 = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uretprobe_sleep, pid, binary, pattern, opts); if (!ASSERT_OK_PTR(link2, "bpf_program__attach_uprobe_multi_opts_retprobe")) goto cleanup; - uprobe_multi_test_run(skel); + uprobe_multi_test_run(skel, child); cleanup: bpf_link__destroy(link4); @@ -116,6 +193,22 @@ test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi uprobe_multi__destroy(skel); } +static void +test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi_opts *opts) +{ + struct child *child; + + /* no pid filter */ + __test_attach_api(binary, pattern, opts, NULL); + + /* pid filter */ + child = spawn_child(); + if (!child) + return; + + __test_attach_api(binary, pattern, opts, child); +} + static void test_attach_api_pattern(void) { LIBBPF_OPTS(bpf_uprobe_multi_opts, opts); @@ -138,7 +231,7 @@ static void test_attach_api_syms(void) test_attach_api("/proc/self/exe", NULL, &opts); } -static void test_link_api(void) +static void __test_link_api(struct child *child) { int prog_fd, link1_fd = -1, link2_fd = -1, link3_fd = -1, link4_fd = -1; LIBBPF_OPTS(bpf_link_create_opts, opts); @@ -159,6 +252,7 @@ static void test_link_api(void) opts.uprobe_multi.path = path; opts.uprobe_multi.offsets = offsets; opts.uprobe_multi.cnt = ARRAY_SIZE(syms); + opts.uprobe_multi.pid = child ? child->pid : 0; skel = uprobe_multi__open_and_load(); if (!ASSERT_OK_PTR(skel, "uprobe_multi__open_and_load")) @@ -187,7 +281,7 @@ static void test_link_api(void) link4_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts); if (!ASSERT_GE(link2_fd, 0, "link4_fd")) goto cleanup; - uprobe_multi_test_run(skel); + uprobe_multi_test_run(skel, child); cleanup: if (link1_fd >= 0) @@ -203,6 +297,21 @@ static void test_link_api(void) free(offsets); } +void test_link_api(void) +{ + struct child *child; + + /* no pid filter */ + __test_link_api(NULL); + + /* pid filter */ + child = spawn_child(); + if (!child) + return; + + __test_link_api(child); +} + static inline __u64 get_time_ns(void) { struct timespec t; diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi.c b/tools/testing/selftests/bpf/progs/uprobe_multi.c index cd73139dc881..1086312b5d1e 100644 --- a/tools/testing/selftests/bpf/progs/uprobe_multi.c +++ b/tools/testing/selftests/bpf/progs/uprobe_multi.c @@ -21,6 +21,8 @@ __u64 uretprobe_multi_func_3_result = 0; __u64 uprobe_multi_sleep_result = 0; int pid = 0; +int child_pid = 0; + bool test_cookie = false; void *user_ptr = 0; @@ -34,7 +36,9 @@ static __always_inline bool verify_sleepable_user_copy(void) static void uprobe_multi_check(void *ctx, bool is_return, bool is_sleep) { - if (bpf_get_current_pid_tgid() >> 32 != pid) + child_pid = bpf_get_current_pid_tgid() >> 32; + + if (pid && child_pid != pid) return; __u64 cookie = test_cookie ? bpf_get_attach_cookie(ctx) : 0; From patchwork Tue Jun 20 08:35:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Olsa X-Patchwork-Id: 13285355 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B010DAD37 for ; Tue, 20 Jun 2023 08:39:48 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 079AAC433C0; Tue, 20 Jun 2023 08:39:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687250388; bh=L0w8dJO+NL2ZM4gfbTKPBvbNpym8PsvyuP/F+8FI4JI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FSGlpLG73bnORe4pMuC6JQ7vVG09AngbfX7EiYlDFG8bIiaEYQf2P/tB3RUHJgPh4 pgjQCjxWaylYlHb/DaEF+WQp8biuTl0SFGePRe+OQY+awyb9RFOgPK7swK4diaMD80 sqVQxbTmtlh82q3gqMekfL+2eLFsPpXsLoknDxKG1YyZIpN2WeOf98TKkgnpJw7Rn2 lJCRbWbY27z4jxF+bAezSASyHXUCd+sVasTR7v69dzxbGn2+kYEIexPFT2b/Apy7fx E5pkiT4xegXfcHcrCufKkSM3xZPWeuuGA8Iv9xjbA79r99WRJPtTLybesrYEzoXNET EmGfCe4MhWPDw== From: Jiri Olsa To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: bpf@vger.kernel.org, Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo Subject: [PATCHv2 bpf-next 24/24] selftests/bpf: Add extra link to uprobe_multi tests Date: Tue, 20 Jun 2023 10:35:50 +0200 Message-ID: <20230620083550.690426-25-jolsa@kernel.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230620083550.690426-1-jolsa@kernel.org> References: <20230620083550.690426-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Attaching extra program to same functions system wide for api and link tests. This way we can test the pid filter works properly when there's extra system wide consumer on the same uprobe that will trigger the original uprobe handler. We expect to have the same counts as before. Signed-off-by: Jiri Olsa --- .../bpf/prog_tests/uprobe_multi_test.c | 19 +++++++++++++++++++ .../selftests/bpf/progs/uprobe_multi.c | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c index efa7b5d49940..9057a228c12d 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c @@ -153,6 +153,7 @@ __test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_mul struct bpf_link *link1 = NULL, *link2 = NULL; struct bpf_link *link3 = NULL, *link4 = NULL; pid_t pid = child ? child->pid : -1; + struct bpf_link *link_extra = NULL; struct uprobe_multi *skel = NULL; skel = uprobe_multi__open_and_load(); @@ -183,9 +184,16 @@ __test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_mul if (!ASSERT_OK_PTR(link2, "bpf_program__attach_uprobe_multi_opts_retprobe")) goto cleanup; + opts->retprobe = false; + link_extra = bpf_program__attach_uprobe_multi_opts(skel->progs.test_uprobe_extra, -1, + binary, pattern, opts); + if (!ASSERT_OK_PTR(link_extra, "bpf_program__attach_uprobe_multi_opts")) + goto cleanup; + uprobe_multi_test_run(skel, child); cleanup: + bpf_link__destroy(link_extra); bpf_link__destroy(link4); bpf_link__destroy(link3); bpf_link__destroy(link2); @@ -243,6 +251,7 @@ static void __test_link_api(struct child *child) "uprobe_multi_func_2", "uprobe_multi_func_3", }; + int link_extra_fd = -1; int err; err = elf_find_multi_func_offset(path, 3, syms, (unsigned long **) &offsets); @@ -281,6 +290,14 @@ static void __test_link_api(struct child *child) link4_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts); if (!ASSERT_GE(link2_fd, 0, "link4_fd")) goto cleanup; + + opts.kprobe_multi.flags = 0; + opts.uprobe_multi.pid = 0; + prog_fd = bpf_program__fd(skel->progs.test_uprobe_extra); + link_extra_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts); + if (!ASSERT_GE(link_extra_fd, 0, "link_extra_fd")) + goto cleanup; + uprobe_multi_test_run(skel, child); cleanup: @@ -292,6 +309,8 @@ static void __test_link_api(struct child *child) close(link3_fd); if (link4_fd >= 0) close(link4_fd); + if (link_extra_fd >= 0) + close(link_extra_fd); uprobe_multi__destroy(skel); free(offsets); diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi.c b/tools/testing/selftests/bpf/progs/uprobe_multi.c index 1086312b5d1e..8ee957670303 100644 --- a/tools/testing/selftests/bpf/progs/uprobe_multi.c +++ b/tools/testing/selftests/bpf/progs/uprobe_multi.c @@ -102,3 +102,9 @@ int test_uprobe_bench(struct pt_regs *ctx) count++; return 0; } + +SEC("uprobe.multi//proc/self/exe:uprobe_multi_func_*") +int test_uprobe_extra(struct pt_regs *ctx) +{ + return 0; +}