ebpfrawciliumtracepoint

Using a program of type raw_tracepoint to trace sched_wakeup,bpf verifies that task_struct *p is empty


I used the program type tracepoint, tracepoint /sched/sched_wakeup, and the function parameter tracepoint format。But I changed the raw_tracepoint type, it is not useful, error:loading objects: field TraceSchedWakeup: program trace_sched_wakeup: load program: permission denied: 5: (61) r1 = *(u32 *)(r7 +2784): R7 invalid mem access 'inv' (5 line(s) omitted。 I know that task_struct *p is empty, which causes this error, but I don't know why I try to empty it

bpf file

SEC("raw_tracepoint/sched_wakeup") 
int trace_sched_wakeup(struct bpf_raw_tracepoint_args *ctx) {
    struct task_struct *p ;
    p=(struct task_struct *) ctx->args[0];
    u64 ntime = bpf_ktime_get_ns();
    struct data_t r_p_data={0};
    r_p_data.pid = p->pid;
    r_p_data.currtime=ntime;
    bpf_perf_event_output(ctx, &output_events, BPF_F_CURRENT_CPU, &r_p_data, sizeof(r_p_data));
    return 0;
}

#go file

load program

if err := rlimit.RemoveMemlock(); err != nil {
    return err
}

opts := ebpf.CollectionOptions{}
    
opts.Programs = ebpf.ProgramOptions{
    KernelTypes: bpfutil.LoadBTFSpecOrNil(),
}

        
if err := loadBpfObjects(&objs, &opts); err != nil {
    return fmt.Errorf("loading objects: %v", err)
}
progentry,err:=link.AttachRawTracepoint(link.RawTracepointOptions{Name:"sched_wakeup",Program:objs.TraceSchedWakeup})
if err != nil {
    return fmt.Errorf("link softirq_entry: %s", err.Error())
}
links = append(links, progentry)

perf read

reader, err := perf.NewReader(objs.bpfMaps.OutputEvents, 10000 * int(unsafe.Sizeof(bpfSchedEventT{})))
if err != nil {
    fmt.Println(err)
    return
}
for {
    record, err := reader.Read()
    ....
}

Why is the raw tracepoint class line empty


Solution

  • The task_struct *p is not empty. The error is caused by p->pid. You can't directly read it, try to change it to:

    r_p_data.pid = BPF_CORE_READ(p, pid);
    

    or

    bpf_probe_read_kernel(&r_p_data.pid, sizeof(r_p_data.pid), &p->pid);