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