2

I have problem with my bpf program. I getting error while loading this program. my bpf program is:

#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <uapi/linux/bpf.h>
#include <linux/version.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <linux/fs.h>
#include <uapi/asm-generic/errno-base.h>

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __type(key,   int);
    __type(value, ino_t);
    __uint(max_entries, 256);
} qu SEC(".maps");


SEC("lsm/task_kill")
BPF_PROG(
    lsm__task_kill,
    struct task_struct* p, 
    struct kernel_siginfo* info,
    int sig,
    const struct cred* cred
) {
    int key = 0;
    int* my_pid = bpf_map_lookup_elem(&qu, &key);
    if (*my_pid == 3935991) {
        return -EPERM;
    }
    
    bpf_ringbuf_output(&rb, &data, sizeof(data), 0);

    return 0;
}

and this is my user program:

#include <bpf/bpf.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/version.h>
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <bpf/libbpf.h>
#include <time.h>


int main(
    int         argc, 
    const char* argv[]
) {
    if (argc <= 1) {
        return -1;
    }
    
    struct stat stat_buf = {0};
    int ret = stat(argv[1], &stat_buf);
    if (ret == -1) {
        printf("ERROR: resolving pathname failed: %s\n", strerror(errno));
        return -1;
    }

    struct bpf_object *obj = bpf_object__open("./my_prog.o");
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "ERROR: opening BPF object file failed\n");
        return 0;
    }

    bpf_object__load(obj);
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "ERROR: opening BPF object file failed\n");
        return 0;
    }

    int qfd = bpf_object__find_map_fd_by_name(obj, "qu");
    if (qfd < 0) {
        fprintf(stderr, "ERROR: finding a queue in obj file failed\n");
        return -1;
    }

    int val = stat_buf.st_ino;
    int key = 0;
    ret = bpf_map_update_elem(qfd, &key, &val, BPF_ANY);
    if (ret < 0) {
        printf("ERROR: updating map failed\n");
        return -1;
    }
    
    
    struct bpf_link*    links[1];
    struct bpf_program* prog;
    int j = 0;
    bpf_object__for_each_program(prog, obj) {
        links[j] = bpf_program__attach_lsm(prog);
        if (libbpf_get_error(links[j])) {
            fprintf(stderr, "ERROR: bpf_program__attach failed\n");
            links[j] = NULL;
            return -1;
        }
        j++;
    }

   
}

there is no error while making bpf object file and compiling user program, but when i run user program i get this error while loading bpf program:

user@host:~$ sudo ./my_prog_loader ./some_file

libbpf: elf: skipping unrecognized data section(22) .eh_frame
libbpf: elf: skipping relo section(23) .rel.eh_frame for section(22) .eh_frame
libbpf: load bpf program failed: Permission denied
libbpf: -- BEGIN DUMP LOG ---
libbpf: 
R1 type=ctx expected=fp
; BPF_PROG(
0: (b7) r6 = 0
; Data data = {0};
1: (7b) *(u64 *)(r10 -8) = r6
last_idx 1 first_idx 0
regs=40 stack=0 before 0: (b7) r6 = 0
2: (7b) *(u64 *)(r10 -16) = r6
3: (7b) *(u64 *)(r10 -24) = r6
4: (7b) *(u64 *)(r10 -32) = r6
5: (bf) r1 = r10
6: (07) r1 += -16
; bpf_get_current_comm(data.str, 16);
7: (b7) r2 = 16
8: (85) call bpf_get_current_comm#16
last_idx 8 first_idx 0
regs=4 stack=0 before 7: (b7) r2 = 16
; data.pid  = 000000;
9: (63) *(u32 *)(r10 -32) = r6
; int key = 0;
10: (63) *(u32 *)(r10 -36) = r6
11: (bf) r2 = r10
; 
12: (07) r2 += -36
; ino_t* my_pid = bpf_map_lookup_elem(&qu, &key);
13: (18) r1 = 0xffff8fa64edafc00
15: (85) call bpf_map_lookup_elem#1
; if (*my_pid == 3935991) {
16: (79) r1 = *(u64 *)(r0 +0)
R0 invalid mem access 'map_value_or_null'
processed 16 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1

libbpf: -- END LOG --
libbpf: failed to load program 'lsm__task_kill'
libbpf: failed to load object './my_prog.o'
ERROR: finding a map in obj file failed

user@host:~$_

why I'm getting this error and what should I do?? thank you for any help!

1 Answer 1

2

TL;DR. You should check that the pointer returned by bpf_map_lookup_elem is not NULL.


With the following logs, the BPF verifier is telling you that, when it reaches the dereference of my_pid, the pointer may still have a NULL value. It thus contains a map value or a NULL value, i.e., map_value_or_null.

; ino_t* my_pid = bpf_map_lookup_elem(&qu, &key);
13: (18) r1 = 0xffff8fa64edafc00
15: (85) call bpf_map_lookup_elem#1
; if (*my_pid == 3935991) {
16: (79) r1 = *(u64 *)(r0 +0)
R0 invalid mem access 'map_value_or_null'

bpf_map_lookup_elem returns a NULL value whenever the looked up key isn't found.

You could simply do something like:

if (my_pid && *my_pid == 3935991) {
    return -EPERM;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. so why I'm getting null value of certain key at all?? am I wrong in updating map?
The verifier runs when you load the program, before you run the program for the first time. So it checks all possibilities, including the possibility that a map lookup returns NULL. That doesn't mean it will happen at runtime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.