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