Re: bpf_probe_read_user EFAULT

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

 



Thanks!

I have tried to use bpf_copy_from_user_task() in place of bpf_probe_read_user() however I cannot seem to run my program. It fails with 'unknown func bpf_copy_from_user_task’.
If I understood correctly, this function should be in ‘bpf/bpf_helpers.h’?

Another quick question:
I have set the bpf program as sleepable using ‘	bpf_program__set_flags(skel, BPF_F_SLEEPABLE);'
I couldn’t find any other way to do that. Is it the right way to set it sleepable?

Victor

De: "Yonghong Song" <yhs@xxxxxxxx>
À: "Victor Laforet" <victor.laforet@xxxxxxxxxxx>, "Jiri Olsa" <olsajiri@xxxxxxxxx>
Cc: "bpf" <bpf@xxxxxxxxxxxxxxx>
Envoyé: Mercredi 28 Décembre 2022 20:41:33
Objet: Re: bpf_probe_read_user EFAULT

On 12/28/22 6:00 AM, Victor Laforet wrote:
> Yes I am sorry I did not mention that the example I sent was a minimal working example. I am filtering the events to select only preempted and events with the right pid as prev.
> 
> Would bpf_copy_from_user_task work better in this setting than bpf_probe_read_user ?
> I don’t really understand why bpf_probe_read_user would not work for this use case.

Right, bpf_copy_from_user_task() is better than bpf_probe_read_user(). 
You could also use bpf_copy_from_user() if you have target_pid checking.

It is possible that the user variable you intended to access is not in 
memory. In such cases, bpf_probe_read_user() will return EFAULT. But
bpf_copy_from_user() and bpf_copy_from_user_task() will go through
page fault process to bring the variable to the memory.
Also because of this extra work, bpf_copy_from_user() and
bpf_copy_from_user_task() only work for sleepable programs.

> 
> Victor
> 
> ----- Mail original -----
> De: "Jiri Olsa" <olsajiri@xxxxxxxxx>
> À: "Victor Laforet" <victor.laforet@xxxxxxxxxxx>
> Cc: "bpf" <bpf@xxxxxxxxxxxxxxx>
> Envoyé: Mardi 27 Décembre 2022 17:00:42
> Objet: Re: bpf_probe_read_user EFAULT
> 
> 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