162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/bpf.h>
362306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
462306a36Sopenharmony_ci#include <bpf/bpf_tracing.h>
562306a36Sopenharmony_ci#include <stdbool.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci__u64 uprobe_multi_func_1_addr = 0;
1062306a36Sopenharmony_ci__u64 uprobe_multi_func_2_addr = 0;
1162306a36Sopenharmony_ci__u64 uprobe_multi_func_3_addr = 0;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci__u64 uprobe_multi_func_1_result = 0;
1462306a36Sopenharmony_ci__u64 uprobe_multi_func_2_result = 0;
1562306a36Sopenharmony_ci__u64 uprobe_multi_func_3_result = 0;
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci__u64 uretprobe_multi_func_1_result = 0;
1862306a36Sopenharmony_ci__u64 uretprobe_multi_func_2_result = 0;
1962306a36Sopenharmony_ci__u64 uretprobe_multi_func_3_result = 0;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci__u64 uprobe_multi_sleep_result = 0;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ciint pid = 0;
2462306a36Sopenharmony_ciint child_pid = 0;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cibool test_cookie = false;
2762306a36Sopenharmony_civoid *user_ptr = 0;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic __always_inline bool verify_sleepable_user_copy(void)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	char data[9];
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	bpf_copy_from_user(data, sizeof(data), user_ptr);
3462306a36Sopenharmony_ci	return bpf_strncmp(data, sizeof(data), "test_data") == 0;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic void uprobe_multi_check(void *ctx, bool is_return, bool is_sleep)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	child_pid = bpf_get_current_pid_tgid() >> 32;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (pid && child_pid != pid)
4262306a36Sopenharmony_ci		return;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	__u64 cookie = test_cookie ? bpf_get_attach_cookie(ctx) : 0;
4562306a36Sopenharmony_ci	__u64 addr = bpf_get_func_ip(ctx);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define SET(__var, __addr, __cookie) ({			\
4862306a36Sopenharmony_ci	if (addr == __addr &&				\
4962306a36Sopenharmony_ci	   (!test_cookie || (cookie == __cookie)))	\
5062306a36Sopenharmony_ci		__var += 1;				\
5162306a36Sopenharmony_ci})
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	if (is_return) {
5462306a36Sopenharmony_ci		SET(uretprobe_multi_func_1_result, uprobe_multi_func_1_addr, 2);
5562306a36Sopenharmony_ci		SET(uretprobe_multi_func_2_result, uprobe_multi_func_2_addr, 3);
5662306a36Sopenharmony_ci		SET(uretprobe_multi_func_3_result, uprobe_multi_func_3_addr, 1);
5762306a36Sopenharmony_ci	} else {
5862306a36Sopenharmony_ci		SET(uprobe_multi_func_1_result, uprobe_multi_func_1_addr, 3);
5962306a36Sopenharmony_ci		SET(uprobe_multi_func_2_result, uprobe_multi_func_2_addr, 1);
6062306a36Sopenharmony_ci		SET(uprobe_multi_func_3_result, uprobe_multi_func_3_addr, 2);
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#undef SET
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (is_sleep && verify_sleepable_user_copy())
6662306a36Sopenharmony_ci		uprobe_multi_sleep_result += 1;
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciSEC("uprobe.multi//proc/self/exe:uprobe_multi_func_*")
7062306a36Sopenharmony_ciint uprobe(struct pt_regs *ctx)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	uprobe_multi_check(ctx, false, false);
7362306a36Sopenharmony_ci	return 0;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciSEC("uretprobe.multi//proc/self/exe:uprobe_multi_func_*")
7762306a36Sopenharmony_ciint uretprobe(struct pt_regs *ctx)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	uprobe_multi_check(ctx, true, false);
8062306a36Sopenharmony_ci	return 0;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciSEC("uprobe.multi.s//proc/self/exe:uprobe_multi_func_*")
8462306a36Sopenharmony_ciint uprobe_sleep(struct pt_regs *ctx)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	uprobe_multi_check(ctx, false, true);
8762306a36Sopenharmony_ci	return 0;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ciSEC("uretprobe.multi.s//proc/self/exe:uprobe_multi_func_*")
9162306a36Sopenharmony_ciint uretprobe_sleep(struct pt_regs *ctx)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	uprobe_multi_check(ctx, true, true);
9462306a36Sopenharmony_ci	return 0;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciSEC("uprobe.multi//proc/self/exe:uprobe_multi_func_*")
9862306a36Sopenharmony_ciint uprobe_extra(struct pt_regs *ctx)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	return 0;
10162306a36Sopenharmony_ci}
102