how to access to bpf map which was made by user program in the kernel program (kernel context)?

2.9k views Asked by At

Let's suppose there are two programs (User program and Kernel program).

User program made bpf map by api bpf_create_map_name() and it returns fd. With this fd, I can access the map by syscalls (e.g., bpf_map_update(fd, ..)). But I can do this only in the user space programs because the fd is valid only to user program(=user process), then How can I access to this map in the bpf program (located in the kernel space)?

I was heard that I can pin the map in the fs via libbpf's bpf_obj_pin(fd, file path) and can get this map via libbpf's bpf_obj_get(file path) but the problem is bpf_obj_get is only available in the user space because this is system call.

I saw a similar discussion before (Accessing BPF maps from kernel space). but this was not clear to me. To access bpf map via bpf_map_lookup_elem(fd, ..) in the kernel space, I have to know map's fd in advance. But as I mentioned before, the map's fd is not valid in the kernel.

I am using libbpf not BCC.

2

There are 2 answers

12
Qeole On BEST ANSWER

You should probably look at libbpf's function bpf_map__reuse_fd(), which allows to reuse a file descriptor pointing to an existing map for a BPF program.

Here is an example using this function: we first retrieve a pointer to the map to replace in the struct bpf_object by calling bpf_object__find_map_by_name(), and then tell it to reuse the existing fd.

0
Dylan Reimerink On

The only way to dynamically add maps to an existing eBPF program is to use a map-in-map type like BPF_MAP_TYPE_ARRAY_OF_MAPS or BPF_MAP_TYPE_HASH_OF_MAPS. To use it we define a inner and outer map type. The userspace program/loader creates the outer map and loads the program with a reference to the outer map. After that we can modify this outer map from userspace to add one or more inner maps to it at any time. Please take a look at samples in the kernel: test_map_in_map_user.c and test_map_in_map_kern.c.

To explain further and to clarify some things:

  • eBPF programs don't create maps, the ELF files contain map definitions which are read by the userspace program/loader which then creates them. eBPF programs can't create maps as of this moment.
  • When the loader creates a map, the kernel returns a file descriptor. When a eBPF program is loaded into the kernel, the loader will dynamically rewrite the program and inject this file descriptor into it. The kernel verifies the program using the loaded map, after which the actual memory address of the map is placed in the program instead of the file descriptor so the generated machine code can access the map directly by memory address. This verification and conversion step is the reason programs can't dynamically "get" map references.
  • Map-in-map types do work dynamically. That is because the verifier validates the inner map definition when the program is loaded to make sure the code is valid. Then when the userspace updates the map-in-map, the actual memory address of the map is stored which can be accesses by the eBPF program. But even so, you need to know how the type/structure of the inner map before loading the first program.