Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.rodata: map create: read- and write-only maps not supported (requires >= v5.2) #628

Closed
cfc4n opened this issue Apr 19, 2022 · 2 comments
Closed
Labels
bug Something isn't working

Comments

@cfc4n
Copy link
Contributor

cfc4n commented Apr 19, 2022

Describe the bug

cant load ebpf bytecode with cilium/ebpf library on linux kernel 4.18.0 .

To Reproduce

  1. git clone https://github.com/cfc4n/ebpf-demo.git
  2. cd no-btf-load-failed
  3. make
  4. ./no-btf-load-failed

change this code between L19 and L22
via:
uretprobe.c#L18-L22

// loading objects: field UretprobeBashReadline: program uretprobe_bash_readline: map .rodata: map create: read- and write-only maps not supported (requires >= v5.2)
const volatile u64 target_pid = 0;

// loading objects: field UretprobeBashReadline: program uretprobe_bash_readline: load program without BTF: invalid argument: unrecognized bpf_ld_imm64 insn
//u64 target_pid = 0;

### A global variable with const
code:
```c
const volatile u64 target_pid = 0;
...
SEC("uretprobe/bash_readline")
int uretprobe_bash_readline(struct pt_regs *ctx) {
......
    if (target_pid != 0 && target_pid != pid) {
        return 0;
    }
......
}

Error info

loading objects: field UretprobeBashReadline: program uretprobe_bash_readline: map .rodata: map create: read- and write-only maps not supported (requires >= v5.2)

ELF section info

[root@cnxc-ebpf no-btf-load-failed]# llvm-objdump -dj .rodata bpf_bpfeb.o

bpf_bpfeb.o:	file format elf64-bpf

Disassembly of section .rodata:

0000000000000000 <target_pid>:
		...

B global variable with normal defined

code:

u64 target_pid = 0;
...
SEC("uretprobe/bash_readline")
int uretprobe_bash_readline(struct pt_regs *ctx) {
......
    if (target_pid != 0 && target_pid != pid) {
        return 0;
    }
......
}

Error info

loading objects: field UretprobeBashReadline: program uretprobe_bash_readline: load program without BTF: invalid argument: unrecognized bpf_ld_imm64 insn

ELF section info

[root@cnxc-ebpf no-btf-load-failed]# llvm-objdump -dj .bss bpf_bpfeb.o

bpf_bpfeb.o:	file format elf64-bpf

Disassembly of section .bss:

0000000000000000 <target_pid>:
...

0000000000000008 <unused>:
...

environment

cilium/ebpf version
0.8.1

OS version

[root@cnxc-ebpf ~]# go version
go version go1.17.8 linux/amd64
[root@cnxc-ebpf ~]# uname -a
Linux cnxc-ebpf 4.18.0-80.11.2.el8_0.x86_64 #1 SMP Tue Sep 24 11:32:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
[root@cnxc-ebpf ~]# cat /etc/issue
\S
Kernel \r on an \m

[root@cnxc-ebpf ~]# clang --version
clang version 13.0.0 (Red Hat 13.0.0-3.module_el8.6.0+1074+380cef3f)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Expected behavior

It works with global variable in ebpf kernel function on linux kernel 4.18.

Question

haveMapMutabilityModifiers function added at f5942f5215490ef5f1bc2072f2c925ce7712a20e
and can we have an other way to do this?

var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() bool {
	// This checks BPF_F_RDONLY_PROG and BPF_F_WRONLY_PROG. Since
	// BPF_MAP_FREEZE appeared in 5.2 as well we don't do a separate check.
	m, err := bpfMapCreate(&bpfMapCreateAttr{
		mapType:    Array,
		keySize:    4,
		valueSize:  4,
		maxEntries: 1,
		flags:      unix.BPF_F_RDONLY_PROG,
	})
	if err != nil {
		return false
	}
	_ = m.Close()
	return true
})

Others
libpf :libbpf: Load global data maps lazily on legacy kernels

  • To support old kernels, we skip creating global data maps
  • (.rodata, .data, .kconfig, etc); later on, during program
  • loading, if we detect that at least one of the to-be-loaded
  • programs is referencing any global data map, we'll error
  • out with program name and relocation index logged.
  • This approach allows to accommodate Clang emitting
  • unnecessary .rodata.str1.1 sections for string literals,
  • but also it allows to have CO-RE applications that use
  • global variables in some of BPF programs, but not others.
  • If those global variable-using programs are not loaded at
  • runtime due to bpf_program__set_autoload(prog, false),
  • bpf_object loading will succeed just fine even on old
  • kernels.

issue : libbpf 1.0: support multiple .rodata*, .data*, .bss* sections #274

conclusion

I think that cilium/ebpf need to do like libbpf to load ebpf bytecode on older kernel.

and I'll keep tracing later for more detail,and send a PR for it if it is a bug.

@lmb
Copy link
Collaborator

lmb commented Apr 21, 2022

read- and write-only maps not supported (requires >= v5.2)

The map in question here is .rodata, which is generated by the compiler if you add constants to your code. As the error message says, it's not supported on your kernel.

Unless I'm missing something this is not a bug, it's a limitation of your environment. Feel free to reopen if you disagree.

@lmb lmb closed this as completed Apr 21, 2022
@cfc4n
Copy link
Contributor Author

cfc4n commented May 4, 2022

got it ,thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants