Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BPF_KPROBE macro provides unexpected value of function argument #57

Closed
artych opened this issue Dec 11, 2021 · 2 comments
Closed

BPF_KPROBE macro provides unexpected value of function argument #57

artych opened this issue Dec 11, 2021 · 2 comments

Comments

@artych
Copy link

artych commented Dec 11, 2021

Hello! While playing with libbpf-bootstrap I'm getting unexpected (and strange) function argument for kprobe syscalls. For example for kprobe on close syscall with int close(inf fd) signature, I got enormous fd values like fd=15761240 while expected small int like fd=4. Reproduced this on Debian 11 x64 (kernel 5.10.0-7-amd64) and Ubuntu 21.10 x64 (kernel ~5.13).

Debug code:

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

// close accept4 syscall
// int accept4(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict addrlen);
SEC("kretprobe/__x64_sys_accept4")
int BPF_KRETPROBE(accept, int ret) {
	u64 id = bpf_get_current_pid_tgid();
	u32 pid = id >> 32;

	// filter specific pid for simplicity
	if (pid != 31114 || ret < 0) {
		return 0;
	}

	// debug returned file descriptor
	bpf_printk("opened pid=%d fd=%d", pid, ret);
	return 0;
}

// close syscall
// int close(int fd);
SEC("kprobe/__x64_sys_close")
int BPF_KPROBE(close, int fd) {
	u64 id = bpf_get_current_pid_tgid();
	u32 pid = id >> 32;
	// filter specific pid for simplicity
	if (pid != 31114) {
		return 0;
	}

	// debug fd arg (expected to be equal to fd returned on accept4)
	bpf_printk("closed pid=%d fd=%d", pid, fd);
    return 0;
}

Results

$ cat /sys/kernel/debug/tracing/trace_pipe
            main-31114   [001] d...  9069.254408: bpf_trace_printk: opened pid=31114 fd=4
            main-31114   [001] d...  9069.321946: bpf_trace_printk: closed pid=31114 fd=15761240

I tried to alter vmlinux.h: at first with vmlinux.h delivered by libbbpf-bootstrap and then with "native" vmlinux.h from the instance OS kernel and on both ways I got the issue above.

Also tried to run the same bpf program in BCC way (compiled with bcc at run-time) with kprobes declared without BPF_KPROBE macro, like that:

int syscall__probe_close_entry(struct pt_regs *ctx, int fd) { ... }

and it worked as expected: fd=4 at all the debug points.
Is it a BPF_KPROBE macro bug/incompatibility with the kernel or I'm missing something?

@anakryiko
Copy link
Member

that __x64_sys_close() actually has only one input parameter, and that's struct pt_regs *, which contains all the syscall input arguments. So you have to do something like this to get access to input arguments:

SEC("kprobe/__x64_sys_close")
int BPF_KPROBE(do_sys_close, struct pt_regs *regs)
{
        pid_t pid;
        int fd;

        fd = PT_REGS_PARM1_CORE(regs);

        pid = bpf_get_current_pid_tgid() >> 32;
        bpf_printk("KPROBE ENTRY pid = %d, fd = %d\n", pid, fd);
        return 0;
}

It might be a good idea to add syscall-specific kprobe/kretprobe macros, as this is a common gotcha. Added libbpf/libbpf#425 to keep track of that.

@artych
Copy link
Author

artych commented Dec 19, 2021

Thanks for explaining that, @anakryiko ! The patch above works as expected. Closing the issue.

@artych artych closed this as completed Dec 19, 2021
kernel-patches-bot pushed a commit to kernel-patches/bpf that referenced this issue Feb 9, 2022
Hengqi Chen says:

====================

Add new macro BPF_KPROBE_SYSCALL, which provides easy access to syscall
input arguments. See [0] and [1] for background.

  [0]: libbpf/libbpf-bootstrap#57
  [1]: libbpf/libbpf#425

v2->v3:
  - Use PT_REGS_SYSCALL_REGS
  - Move selftest to progs/bpf_syscall_macro.c

v1->v2:
  - Use PT_REGS_PARM2_CORE_SYSCALL instead
====================

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants