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;
}
```