All of lore.kernel.org
 help / color / mirror / Atom feed
* Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL
@ 2022-01-05 10:03 Buchberger, Dennis
  2022-01-05 10:43 ` Greg KH
  2022-01-06  4:55 ` Andrii Nakryiko
  0 siblings, 2 replies; 7+ messages in thread
From: Buchberger, Dennis @ 2022-01-05 10:03 UTC (permalink / raw)
  To: bpf

Hello :)

I am currently having a problem and hope you can help me: My goal is to develop a BPF-program (see below) on a development machine and then deploy it to another machine to run it there using BPF CO:RE.
But the program does not load; bpf_object__load returns -EINVAL.

Development machine:
- Ubuntu 20.04 LTS
- Linux 5.4.0-90-generic x86_64
- Kernel compiled with CONFIG_DEBUG_INFO_BTF=y, so BTF is available under /sys/kernel/btf/vmlinux
- clang version: 10.0.0-4ubuntu1
- llc version: 10.0.0

Target machine:
- Ubuntu 18.10
- Linux 4.18.0-25-generic x86_64
- clang version: 13.0.0
- llc version: 13.0.0

As the target kernel does not support CONFIG_DEBUG_INFO_BTF, I used pahole -J (v1.22) to create vmlinux file with BTF info embedded there.
Basically, I followed this mails: https://lore.kernel.org/bpf/CADmGQ+1euj7Uv9e8UyZMMXDiYAKqXe9=GSTBFNbbg1E0R-ejyg@mail.gmail.com/

Right now, the bpf program is just a uProbe for a simple test app, which writes some output to the tracing pipe. As Kernel 4.18. does not support global data for bpf programs, I had to remove (comment out) the bpf_trace_printk statements.
On the development machine, it works fine. But on the target machine, loading the program fails: libbpf: load bpf program failed: Invalid argument (full libbpf log see below).
When compiling the programs on the target machine without using CO:RE, I get a similar error (invalid argument, -22).
What could be the problem? I don't think the eBPF program uses anything that is available on Kernel 5.4.0 and not available on the system with Kernel 4.18, does it?

Thanks in advance for your help.
Best
Dennis




============ log ============

sudo ./ebpf 
libbpf: loading main.bpf.o
libbpf: elf: section(3) kprobe/, size 272, link 0, flags 6, type=1
libbpf: sec 'kprobe/': found program 'trace_func_entry' at insn offset 0 (0 bytes), code size 34 insns (272 bytes)
libbpf: elf: section(4) .relkprobe/, size 16, link 24, flags 0, type=9
libbpf: elf: section(5) kretprobe/, size 88, link 0, flags 6, type=1
libbpf: sec 'kretprobe/': found program 'trace_func_exit' at insn offset 0 (0 bytes), code size 11 insns (88 bytes)
libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
libbpf: license of main.bpf.o is GPL
libbpf: elf: section(7) maps, size 20, link 0, flags 3, type=1
libbpf: elf: section(16) .BTF, size 1406, link 0, flags 0, type=1
libbpf: elf: section(18) .BTF.ext, size 460, link 0, flags 0, type=1
libbpf: elf: section(24) .symtab, size 2160, link 1, flags 0, type=2
libbpf: looking for externs among 90 symbols...
libbpf: collected 0 externs total
libbpf: elf: found 1 legacy map definitions (20 bytes) in main.bpf.o
libbpf: map 'stackdata_map' (legacy): at sec_idx 7, offset 0.
libbpf: map 87 is "stackdata_map"
libbpf: sec '.relkprobe/': collecting relocation for section(3) 'kprobe/'
libbpf: sec '.relkprobe/': relo #0: insn #20 against 'stackdata_map'
libbpf: prog 'trace_func_entry': found map 0 (stackdata_map, sec 7, off 0) for insn #20
>> Loading eBPF program
libbpf: loading kernel BTF '/usr/lib/debug/boot/vmlinux-4.18.0-25-generic': 0
libbpf: map:stackdata_map container_name:____btf_map_stackdata_map cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?
libbpf: map 'stackdata_map': created successfully, fd=4
libbpf: sec 'kprobe/': found 2 CO-RE relocations
libbpf: CO-RE relocating [0] struct pt_regs: found target candidate [201] struct pt_regs in [vmlinux]
libbpf: prog 'trace_func_entry': relo #0: kind <byte_off> (0), spec is [2] struct pt_regs.di (0:14 @ offset 112)
libbpf: prog 'trace_func_entry': relo #0: matching candidate #0 [201] struct pt_regs.di (0:14 @ offset 112)
libbpf: prog 'trace_func_entry': relo #0: patched insn #2 (ALU/ALU64) imm 112 -> 112
libbpf: prog 'trace_func_entry': relo #1: kind <byte_off> (0), spec is [2] struct pt_regs.si (0:13 @ offset 104)
libbpf: prog 'trace_func_entry': relo #1: matching candidate #0 [201] struct pt_regs.si (0:13 @ offset 104)
libbpf: prog 'trace_func_entry': relo #1: patched insn #9 (ALU/ALU64) imm 104 -> 104
libbpf: sec 'kretprobe/': found 1 CO-RE relocations
libbpf: prog 'trace_func_exit': relo #0: kind <byte_off> (0), spec is [2] struct pt_regs.ax (0:10 @ offset 80)
libbpf: prog 'trace_func_exit': relo #0: matching candidate #0 [201] struct pt_regs.ax (0:10 @ offset 80)
libbpf: prog 'trace_func_exit': relo #0: patched insn #2 (ALU/ALU64) imm 80 -> 80
libbpf: load bpf program failed: Invalid argument
libbpf: failed to load program 'trace_func_entry'
libbpf: failed to load object 'main.bpf.o'
bpf_object__load: -22



============  BPF Code: ============

// Compiled with:
	// clang -I /home/[...]/DATA/90_lib/libbpf/build/root/usr/include/ -target bpf -S -D __BPF_TRACING__ -D__TARGET_ARCH_x86 -Wall -O2 -emit-llvm -c -g main.bpf.c
	// llc-11 -march=bpf -filetype=obj -o main.bpf.o main.bpf.ll
// __TARGET_ARCH_x86: For x86_64 machines, too. (see bpf_tracing.h)

#include "../91_bin/vmlinux.h"

#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

// #include <uapi/linux/bpf.h>  // Conflicts with vmlinux.h
/* flags for both BPF_FUNC_get_stackid and BPF_FUNC_get_stack. */
#define BPF_F_SKIP_FIELD_MASK		0xffULL     // Missing definitions in vmlinux.h
#define BPF_F_USER_STACK		(1ULL << 8)
/* flags used by BPF_FUNC_get_stackid only. */
#define BPF_F_FAST_STACK_CMP		(1ULL << 9)
#define BPF_F_REUSE_STACKID		(1ULL << 10)
/* flags used by BPF_FUNC_get_stack only. */
#define BPF_F_USER_BUILD_ID		(1ULL << 11)

char _license[] SEC("license") = "GPL";

#define MAX_STACK_RAWTP 100
struct stack_trace_t {
	int pid;
	int kern_stack_size;
	int user_stack_size;
	int user_stack_buildid_size;
	__u64 kern_stack[MAX_STACK_RAWTP];
	__u64 user_stack[MAX_STACK_RAWTP];
	struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP];
};

struct bpf_map_def SEC("maps") stackdata_map = {
	.type = BPF_MAP_TYPE_PERCPU_ARRAY,
	.key_size = sizeof(__u32),
	.value_size = sizeof(struct stack_trace_t),
	.max_entries = 1,
};

SEC("kprobe/")
int trace_func_entry(struct pt_regs *ctx)
{
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid;

    {
        // char fmt[] = "Catched function call; PID = : %d.\n";
        // bpf_trace_printk(fmt, sizeof(fmt), pid, sizeof(pid));
    }

    int arg1;
    int arg2;

    arg1 = BPF_CORE_READ(ctx, di);
    arg2 = PT_REGS_PARM2_CORE(ctx);

    {
        // char fmt[] = "  Arg1 = : %u.\n";
        // bpf_trace_printk(fmt, sizeof(fmt), arg1, sizeof(arg1));
    }
    {
        // char fmt[] = "  Arg2 = : %u.\n";
        // bpf_trace_printk(fmt, sizeof(fmt), arg2, sizeof(arg2));
    }

    __u32 key = 0;
    struct stack_trace_t* data;
    data = bpf_map_lookup_elem(&stackdata_map, &key);
	if (!data)
		return 0;

    size_t max_len = MAX_STACK_RAWTP * sizeof(__u64);

    data->user_stack_size = bpf_get_stack(ctx, data->user_stack, max_len, BPF_F_USER_STACK);

    if(data->user_stack_size <= 0)
        return 0;
    
    {
        // char fmt[] = "  Got stack; len = : %u.\n";
        // bpf_trace_printk(fmt, sizeof(fmt), data->user_stack_size, sizeof(data->user_stack_size));
    }

    if(data->user_stack_size > MAX_STACK_RAWTP)
        return 0; // make verifier happy

    // // for(size_t i = 0; i < data->user_stack_size; ++i)
    // #pragma clang loop unroll(full)
    // for(size_t i = 0; i < 20; ++i)
    // {
    //     if(i < data->user_stack_size)
    //     {
    //         u64 stackEntry = data->user_stack[i];
    //         stackEntry += 1;

    //         char val[22];
    //         toHex(stackEntry, val, false);
    //         char fmt[] = "    : %s.\n";
    //         bpf_trace_printk(fmt, sizeof(fmt), val, sizeof(val));
    //     }
    // }

    return 0;
}


SEC("kretprobe/")
int trace_func_exit(struct pt_regs *ctx)
{
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid;
 
    {
        // char fmt[] = "Catched function exit; PID = : %d.\n";
        // bpf_trace_printk(fmt, sizeof(fmt), pid, sizeof(pid));
    }

    int ret;
    //bpf_probe_read_user(&key.c, sizeof(key.c), (void *)PT_REGS_PARM1(ctx));
    // arg1 = ctx->di;     // Automatic CO:RE Relocation and rewriting

    // ret = PT_REGS_RET_CORE(ctx);     // Does NOT work - Result is passed using Register eax
    ret = BPF_CORE_READ(ctx, ax);

    {
        // char fmt[] = "    ret = : %u.\n";
        // bpf_trace_printk(fmt, sizeof(fmt), ret, sizeof(ret));
    }

    return 0;
}



============ Loader code ============

// Compiled with 
	// g++ -I /home/[...]/DATA/90_lib/libbpf/build/root/usr/include/ -L../90_lib/libbpf/build/root/usr/lib64 \
	//	-l:libbpf.a \
	//	-o ebpf main.cc -Wl,--copy-dt-needed-entries /home/[...]/DATA/90_lib/libbpf/build/root/usr/lib64/libbpf.a -B static -lelf

#include <iostream>
#include <thread>
#include <chrono>
#include <unistd.h>
#include <fstream>
#include <dirent.h>

#include <linux/bpf.h>
enum bpf_stats_type {           // Should be defined in linux/bpf.h,. but is not (before Kernel 5.8)
	BPF_STATS_RUN_TIME = 0,         // used in libbpf/build/root/usr/include/bpf/bpf.h
};

#include <bpf/bpf.h>
// #include "../91_bin/vmlinux.h"
#include <bpf/libbpf.h>

#include <linux/ptrace.h>
#include <sys/resource.h>

using namespace std;

void bump_memlock_rlimit(void)
{
	struct rlimit rlim_new = {
		.rlim_cur	= RLIM_INFINITY,
		.rlim_max	= RLIM_INFINITY,
	};

	if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
		fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
		exit(1);
	}
}


int print_libbpf_log(enum libbpf_print_level lvl, const char *fmt, va_list args)
{
    return vfprintf(stderr, fmt, args);
}


int getProcIdByName(string procName)
{
    int pid = -1;

    // Open the /proc directory
    DIR *dp = opendir("/proc");
    if (dp != NULL)
    {
        // Enumerate all entries in directory until process found
        struct dirent *dirp;
        while (pid < 0 && (dirp = readdir(dp)))
        {
            // Skip non-numeric entries
            int id = atoi(dirp->d_name);
            if (id > 0)
            {
                // Read contents of virtual /proc/{pid}/cmdline file
                string cmdPath = string("/proc/") + dirp->d_name + "/cmdline";
                ifstream cmdFile(cmdPath.c_str());
                string cmdLine;
                getline(cmdFile, cmdLine);
                if (!cmdLine.empty())
                {
                    // Keep first cmdline item which contains the program path
                    size_t pos = cmdLine.find('\0');
                    if (pos != string::npos)
                        cmdLine = cmdLine.substr(0, pos);
                    // Keep program name only, removing the path
                    pos = cmdLine.rfind('/');
                    if (pos != string::npos)
                        cmdLine = cmdLine.substr(pos + 1);
                    // Compare against requested process name
                    if (procName == cmdLine)
                        pid = id;
                }
            }
        }
    }
    closedir(dp);
    return pid;
}



int main (int argc, char ** argv)
{
    bump_memlock_rlimit();
    libbpf_set_print(print_libbpf_log); /* set custom log handler */

    int prog_fd ;

    struct bpf_object_open_opts* openOpts = (struct bpf_object_open_opts*) calloc(1, sizeof(bpf_object_open_opts));
    openOpts->sz = sizeof(openOpts);
    openOpts->btf_custom_path = "./vmlinux";           // Custom BTF path - currently ignored? BTF loaded from /sys/kernel/btf/vmlinux or /usr/lib/debug/boot/vmlinux-4.18.0-25-generic
    struct bpf_object* main_bpf_obj = bpf_object__open_file("main.bpf.o", openOpts);

    if(main_bpf_obj == nullptr
    {
        cout << "Error loading bpf object: nullptr" << endl;
        return -1;
    }

    // bpf_object__set_kversion(struct bpf_object *obj, __u32 kern_version);       // For kProbes. Where to get the kernel version as u32?
    cout << ">> Loading eBPF program" << endl;
    int ret = bpf_object__load(main_bpf_obj);
    cout << "bpf_object__load: " << ret << endl;

    struct bpf_program * prog = bpf_object__find_program_by_name(main_bpf_obj, "trace_func_entry");
    struct bpf_program * retProbe = bpf_object__find_program_by_name(main_bpf_obj, "trace_func_exit");

    int pid = getProcIdByName("testApp");
    if(pid == -1)
    {
        cout << "Can not find testApp" << endl;
        return 0;
    }
    else
    {
        cout << "Found testApp with PID " << pid << endl;
    }


    cout << "Setting up Link" << endl;
    DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
    uprobe_opts.retprobe = false;
	struct bpf_link *uprobe_link;
    struct bpf_link *uretprobe_link;

    uprobe_link = bpf_program__attach_uprobe_opts(prog,
						      pid /* pid */,
						      "/home/[...]/DATA/Test_uProbe/testApp",
						      0x1209,		// int testApp::calc(int, int) function entry
						      &uprobe_opts);
    
    cout << "Setting up Link retprobe" << endl;

    uretprobe_link = bpf_program__attach_uprobe(retProbe, true,
                            pid,
                            "/home/[...]/DATA/Test_uProbe/testApp",
                            0x1209);


    cout << "Main loop" << endl;
    while(true)
    {
        this_thread::sleep_for(chrono::milliseconds(1000));
    }

    return 0;
}





============ testApp ============

// Compiled with g++ -o testApp testApp.cc

#include <iostream>
#include <chrono>
#include <thread>
#include <string>

using namespace std;

int calc(int a, int b)
{
    return a + b;
}

int main()
{
    int i = 0;

    while(true)
    {
        cout << calc(i, 1) << endl;
        this_thread::sleep_for(chrono::milliseconds(1000));
        ++i;
    }
    return 0;
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL
  2022-01-05 10:03 Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL Buchberger, Dennis
@ 2022-01-05 10:43 ` Greg KH
  2022-01-05 18:20   ` AW: [Extern] " Buchberger, Dennis
  2022-01-06  4:55 ` Andrii Nakryiko
  1 sibling, 1 reply; 7+ messages in thread
From: Greg KH @ 2022-01-05 10:43 UTC (permalink / raw)
  To: Buchberger, Dennis; +Cc: bpf

On Wed, Jan 05, 2022 at 10:03:30AM +0000, Buchberger, Dennis wrote:
> Hello :)
> 
> I am currently having a problem and hope you can help me: My goal is to develop a BPF-program (see below) on a development machine and then deploy it to another machine to run it there using BPF CO:RE.
> But the program does not load; bpf_object__load returns -EINVAL.
> 
> Development machine:
> - Ubuntu 20.04 LTS
> - Linux 5.4.0-90-generic x86_64
> - Kernel compiled with CONFIG_DEBUG_INFO_BTF=y, so BTF is available under /sys/kernel/btf/vmlinux
> - clang version: 10.0.0-4ubuntu1
> - llc version: 10.0.0
> 
> Target machine:
> - Ubuntu 18.10
> - Linux 4.18.0-25-generic x86_64

4.18 is very old and obsolete and insecure and only supported by the
vendor you are paying support from.  Please upgrade to a more modern
kernel (4.18 was released way back in 2018), if you wish to get help
from the kernel community.

Actually, the vendor you are paying for support to stay at this old
kernel version should be able to provide help to you, why not ask them?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 7+ messages in thread

* AW: [Extern] Re: Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL
  2022-01-05 10:43 ` Greg KH
@ 2022-01-05 18:20   ` Buchberger, Dennis
  0 siblings, 0 replies; 7+ messages in thread
From: Buchberger, Dennis @ 2022-01-05 18:20 UTC (permalink / raw)
  To: Greg KH; +Cc: bpf

>> Hello :)
>>
>> I am currently having a problem and hope you can help me: My goal is to develop a BPF-program (see below) on a development machine and then deploy it to another machine to run it there using BPF CO:RE.
>> But the program does not load; bpf_object__load returns -EINVAL.
>>
>> Development machine:
>> - Ubuntu 20.04 LTS
>> - Linux 5.4.0-90-generic x86_64
>> - Kernel compiled with CONFIG_DEBUG_INFO_BTF=y, so BTF is available under /sys/kernel/btf/vmlinux
>> - clang version: 10.0.0-4ubuntu1
>> - llc version: 10.0.0
>>
>> Target machine:
>> - Ubuntu 18.10
>> - Linux 4.18.0-25-generic x86_64
>
> 4.18 is very old and obsolete and insecure and only supported by the
> vendor you are paying support from.  Please upgrade to a more modern
> kernel (4.18 was released way back in 2018), if you wish to get help
> from the kernel community.
> 
> Actually, the vendor you are paying for support to stay at this old
> kernel version should be able to provide help to you, why not ask them?
> 
> thanks,
> 
> greg k-h

Ubuntu 18.04 LTS is still out there and did not reach its end of maintenance; 18.10 is even a bit newer. So yes, it is not up to date, but I would not consider it very old or obsolete.
Actually, I am a student and not paying any vendor I could ask.

BPF CO:RE stands for Compile Once, Run >Everywhere<, so I do wonder why it does not work - it should, no matter wether it is kernel 4.18 or another one, should't it?.

I just get started to eBPF programming and find it difficult to get documentation and examples on how to do it in a not-deprecated way without using bcc, bpftrace or skeletons.

It is quite a simple program, why does it fail getting loaded on 4.18 but not on 5.4?:

SEC("kprobe/")
int trace_func_entry(struct pt_regs *ctx) {
    u64 pid_tgid = bpf_get_current_pid_tgid();
    u32 pid = pid_tgid;

    int arg1;
    int arg2;

    arg1 = BPF_CORE_READ(ctx, di);
    arg2 = PT_REGS_PARM2_CORE(ctx);

    __u32 key = 0;
    struct stack_trace_t* data;
    data = bpf_map_lookup_elem(&stackdata_map, &key);
	if (!data)
		return 0;

    size_t max_len = MAX_STACK_RAWTP * sizeof(__u64);
    data->user_stack_size = bpf_get_stack(ctx, data->user_stack, max_len, BPF_F_USER_STACK);
    return 0;
}

Thanks for any help
Dennis


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL
  2022-01-05 10:03 Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL Buchberger, Dennis
  2022-01-05 10:43 ` Greg KH
@ 2022-01-06  4:55 ` Andrii Nakryiko
  2022-01-06 16:53   ` AW: [Extern] " Buchberger, Dennis
  1 sibling, 1 reply; 7+ messages in thread
From: Andrii Nakryiko @ 2022-01-06  4:55 UTC (permalink / raw)
  To: Buchberger, Dennis; +Cc: bpf

On Wed, Jan 5, 2022 at 2:12 PM Buchberger, Dennis
<dennis.buchberger@hs-osnabrueck.de> wrote:
>
> Hello :)
>
> I am currently having a problem and hope you can help me: My goal is to develop a BPF-program (see below) on a development machine and then deploy it to another machine to run it there using BPF CO:RE.
> But the program does not load; bpf_object__load returns -EINVAL.
>
> Development machine:
> - Ubuntu 20.04 LTS
> - Linux 5.4.0-90-generic x86_64
> - Kernel compiled with CONFIG_DEBUG_INFO_BTF=y, so BTF is available under /sys/kernel/btf/vmlinux
> - clang version: 10.0.0-4ubuntu1
> - llc version: 10.0.0
>
> Target machine:
> - Ubuntu 18.10
> - Linux 4.18.0-25-generic x86_64
> - clang version: 13.0.0
> - llc version: 13.0.0
>
> As the target kernel does not support CONFIG_DEBUG_INFO_BTF, I used pahole -J (v1.22) to create vmlinux file with BTF info embedded there.
> Basically, I followed this mails: https://lore.kernel.org/bpf/CADmGQ+1euj7Uv9e8UyZMMXDiYAKqXe9=GSTBFNbbg1E0R-ejyg@mail.gmail.com/
>
> Right now, the bpf program is just a uProbe for a simple test app, which writes some output to the tracing pipe. As Kernel 4.18. does not support global data for bpf programs, I had to remove (comment out) the bpf_trace_printk statements.

You can do #define BPF_NO_GLOBAL_DATA before including bpf_helpers.h
and then you can still use bpf_printk() helper macro.


> On the development machine, it works fine. But on the target machine, loading the program fails: libbpf: load bpf program failed: Invalid argument (full libbpf log see below).
> When compiling the programs on the target machine without using CO:RE, I get a similar error (invalid argument, -22).
> What could be the problem? I don't think the eBPF program uses anything that is available on Kernel 5.4.0 and not available on the system with Kernel 4.18, does it?
>
> Thanks in advance for your help.
> Best
> Dennis
>
>
>
>
> ============ log ============
>
> sudo ./ebpf
> libbpf: loading main.bpf.o
> libbpf: elf: section(3) kprobe/, size 272, link 0, flags 6, type=1
> libbpf: sec 'kprobe/': found program 'trace_func_entry' at insn offset 0 (0 bytes), code size 34 insns (272 bytes)
> libbpf: elf: section(4) .relkprobe/, size 16, link 24, flags 0, type=9
> libbpf: elf: section(5) kretprobe/, size 88, link 0, flags 6, type=1
> libbpf: sec 'kretprobe/': found program 'trace_func_exit' at insn offset 0 (0 bytes), code size 11 insns (88 bytes)
> libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
> libbpf: license of main.bpf.o is GPL
> libbpf: elf: section(7) maps, size 20, link 0, flags 3, type=1
> libbpf: elf: section(16) .BTF, size 1406, link 0, flags 0, type=1
> libbpf: elf: section(18) .BTF.ext, size 460, link 0, flags 0, type=1
> libbpf: elf: section(24) .symtab, size 2160, link 1, flags 0, type=2
> libbpf: looking for externs among 90 symbols...
> libbpf: collected 0 externs total
> libbpf: elf: found 1 legacy map definitions (20 bytes) in main.bpf.o
> libbpf: map 'stackdata_map' (legacy): at sec_idx 7, offset 0.
> libbpf: map 87 is "stackdata_map"
> libbpf: sec '.relkprobe/': collecting relocation for section(3) 'kprobe/'
> libbpf: sec '.relkprobe/': relo #0: insn #20 against 'stackdata_map'
> libbpf: prog 'trace_func_entry': found map 0 (stackdata_map, sec 7, off 0) for insn #20
> >> Loading eBPF program
> libbpf: loading kernel BTF '/usr/lib/debug/boot/vmlinux-4.18.0-25-generic': 0
> libbpf: map:stackdata_map container_name:____btf_map_stackdata_map cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?
> libbpf: map 'stackdata_map': created successfully, fd=4
> libbpf: sec 'kprobe/': found 2 CO-RE relocations
> libbpf: CO-RE relocating [0] struct pt_regs: found target candidate [201] struct pt_regs in [vmlinux]
> libbpf: prog 'trace_func_entry': relo #0: kind <byte_off> (0), spec is [2] struct pt_regs.di (0:14 @ offset 112)
> libbpf: prog 'trace_func_entry': relo #0: matching candidate #0 [201] struct pt_regs.di (0:14 @ offset 112)
> libbpf: prog 'trace_func_entry': relo #0: patched insn #2 (ALU/ALU64) imm 112 -> 112
> libbpf: prog 'trace_func_entry': relo #1: kind <byte_off> (0), spec is [2] struct pt_regs.si (0:13 @ offset 104)
> libbpf: prog 'trace_func_entry': relo #1: matching candidate #0 [201] struct pt_regs.si (0:13 @ offset 104)
> libbpf: prog 'trace_func_entry': relo #1: patched insn #9 (ALU/ALU64) imm 104 -> 104
> libbpf: sec 'kretprobe/': found 1 CO-RE relocations
> libbpf: prog 'trace_func_exit': relo #0: kind <byte_off> (0), spec is [2] struct pt_regs.ax (0:10 @ offset 80)
> libbpf: prog 'trace_func_exit': relo #0: matching candidate #0 [201] struct pt_regs.ax (0:10 @ offset 80)
> libbpf: prog 'trace_func_exit': relo #0: patched insn #2 (ALU/ALU64) imm 80 -> 80

CO-RE relocations succeeded, btf_custom_path worked, the problem is
not in CO-RE.

> libbpf: load bpf program failed: Invalid argument
> libbpf: failed to load program 'trace_func_entry'

I suspect this is due to your target machine running Ubuntu 18.10.
Ubuntu has infamous problem with reporting kernel version through
uname() syscall. I've just improved libbpf's detection of it few days
ago (see [0]), but it didn't yet make it into Github mirror of libbpf.
I'm going to start the sync right now, but you can manually specify
correct version code with bpf_object__set_kversion() as you already
realized. See how I do that in my patch [0], you can do that manually
as well.

  [0] https://patchwork.kernel.org/project/netdevbpf/patch/20211222231003.2334940-1-andrii@kernel.org/

> libbpf: failed to load object 'main.bpf.o'
> bpf_object__load: -22
>
>
>

[...]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* AW: [Extern] Re: Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL
  2022-01-06  4:55 ` Andrii Nakryiko
@ 2022-01-06 16:53   ` Buchberger, Dennis
  2022-01-06 20:17     ` Andrii Nakryiko
  0 siblings, 1 reply; 7+ messages in thread
From: Buchberger, Dennis @ 2022-01-06 16:53 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: bpf

> >  [...]
> > As the target kernel does not support CONFIG_DEBUG_INFO_BTF, I used pahole -J (v1.22) to create vmlinux file with BTF info embedded there.
> > Basically, I followed this mails:
> > https://urldefense.com/v3/__https://lore.kernel.org/bpf/CADmGQ*1euj7Uv
> > 9e8UyZMMXDiYAKqXe9=GSTBFNbbg1E0R-ejyg@mail.gmail.com/__;Kw!!MeVeBiz6!5
> > PZT7QBM-W93AhbZnRJ3kmTO4JyBUiapxeJrPCl4k4gKHidI5Ri0WQp19MbBDFP1nWOL3A$
> >
> > Right now, the bpf program is just a uProbe for a simple test app, which writes some output to the tracing pipe. As Kernel 4.18. does not support global data for bpf programs, I had to remove (comment out) the bpf_trace_printk statements.
>
> You can do #define BPF_NO_GLOBAL_DATA before including bpf_helpers.h and then you can still use bpf_printk() helper macro.
>

Thank you! That's really helpful. Is there any collection of up-to-date documentation and best practices in writing bpf code (without skeletons) besides the sources in libbpf/libbpf-bootstrap, iovisor /libbpf-tools and linux/tools/testing/selftests/bpf ?


>
> > On the development machine, it works fine. But on the target machine, loading the program fails: libbpf: load bpf program failed: Invalid argument (full libbpf log see below).
> > When compiling the programs on the target machine without using CO:RE, I get a similar error (invalid argument, -22).
> > What could be the problem? I don't think the eBPF program uses anything that is available on Kernel 5.4.0 and not available on the system with Kernel 4.18, does it?
> >
> > Thanks in advance for your help.
> > Best
> > Dennis
> >
> >
> >
> >
> > ============ log ============
> >
> > sudo ./ebpf
> > libbpf: loading main.bpf.o
> > [...]
> > libbpf: CO-RE relocating [0] struct pt_regs: found target candidate
> > [201] struct pt_regs in [vmlinux]
> > libbpf: prog 'trace_func_entry': relo #0: kind <byte_off> (0), spec is
> > [2] struct pt_regs.di (0:14 @ offset 112)
> > libbpf: prog 'trace_func_entry': relo #0: matching candidate #0 [201]
> > struct pt_regs.di (0:14 @ offset 112)
> > libbpf: prog 'trace_func_entry': relo #0: patched insn #2 (ALU/ALU64)
> > imm 112 -> 112
> > libbpf: prog 'trace_func_entry': relo #1: kind <byte_off> (0), spec is
> > [2] struct pt_regs.si (0:13 @ offset 104)
> > libbpf: prog 'trace_func_entry': relo #1: matching candidate #0 [201]
> > struct pt_regs.si (0:13 @ offset 104)
> > libbpf: prog 'trace_func_entry': relo #1: patched insn #9 (ALU/ALU64)
> > imm 104 -> 104
> > libbpf: sec 'kretprobe/': found 1 CO-RE relocations
> > libbpf: prog 'trace_func_exit': relo #0: kind <byte_off> (0), spec is
> > [2] struct pt_regs.ax (0:10 @ offset 80)
> > libbpf: prog 'trace_func_exit': relo #0: matching candidate #0 [201]
> > struct pt_regs.ax (0:10 @ offset 80)
> > libbpf: prog 'trace_func_exit': relo #0: patched insn #2 (ALU/ALU64)
> > imm 80 -> 80
>
> CO-RE relocations succeeded, btf_custom_path worked, the problem is not in CO-RE.
>
> > libbpf: load bpf program failed: Invalid argument
> > libbpf: failed to load program 'trace_func_entry'
>
> I suspect this is due to your target machine running Ubuntu 18.10.
> Ubuntu has infamous problem with reporting kernel version through
> uname() syscall. I've just improved libbpf's detection of it few days ago (see [0]), but it didn't yet make it into Github mirror of libbpf.
> I'm going to start the sync right now, but you can manually specify correct version code with bpf_object__set_kversion() as you already realized. See how I do that in my patch [0], you can do that manually as well.
>
>   [0] https://urldefense.com/v3/__https://patchwork.kernel.org/project/netdevbpf/patch/20211222231003.2334940-1-andrii@kernel.org/__;!!MeVeBiz6!5PZT7QBM-W93AhbZnRJ3kmTO4JyBUiapxeJrPCl4k4gKHidI5Ri0WQp19MbBDFM_zuNNKA$

That's it, thank you very much!

I just added
	__u32 currKernelVersion = get_kernel_version();
	bpf_object__set_kversion(main_bpf_obj, currKernelVersion)
with get_kernel_version() from libbpf.c and your patch [0] and now it is working. :)

However, there is something I do not understand:
(a): Why did it work on the development machine in the first place with Ubuntu 20.04?
	- the old get_kernel_version() returned 328704 (5.4.0), the new version returns 328852 (5.4.148) so there already is a missmatch. (and I did not call it, so libbpf set the kernel version to 0?)
	- on the target machine, it is 266752 (4.2.0) vs. 266772 (4.2.4)
(b): I use a uProbe. Why is the bpf program type kProbe? Is it just for usability of libbpf as for a uProbe the user must specify the address while for a kprobe only the symbol is required?
(c): Why does the kernel version matter at all?

It would be really nice if you could answer these questions as well or point me to a source.

Best
Dennis

[...]


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Extern] Re: Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL
  2022-01-06 16:53   ` AW: [Extern] " Buchberger, Dennis
@ 2022-01-06 20:17     ` Andrii Nakryiko
  2022-01-07  9:30       ` AW: " Buchberger, Dennis
  0 siblings, 1 reply; 7+ messages in thread
From: Andrii Nakryiko @ 2022-01-06 20:17 UTC (permalink / raw)
  To: Buchberger, Dennis; +Cc: bpf

On Thu, Jan 6, 2022 at 8:53 AM Buchberger, Dennis
<dennis.buchberger@hs-osnabrueck.de> wrote:
>
> > >  [...]
> > > As the target kernel does not support CONFIG_DEBUG_INFO_BTF, I used pahole -J (v1.22) to create vmlinux file with BTF info embedded there.
> > > Basically, I followed this mails:
> > > https://urldefense.com/v3/__https://lore.kernel.org/bpf/CADmGQ*1euj7Uv
> > > 9e8UyZMMXDiYAKqXe9=GSTBFNbbg1E0R-ejyg@mail.gmail.com/__;Kw!!MeVeBiz6!5
> > > PZT7QBM-W93AhbZnRJ3kmTO4JyBUiapxeJrPCl4k4gKHidI5Ri0WQp19MbBDFP1nWOL3A$
> > >
> > > Right now, the bpf program is just a uProbe for a simple test app, which writes some output to the tracing pipe. As Kernel 4.18. does not support global data for bpf programs, I had to remove (comment out) the bpf_trace_printk statements.
> >
> > You can do #define BPF_NO_GLOBAL_DATA before including bpf_helpers.h and then you can still use bpf_printk() helper macro.
> >
>
> Thank you! That's really helpful. Is there any collection of up-to-date documentation and best practices in writing bpf code (without skeletons) besides the sources in libbpf/libbpf-bootstrap, iovisor /libbpf-tools and linux/tools/testing/selftests/bpf ?

There are also various blog posts on the Internet. I tried to do my
part with CO-RE at [0], but I don't think there is any single
documentation that captures all possible issues in one place (and I
don't think it's possible, there are just way too many variables to
anticipate all possible problems).

  [0] https://nakryiko.com/posts/bpf-core-reference-guide/

>
>
> >
> > > On the development machine, it works fine. But on the target machine, loading the program fails: libbpf: load bpf program failed: Invalid argument (full libbpf log see below).
> > > When compiling the programs on the target machine without using CO:RE, I get a similar error (invalid argument, -22).
> > > What could be the problem? I don't think the eBPF program uses anything that is available on Kernel 5.4.0 and not available on the system with Kernel 4.18, does it?
> > >
> > > Thanks in advance for your help.
> > > Best
> > > Dennis
> > >
> > >
> > >
> > >
> > > ============ log ============
> > >
> > > sudo ./ebpf
> > > libbpf: loading main.bpf.o
> > > [...]
> > > libbpf: CO-RE relocating [0] struct pt_regs: found target candidate
> > > [201] struct pt_regs in [vmlinux]
> > > libbpf: prog 'trace_func_entry': relo #0: kind <byte_off> (0), spec is
> > > [2] struct pt_regs.di (0:14 @ offset 112)
> > > libbpf: prog 'trace_func_entry': relo #0: matching candidate #0 [201]
> > > struct pt_regs.di (0:14 @ offset 112)
> > > libbpf: prog 'trace_func_entry': relo #0: patched insn #2 (ALU/ALU64)
> > > imm 112 -> 112
> > > libbpf: prog 'trace_func_entry': relo #1: kind <byte_off> (0), spec is
> > > [2] struct pt_regs.si (0:13 @ offset 104)
> > > libbpf: prog 'trace_func_entry': relo #1: matching candidate #0 [201]
> > > struct pt_regs.si (0:13 @ offset 104)
> > > libbpf: prog 'trace_func_entry': relo #1: patched insn #9 (ALU/ALU64)
> > > imm 104 -> 104
> > > libbpf: sec 'kretprobe/': found 1 CO-RE relocations
> > > libbpf: prog 'trace_func_exit': relo #0: kind <byte_off> (0), spec is
> > > [2] struct pt_regs.ax (0:10 @ offset 80)
> > > libbpf: prog 'trace_func_exit': relo #0: matching candidate #0 [201]
> > > struct pt_regs.ax (0:10 @ offset 80)
> > > libbpf: prog 'trace_func_exit': relo #0: patched insn #2 (ALU/ALU64)
> > > imm 80 -> 80
> >
> > CO-RE relocations succeeded, btf_custom_path worked, the problem is not in CO-RE.
> >
> > > libbpf: load bpf program failed: Invalid argument
> > > libbpf: failed to load program 'trace_func_entry'
> >
> > I suspect this is due to your target machine running Ubuntu 18.10.
> > Ubuntu has infamous problem with reporting kernel version through
> > uname() syscall. I've just improved libbpf's detection of it few days ago (see [0]), but it didn't yet make it into Github mirror of libbpf.
> > I'm going to start the sync right now, but you can manually specify correct version code with bpf_object__set_kversion() as you already realized. See how I do that in my patch [0], you can do that manually as well.
> >
> >   [0] https://urldefense.com/v3/__https://patchwork.kernel.org/project/netdevbpf/patch/20211222231003.2334940-1-andrii@kernel.org/__;!!MeVeBiz6!5PZT7QBM-W93AhbZnRJ3kmTO4JyBUiapxeJrPCl4k4gKHidI5Ri0WQp19MbBDFM_zuNNKA$
>
> That's it, thank you very much!
>
> I just added
>         __u32 currKernelVersion = get_kernel_version();
>         bpf_object__set_kversion(main_bpf_obj, currKernelVersion)
> with get_kernel_version() from libbpf.c and your patch [0] and now it is working. :)
>

Great, once [1] is merged (I'll need to fix up selftests first),
libbpf will be able to deal with this Ubuntu quirk automatically and
you'll never know it existed.

  [1] https://github.com/libbpf/libbpf/pull/435

> However, there is something I do not understand:
> (a): Why did it work on the development machine in the first place with Ubuntu 20.04?
>         - the old get_kernel_version() returned 328704 (5.4.0), the new version returns 328852 (5.4.148) so there already is a missmatch. (and I did not call it, so libbpf set the kernel version to 0?)

You dev machine has recent enough kernel that doesn't check kernel
version anymore, so it doesn't matter that Ubuntu reports the wrong
one.

>         - on the target machine, it is 266752 (4.2.0) vs. 266772 (4.2.4)
> (b): I use a uProbe. Why is the bpf program type kProbe? Is it just for usability of libbpf as for a uProbe the user must specify the address while for a kprobe only the symbol is required?

4.2 is old enough where kernel version has to match and it didn't.


> (c): Why does the kernel version matter at all?
>
> It would be really nice if you could answer these questions as well or point me to a source.
>
> Best
> Dennis
>
> [...]
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* AW: [Extern] Re: Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL
  2022-01-06 20:17     ` Andrii Nakryiko
@ 2022-01-07  9:30       ` Buchberger, Dennis
  0 siblings, 0 replies; 7+ messages in thread
From: Buchberger, Dennis @ 2022-01-07  9:30 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: bpf

> > > >  [...]
> > > > As the target kernel does not support CONFIG_DEBUG_INFO_BTF, I used pahole -J (v1.22) to create vmlinux file with BTF info embedded there.
> > > > Basically, I followed this mails:
> > > > https://urldefense.com/v3/__https://lore.kernel.org/bpf/CADmGQ*1euj7Uv
> > > > 9e8UyZMMXDiYAKqXe9=GSTBFNbbg1E0R-ejyg@mail.gmail.com/__;Kw!!MeVeBiz6!5
> > > > PZT7QBM-W93AhbZnRJ3kmTO4JyBUiapxeJrPCl4k4gKHidI5Ri0WQp19MbBDFP1nWOL3A$
> > > >
> > > > Right now, the bpf program is just a uProbe for a simple test app, which writes some output to the tracing pipe. As Kernel 4.18. does not support global data for bpf programs, I had to 
remove (comment out) the bpf_trace_printk statements.
> > >
> > > You can do #define BPF_NO_GLOBAL_DATA before including bpf_helpers.h and then you can still use bpf_printk() helper macro.
> > >
> >
> > Thank you! That's really helpful. Is there any collection of up-to-date documentation and best practices in writing bpf code (without skeletons) besides the sources in libbpf/libbpf-bootstrap, iovisor /libbpf-tools and linux/tools/testing/selftests/bpf ?
>
> There are also various blog posts on the Internet. I tried to do my
> part with CO-RE at [0], but I don't think there is any single
> documentation that captures all possible issues in one place (and I
> don't think it's possible, there are just way too many variables to
> anticipate all possible problems).
>
>   [0] https://nakryiko.com/posts/bpf-core-reference-guide/

What a pity. ok thanks!


> >
> >
> > >
> > > > On the development machine, it works fine. But on the target machine, loading the program fails: libbpf: load bpf program failed: Invalid argument (full libbpf log see below).
> > > > When compiling the programs on the target machine without using CO:RE, I get a similar error (invalid argument, -22).
> > > > What could be the problem? I don't think the eBPF program uses anything that is available on Kernel 5.4.0 and not available on the system with Kernel 4.18, does it?
> > > >
> > > > Thanks in advance for your help.
> > > > Best
> > > > Dennis
> > > >
> > > >
> > > >
> > > >
> > > > ============ log ============
> > > >
> > > > sudo ./ebpf
> > > > libbpf: loading main.bpf.o
> > > > [...]
> > > > libbpf: CO-RE relocating [0] struct pt_regs: found target candidate
> > > > [201] struct pt_regs in [vmlinux]
> > > > libbpf: prog 'trace_func_entry': relo #0: kind <byte_off> (0), spec is
> > > > [2] struct pt_regs.di (0:14 @ offset 112)
> > > > libbpf: prog 'trace_func_entry': relo #0: matching candidate #0 [201]
> > > > struct pt_regs.di (0:14 @ offset 112)
> > > > libbpf: prog 'trace_func_entry': relo #0: patched insn #2 (ALU/ALU64)
> > > > imm 112 -> 112
> > > > libbpf: prog 'trace_func_entry': relo #1: kind <byte_off> (0), spec is
> > > > [2] struct pt_regs.si (0:13 @ offset 104)
> > > > libbpf: prog 'trace_func_entry': relo #1: matching candidate #0 [201]
> > > > struct pt_regs.si (0:13 @ offset 104)
> > > > libbpf: prog 'trace_func_entry': relo #1: patched insn #9 (ALU/ALU64)
> > > > imm 104 -> 104
> > > > libbpf: sec 'kretprobe/': found 1 CO-RE relocations
> > > > libbpf: prog 'trace_func_exit': relo #0: kind <byte_off> (0), spec is
> > > > [2] struct pt_regs.ax (0:10 @ offset 80)
> > > > libbpf: prog 'trace_func_exit': relo #0: matching candidate #0 [201]
> > > > struct pt_regs.ax (0:10 @ offset 80)
> > > > libbpf: prog 'trace_func_exit': relo #0: patched insn #2 (ALU/ALU64)
> > > > imm 80 -> 80
> > >
> > > CO-RE relocations succeeded, btf_custom_path worked, the problem is not in CO-RE.
> > >
> > > > libbpf: load bpf program failed: Invalid argument
> > > > libbpf: failed to load program 'trace_func_entry'
> > >
> > > I suspect this is due to your target machine running Ubuntu 18.10.
> > > Ubuntu has infamous problem with reporting kernel version through
> > > uname() syscall. I've just improved libbpf's detection of it few days ago (see [0]), but it didn't yet make it into Github mirror of libbpf.
> > > I'm going to start the sync right now, but you can manually specify correct version code with bpf_object__set_kversion() as you already realized. See how I do that in my patch [0], you can do that manually as well.
> > >
> > >   [0] https://urldefense.com/v3/__https://patchwork.kernel.org/project/netdevbpf/patch/20211222231003.2334940-1-andrii@kernel.org/__;!!MeVeBiz6!5PZT7QBM-W93AhbZnRJ3kmTO4JyBUiapxeJrPCl4k4gKHidI5Ri0WQp19MbBDFM_zuNNKA$
> >
> > That's it, thank you very much!
> >
> > I just added
> >         __u32 currKernelVersion = get_kernel_version();
> >         bpf_object__set_kversion(main_bpf_obj, currKernelVersion)
> > with get_kernel_version() from libbpf.c and your patch [0] and now it is working. :)
> >
>
> Great, once [1] is merged (I'll need to fix up selftests first),
> libbpf will be able to deal with this Ubuntu quirk automatically and
> you'll never know it existed.
>
>   [1] https://github.com/libbpf/libbpf/pull/435
>
> > However, there is something I do not understand:
> > (a): Why did it work on the development machine in the first place with Ubuntu 20.04?
> >         - the old get_kernel_version() returned 328704 (5.4.0), the new version returns 328852 (5.4.148) so there already is a missmatch. (and I did not call it, so libbpf set the kernel version to 0?)
>
> You dev machine has recent enough kernel that doesn't check kernel
> version anymore, so it doesn't matter that Ubuntu reports the wrong
> one.
>
> >         - on the target machine, it is 266752 (4.2.0) vs. 266772 (4.2.4)
> > (b): I use a uProbe. Why is the bpf program type kProbe? Is it just for usability of libbpf as for a uProbe the user must specify the address while for a kprobe only the symbol is required?>
> 4.2 is old enough where kernel version has to match and it didn't.
>

Thank you!


> > (c): Why does the kernel version matter at all?
> >
> > It would be really nice if you could answer these questions as well or point me to a source.
> >
> > Best
> > Dennis
> >
> > [...]
> >
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-01-07  9:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-05 10:03 Problem loading eBPF program on Kernel 4.18 (best with CO:RE): -EINVAL Buchberger, Dennis
2022-01-05 10:43 ` Greg KH
2022-01-05 18:20   ` AW: [Extern] " Buchberger, Dennis
2022-01-06  4:55 ` Andrii Nakryiko
2022-01-06 16:53   ` AW: [Extern] " Buchberger, Dennis
2022-01-06 20:17     ` Andrii Nakryiko
2022-01-07  9:30       ` AW: " Buchberger, Dennis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.