我正在尝试使用 ebpf uprobes 在运行时修改用户空间函数的行为。
bpf_override_return
在kprobes中用于覆盖返回值,是否可以在uprobes/uretprobes中使用它?
uprobes 共享 kprobes 的 BPF 基础设施,所以是的,您应该能够从 uprobe BPF 程序调用
bpf_override_return
。请注意,您的内核配置中需要 CONFIG_BPF_KPROBE_OVERRIDE
。
bcc 项目有一个列表,其中列出了哪些程序类型允许使用哪些助手,位于 https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md。
要检查给定帮助程序允许哪种程序类型,您可以在内核源代码上运行以下命令:
$ git grep -W "&bpf_override_return_proto"
kernel/trace/bpf_trace.c=kprobe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
kernel/trace/bpf_trace.c-{
kernel/trace/bpf_trace.c- switch (func_id) {
kernel/trace/bpf_trace.c- case BPF_FUNC_perf_event_output:
kernel/trace/bpf_trace.c- return &bpf_perf_event_output_proto;
kernel/trace/bpf_trace.c- case BPF_FUNC_get_stackid:
kernel/trace/bpf_trace.c- return &bpf_get_stackid_proto;
kernel/trace/bpf_trace.c- case BPF_FUNC_get_stack:
kernel/trace/bpf_trace.c- return &bpf_get_stack_proto;
kernel/trace/bpf_trace.c-#ifdef CONFIG_BPF_KPROBE_OVERRIDE
kernel/trace/bpf_trace.c- case BPF_FUNC_override_return:
kernel/trace/bpf_trace.c: return &bpf_override_return_proto;
kernel/trace/bpf_trace.c-#endif
在这里我们看到
bpf_override_return
只能从kprobe程序中调用。
@pchaigno 我在尝试将
uretprobe
与 bpf_override_return
结合使用时遇到了问题。我将 uretprobe
附加到返回当前实时值的 Python 库函数。我的目标是用不同的旧时间修改时间,但我遇到了以下问题:
收到的错误消息是:无法创建 bpf perf 链接:无效参数。
内核端代码如下:
SEC("uretprobe/_PyTime_GetSystemClock")
int _PyTime_GetSystemClock_bpf(struct pt_regs *ctx)
{
u64 id = bpf_get_current_pid_tgid();
u32 pid = id >> 32;
u32 kZero = 0;
u32 *appPid = bpf_map_lookup_elem(&app_pid_map, &kZero);
if (appPid)
{
if (pid != *appPid || pid != 1369246)
{
return 0;
}
}
else
{
return 0;
}
u64 time = (PT_REGS_RC(ctx));
bpf_printk("[_PyTime_GetSystemClock_bpf]Info: called :%lu & time is:%llu", pid, time);
u64 t = 1706533301399118410; // Some time value to overwrite
long ret = bpf_override_return(ctx, t);
if (ret != 0)
{
bpf_printk("[_PyTime_GetSystemClock_bpf]Error: bpf_override_return failed");
return 0;
}
// Print the process pid
bpf_printk("[_PyTime_GetSystemClock_bpf]Info: Modified time for pid: %lu & time is:%llu", pid, t);
return 0;
}
在用户空间代码中:
binPath := "/usr/bin/python3.10"
symbol := "_PyTime_GetSystemClock"
// Open an ELF binary and read its symbols.
ex, err := link.OpenExecutable(binPath)
if err != nil {
log.Fatalf("opening executable: %s", err)
}
// Open a Uretprobe at the exit point of the symbol and attach
// the pre-compiled eBPF program to it.
up, err := ex.Uretprobe(symbol, objs.PyTimeGetSystemClockBpf, nil)
if err != nil {
log.Fatalf("creating uretprobe: %+v", err)
}
defer up.Close()
不使用 bpf_override_return 时不会出现任何问题,并且所需的配置
CONFIG_BPF_KPROBE_OVERRIDE=y
已在我的计算机上启用。