0

I understand how to attach specific bpf kernel program using libbpf code. user space program has total control on programs and maps etc. but how to achieve the same with Auto generated boilerplate bpf code i.e xxx_bpf_attach.

use case , attach only required programs based on options passed to tool.

How to attach only specific programs with bpftool generated skeleton code. all programs and links are populated inside autogenerated skeleton code, not much control.

any tricks or existing samples would be helpful went through https://github.com/anakryiko/bpf-ringbuf-examples and also very good details posts by bpf contributor https://nakryiko.com/

Please let me know if more details or context needed

kernelspace.c

SEC("tp/sched/sched_process_exec")
int handle_exec(struct trace_event_raw_sched_process_exec *ctx)
{

}
SEC("tp/sched/sched_process_exit")
int handle_exit(struct trace_event_raw_sched_process_template *ctx)
{
}


userspace.c 
int main(int argc, char **argv)
{
    struct ring_buffer *rb = NULL;
    char filename[256];
    struct bpf_object *obj = NULL;
    int map_fd[2];
    struct bpf_program *prog[2];
    static struct bpf_link *bpflinks[2];
    int err;

    
    snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
    obj = bpf_object__open_file(filename, NULL);
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "ERROR: opening BPF object file failed\n");
        obj = NULL;
        goto cleanup;
    }
    /* load BPF program */
    if (bpf_object__load(obj)) {
        fprintf(stderr, "ERROR: loading BPF object file failed\n");
        goto cleanup;
    }

     map_fd[0] = bpf_object__find_map_fd_by_name(obj, "exec_start");
     map_fd[1] = bpf_object__find_map_fd_by_name(obj, "rb");


     prog[0] = bpf_object__find_program_by_name(obj, "handle_exec");
//   prog[1] = bpf_object__find_program_by_name(obj, "handle_exit");  // i can decide which one to attach

#if 0
    /* Load and verify BPF application */
    skel = bootstrap__open();
    if (!skel) {
        fprintf(stderr, "Failed to open and load BPF skeleton\n");
        return 1;
    }

    /* Parameterize BPF code with minimum duration parameter */
    skel->rodata->min_duration_ns = env.min_duration_ms * 1000000ULL;

    /* Load & verify BPF programs */
    err = bootstrap__load(skel);
    if (err) {
        fprintf(stderr, "Failed to load and verify BPF skeleton\n");
        goto cleanup;
    }

    /* Attach tracepoints */
    err = bootstrap__attach(skel);   // how to Customize programs to load , we don't have much control here 
    if (err) {
        fprintf(stderr, "Failed to attach BPF skeleton\n");
        goto cleanup;
    }
#endif


 /* Set up ring buffer polling */
    rb = ring_buffer__new(map_fd[1], handle_event, NULL, NULL);
    if (!rb) {
        err = -1;
        fprintf(stderr, "Failed to create ring buffer\n");
        goto cleanup;
    }

    /* Process events */
    printf("%-8s %-5s %-16s %-7s %-7s %s\n", "TIME", "EVENT", "COMM", "PID", "PPID",
           "FILENAME/EXIT CODE");
    while (!exiting) {
        err = ring_buffer__poll(rb, 100 /* timeout, ms */);
        /* Ctrl-C will cause -EINTR */
        if (err == -EINTR) {
            err = 0;
            break;
        }
        if (err < 0) {
            printf("Error polling perf buffer: %d\n", err);
            break;
        }
    }

cleanup:
    /* Clean up */
    ring_buffer__free(rb);
    bpf_link__destroy(bpflinks[0]);
//  bpf_link__destroy(bpflinks[1]);
    //bootstrap__destroy(skel);

    return err < 0 ? -err : 0;
}

// Skeleton code generated by bpftool for bpf program
skeleton.h

static inline int
bootstrap__create_skeleton(struct bootstrap *obj)
{
    struct bpf_object_skeleton *s;
    int err;

    s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
    if (!s) {
        err = -ENOMEM;
        goto err;
    }

    s->sz = sizeof(*s);
    s->name = "bootstrap";
    s->obj = &obj->obj;

    /* maps */
    s->map_cnt = 3;
    s->map_skel_sz = sizeof(*s->maps);
    s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
    if (!s->maps) {
        err = -ENOMEM;
        goto err;
    }

    s->maps[0].name = "exec_start";
    s->maps[0].map = &obj->maps.exec_start;

    s->maps[1].name = "rb";
    s->maps[1].map = &obj->maps.rb;

    s->maps[2].name = "bootstra.rodata";
    s->maps[2].map = &obj->maps.rodata;
    s->maps[2].mmaped = (void **)&obj->rodata;

    /* programs */
    s->prog_cnt = 2;
    s->prog_skel_sz = sizeof(*s->progs);
    s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
    if (!s->progs) {
        err = -ENOMEM;
        goto err;
    }
s->progs[0].name = "handle_exec";
    s->progs[0].prog = &obj->progs.handle_exec;
    s->progs[0].link = &obj->links.handle_exec;

    s->progs[1].name = "handle_exit";
    s->progs[1].prog = &obj->progs.handle_exit;
    s->progs[1].link = &obj->links.handle_exit;

    s->data = (void *)bootstrap__elf_bytes(&s->data_sz);

    obj->skeleton = s;
    return 0;
err:
    bpf_object__destroy_skeleton(s);
    return err;
}
nullptr
  • 5
  • 3

0 Answers0