2

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
user786
  • 3,902
  • 4
  • 40
  • 72
  • 2
    `prog = bpf_object__find_program_by_name(obj, "kprobe/__x64_sys_write");` -> `kprobe/__x64_sys_write` is the name of the ELF section that you're using, I don't think it's the name of your program. Unless I'm mistaken, the name that you should pass here would instead be the name of your C function: in your case, `__x64_sys_write` (for the one on `kprobe/__seccomp_filter`, it would be `bpf_prog1`). – Qeole Jan 24 '22 at 16:02
  • errno only has a defined value if an error occurs. – stark Jan 24 '22 at 21:26
  • @Qeole yes I tried that too. Do u know where the implementation of this function. Is it part of my kernel or libbpf – user786 Jan 25 '22 at 06:29
  • Both. It's part of libbpf, which is part of the kernel. I'd expect Qeole's solution to work. – pchaigno Jan 25 '22 at 08:36
  • @pchaigno yes I tried that but I don't know why my error was still getting set at 2. Do u know how to print elf section of my program from object file for ebpf program. Is there a way I can confirm my elf object program and file is correct and can be loaded by verifier – user786 Jan 25 '22 at 11:41
  • You can use the readelf CLI for that. – pchaigno Jan 25 '22 at 11:50
  • 1
    Just a suggestion... It looks like you based your example on some of the kernel samples, so one way to debug could maybe consist in starting with the original files, which are “known to work”, and then modify progressively until you changed them to implement your own example, while checking at the different steps that everything is still loading as expected? – Qeole Jan 25 '22 at 14:24

1 Answers1

0

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
PhilMasteG
  • 3,095
  • 1
  • 20
  • 27
kong chen
  • 11
  • 2