Skip to content

Commit 16e0c35

Browse files
anakryikoborkmann
authored andcommitted
libbpf: Load global data maps lazily on legacy kernels
Load global data maps lazily, if kernel is too old to support global data. Make sure that programs are still correct by detecting if any of the to-be-loaded programs have relocation against any of such maps. This allows to solve the issue ([0]) with bpf_printk() and Clang generating unnecessary and unreferenced .rodata.strX.Y sections, but it also goes further along the CO-RE lines, allowing to have a BPF object in which some code can work on very old kernels and relies only on BPF maps explicitly, while other BPF programs might enjoy global variable support. If such programs are correctly set to not load at runtime on old kernels, bpf_object will load and function correctly now. [0] https://lore.kernel.org/bpf/CAK-59YFPU3qO+_pXWOH+c1LSA=8WA1yabJZfREjOEXNHAqgXNg@mail.gmail.com/ Fixes: aed6591 ("libbpf: Support multiple .rodata.* and .data.* BPF maps") Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Song Liu <songliubraving@fb.com> Link: https://lore.kernel.org/bpf/20211123200105.387855-1-andrii@kernel.org
1 parent fa721d4 commit 16e0c35

File tree

1 file changed

+30
-4
lines changed

1 file changed

+30
-4
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5006,6 +5006,24 @@ bpf_object__create_maps(struct bpf_object *obj)
50065006
for (i = 0; i < obj->nr_maps; i++) {
50075007
map = &obj->maps[i];
50085008

5009+
/* To support old kernels, we skip creating global data maps
5010+
* (.rodata, .data, .kconfig, etc); later on, during program
5011+
* loading, if we detect that at least one of the to-be-loaded
5012+
* programs is referencing any global data map, we'll error
5013+
* out with program name and relocation index logged.
5014+
* This approach allows to accommodate Clang emitting
5015+
* unnecessary .rodata.str1.1 sections for string literals,
5016+
* but also it allows to have CO-RE applications that use
5017+
* global variables in some of BPF programs, but not others.
5018+
* If those global variable-using programs are not loaded at
5019+
* runtime due to bpf_program__set_autoload(prog, false),
5020+
* bpf_object loading will succeed just fine even on old
5021+
* kernels.
5022+
*/
5023+
if (bpf_map__is_internal(map) &&
5024+
!kernel_supports(obj, FEAT_GLOBAL_DATA))
5025+
continue;
5026+
50095027
retried = false;
50105028
retry:
50115029
if (map->pin_path) {
@@ -5605,6 +5623,14 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
56055623
insn[0].src_reg = BPF_PSEUDO_MAP_IDX_VALUE;
56065624
insn[0].imm = relo->map_idx;
56075625
} else {
5626+
const struct bpf_map *map = &obj->maps[relo->map_idx];
5627+
5628+
if (bpf_map__is_internal(map) &&
5629+
!kernel_supports(obj, FEAT_GLOBAL_DATA)) {
5630+
pr_warn("prog '%s': relo #%d: kernel doesn't support global data\n",
5631+
prog->name, i);
5632+
return -ENOTSUP;
5633+
}
56085634
insn[0].src_reg = BPF_PSEUDO_MAP_VALUE;
56095635
insn[0].imm = obj->maps[relo->map_idx].fd;
56105636
}
@@ -6139,6 +6165,8 @@ bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
61396165
*/
61406166
if (prog_is_subprog(obj, prog))
61416167
continue;
6168+
if (!prog->load)
6169+
continue;
61426170

61436171
err = bpf_object__relocate_calls(obj, prog);
61446172
if (err) {
@@ -6152,6 +6180,8 @@ bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
61526180
prog = &obj->programs[i];
61536181
if (prog_is_subprog(obj, prog))
61546182
continue;
6183+
if (!prog->load)
6184+
continue;
61556185
err = bpf_object__relocate_data(obj, prog);
61566186
if (err) {
61576187
pr_warn("prog '%s': failed to relocate data references: %d\n",
@@ -6939,10 +6969,6 @@ static int bpf_object__sanitize_maps(struct bpf_object *obj)
69396969
bpf_object__for_each_map(m, obj) {
69406970
if (!bpf_map__is_internal(m))
69416971
continue;
6942-
if (!kernel_supports(obj, FEAT_GLOBAL_DATA)) {
6943-
pr_warn("kernel doesn't support global data\n");
6944-
return -ENOTSUP;
6945-
}
69466972
if (!kernel_supports(obj, FEAT_ARRAY_MMAP))
69476973
m->def.map_flags ^= BPF_F_MMAPABLE;
69486974
}

0 commit comments

Comments
 (0)