Re: bpf_probe_read_user EFAULT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Dec 27, 2022 at 03:56:06PM +0100, Victor Laforet wrote:
> Hi all,
> 
> I am trying to use bpf_probe_read_user to read a user space value from BPF. The issue is that I am getting -14 (-EFAULT) result from bpf_probe_read_user. I haven’t been able to make this function work reliably. Sometimes I get no error code then it goes back to EFAULT.
> 
> I am seeking your help to try and make this code work.
> Thank you!
> 
> My goal is to read the variable pid on every bpf event.
> Here is a full example:
> (cat /sys/kernel/debug/tracing/trace_pipe to read the output).
> 
> sched_switch.bpf.c
> ```
> #include "vmlinux.h"
> #include <bpf/bpf_helpers.h>
> 
> int *input_pid;
> 
> char _license[4] SEC("license") = "GPL";
> 
> SEC("tp_btf/sched_switch")
> int handle_sched_switch(u64 *ctx)

you might want to filter for your task, because sched_switch
tracepoint is called for any task scheduler switch

check BPF_PROG macro in bpf selftests on how to access tp_btf
arguments from context, for sched_switch it's:

        TP_PROTO(bool preempt,
                 struct task_struct *prev,
                 struct task_struct *next,
                 unsigned int prev_state),

and call the read helper only for prev->pid == 'your app pid',

there's bpf_copy_from_user_task helper you could use to read
another task's user memory reliably, but it needs to be called
from sleepable probe and you need to have the task pointer

jirka

> {
>   int pid;
>   int err;
> 
>   err = bpf_probe_read_user(&pid, sizeof(int), (void *)input_pid);
>   if (err != 0)
>   {
>     bpf_printk("Error on bpf_probe_read_user(pid) -> %d.\n", err);
>     return 0;
>   }
> 
>   bpf_printk("pid %d.\n", pid);
>   return 0;
> }
> ```
> 
> sched_switch.c
> ```
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/resource.h>
> #include <bpf/libbpf.h>
> #include "sched_switch.skel.h"
> #include <time.h>
> 
> static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
> {
>   return vfprintf(stderr, format, args);
> }
> 
> int main(int argc, char **argv)
> {
>   struct sched_switch_bpf *skel;
>   int err;
>   int pid = getpid();
> 
>   libbpf_set_print(libbpf_print_fn);
> 
>   skel = sched_switch_bpf__open();
>   if (!skel)
>   {
>     fprintf(stderr, "Failed to open BPF skeleton\n");
>     return 1;
>   }
> 
>   skel->bss->input_pid = &pid;
> 
>   err = sched_switch_bpf__load(skel);
>   if (err)
>   {
>     fprintf(stderr, "Failed to load and verify BPF skeleton\n");
>     goto cleanup;
>   }
> 
>   err = sched_switch_bpf__attach(skel);
>   if (err)
>   {
>     fprintf(stderr, "Failed to attach BPF skeleton\n");
>     goto cleanup;
>   }
> 
>   while (1);
> 
> cleanup:
>   sched_switch_bpf__destroy(skel);
>   return -err;
> }
> ```



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux