errno = 2 right after call to bpf_object__open_file and libbpf_get_error not saying anything

Viewed 238

I wrote a simple ebpf so I opened it with obj = bpf_object__open_file(filename, NULL);

then when I do prog = bpf_object__find_program_by_name(obj, "kprobe/__x64_sys_write");

This function returns NULL and prints message that printf("finding a prog in obj file failed\n");. so basically my function or program could not be found in object file, I like to know what might be the reason for this so I also found after the call to bpf_object__open_file my errno got set to 2 so I like to know what is exactly happening why my errno set to 2 right after bpf_object__open_file and I made sure that file does exists

this condition is also not fullfilling

   if (libbpf_get_error(obj)) {
    printf("ERROR: opening BPF object file failed\n");

This is a loader program

// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <sys/resource.h>
#include <errno.h>
//#include "trace_helpers.h"

#ifdef __mips__
#define MAX_ENTRIES  6000 /* MIPS n64 syscalls start at 5000 */
#else
#define MAX_ENTRIES  1024
#endif

/* install fake seccomp program to enable seccomp code path inside the kernel,
 * so that our kprobe attached to seccomp_phase1() can be triggered
 */
static void install_accept_all_seccomp(void)
{
    struct sock_filter filter[] = {
        BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
    };
    struct sock_fprog prog = {
        .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
        .filter = filter,
    };
    if (prctl(PR_SET_SECCOMP, 2, &prog))
        perror("prctl");
}

int main(int ac, char **argv)
{
    struct bpf_link *link = NULL;
    struct bpf_program *prog;
    struct bpf_object *obj;
    int key, fd, progs_fd;
    const char *section;
    char filename[256]="/home/fawad/bpf/linux-5.13.1/samples/bpf/kern5.o";
    printf("%s\n",filename);
    FILE *f;


//snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
    printf("errono before %d\n",errno);
    obj = bpf_object__open_file(filename, NULL);
    printf("errono after %d\n",errno);
    if (libbpf_get_error(obj)) {
        printf("ERROR: opening BPF object file failed\n");
        return 0;
    }

    printf("errno before %d\n",errno);
    prog =  bpf_object__find_program_by_name(obj, "kprobe/__x64_sys_write");
    printf("errno after %d\n",errno);
    if (!prog) {
        printf("finding a prog in obj file failed\n");
        goto cleanup;
    }

    /* load BPF program */
    if (bpf_object__load(obj)) {
        fprintf(stderr, "ERROR: loading BPF object file failed\n");
        goto cleanup;
    }

    link = bpf_program__attach(prog);
    if (libbpf_get_error(link)) {
        fprintf(stderr, "ERROR: bpf_program__attach failed\n");
        link = NULL;
        goto cleanup;
    }

    progs_fd = bpf_object__find_map_fd_by_name(obj, "progs");
    if (progs_fd < 0) {
        fprintf(stderr, "ERROR: finding a map in obj file failed\n");
        goto cleanup;
    }

    bpf_object__for_each_program(prog, obj) {
        section = bpf_program__section_name(prog);
        /* register only syscalls to PROG_ARRAY */
        if (sscanf(section, "kprobe/%d", &key) != 1)
            continue;

        fd = bpf_program__fd(prog);
        bpf_map_update_elem(progs_fd, &key, &fd, BPF_ANY);
    }

    install_accept_all_seccomp();

    f = popen("dd if=/dev/zero of=/dev/null count=5", "r");
    (void) f;

//  read_trace_pipe();

cleanup:
    bpf_link__destroy(link);
    bpf_object__close(obj);
    return 0;
}

and this is ebpf program

/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 */
#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
//#include "syscall_nrs.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F


struct {
    __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    __uint(key_size, sizeof(int));
    __uint(value_size, sizeof(int));
#ifdef __mips__
    __uint(max_entries, 6000); /* MIPS n64 syscalls start at 5000 */
#else
    __uint(max_entries, 1024);
#endif
} progs SEC(".maps");

/*SEC("kprobe/SYS__NR_write")
int bpf_prog2(struct pt_regs *ctx)
{
    struct seccomp_data sd;

    bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
    if (sd.args[2] == 512) {
        char fmt[] = "write(fd=%d, buf=%p, size=%d)\n";
        bpf_trace_printk(fmt, sizeof(fmt),
                 sd.args[0], sd.args[1], sd.args[2]);
    }
    return 0;
}*/

SEC("kprobe/__seccomp_filter")
int bpf_prog1(struct pt_regs *ctx)
{
    int sc_nr = (int)PT_REGS_PARM1(ctx);

    /* dispatch into next BPF program depending on syscall number */
    bpf_tail_call(ctx, &progs, sc_nr);

    /* fall through -> unknown syscall */
    if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) {
        char fmt[] = "syscall=%d (one of get/set uid/pid/gid)\n";
        bpf_trace_printk(fmt, sizeof(fmt), sc_nr);
    }
    return 0;
}

SEC("kprobe/__x64_sys_write")
/* we jump here when syscall number == __NR_write */
//PROG(SYS__NR_write)(struct pt_regs *ctx)
int __x64_sys_write(struct pt_regs *ctx)
{
    struct seccomp_data sd;

    bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
    if (sd.args[2] == 512) {
        char fmt[] = "write(fd=%d, buf=%p, size=%d)\n";
        bpf_trace_printk(fmt, sizeof(fmt),
                 sd.args[0], sd.args[1], sd.args[2]);
    }
    return 0;
}

/*
PROG(SYS__NR_read)(struct pt_regs *ctx)
{
    struct seccomp_data sd;

    bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
    if (sd.args[2] > 128 && sd.args[2] <= 1024) {
        char fmt[] = "read(fd=%d, buf=%p, size=%d)\n";
        bpf_trace_printk(fmt, sizeof(fmt),
                 sd.args[0], sd.args[1], sd.args[2]);
    }
    return 0;
}

#ifdef __NR_mmap2
PROG(SYS__NR_mmap2)(struct pt_regs *ctx)
{
    char fmt[] = "mmap2\n";

    bpf_trace_printk(fmt, sizeof(fmt));
    return 0;
}
#endif

#ifdef __NR_mmap
PROG(SYS__NR_mmap)(struct pt_regs *ctx)
{
    char fmt[] = "mmap\n";

    bpf_trace_printk(fmt, sizeof(fmt));
    return 0;
}
#endif
*/
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;

compiling userspace loader like

 clang -L /usr/lib/usr/lib64/  -I /usr/include/   -I /usr/lib/usr/include/  tracex5_user.c -o user1.o -lbpf

compiling kernel ebpf program like

sudo clang -Wall -O2 -g -target bpf -I  /usr/lib/usr/include -I /usr/include/x86_64-linux-gnu/ -I /usr/include/linux/ -c syscall_tp_kern.c -o kern5.o
1 Answers

Please try this command

bpftool prog load bpf_test.o /sys/fs/bpf/vfs_create

In my scenario, I got the error:

libbpf: failed to find BTF for extern 'PT_REGS_PARM2': -3
Related