Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

libbpf: Add gating for arena globals relocation feature

Add feature gating for the arena globals relocation introduced in
commit c1f61171d44b. The commit depends on a previous commit in the
same patchset that is absent from older kernels
(12a1fe6e12db "bpf/verifier: Do not limit maximum direct offset into arena map").

Without this commit, arena globals relocation with arenas >= 512MiB
fails to load and breaks libbpf's backwards compatibility.

Introduce a libbpf feature to check whether the running kernel allows for
full range ldimm64 offset, and only relocate arena globals if it does.

Fixes: c1f61171d44b ("libbpf: Move arena globals to the end of the arena")
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260210184532.255475-1-emil@etsalapatis.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Emil Tsalapatis and committed by
Alexei Starovoitov
728ff167 44331bd6

+71 -2
+64
tools/lib/bpf/features.c
··· 506 506 return probe_fd(prog_fd); 507 507 } 508 508 509 + static int probe_ldimm64_full_range_off(int token_fd) 510 + { 511 + char log_buf[1024]; 512 + int prog_fd, map_fd; 513 + int ret; 514 + LIBBPF_OPTS(bpf_map_create_opts, map_opts, 515 + .token_fd = token_fd, 516 + .map_flags = token_fd ? BPF_F_TOKEN_FD : 0, 517 + ); 518 + LIBBPF_OPTS(bpf_prog_load_opts, prog_opts, 519 + .token_fd = token_fd, 520 + .prog_flags = token_fd ? BPF_F_TOKEN_FD : 0, 521 + .log_buf = log_buf, 522 + .log_size = sizeof(log_buf), 523 + ); 524 + struct bpf_insn insns[] = { 525 + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 1UL << 30), 526 + BPF_EXIT_INSN(), 527 + }; 528 + int insn_cnt = ARRAY_SIZE(insns); 529 + 530 + map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr", sizeof(int), 1, 1, &map_opts); 531 + if (map_fd < 0) { 532 + ret = -errno; 533 + pr_warn("Error in %s(): %s. Couldn't create simple array map.\n", 534 + __func__, errstr(ret)); 535 + return ret; 536 + } 537 + insns[0].imm = map_fd; 538 + 539 + prog_fd = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, "global_reloc", "GPL", insns, insn_cnt, &prog_opts); 540 + ret = -errno; 541 + 542 + close(map_fd); 543 + close(prog_fd); 544 + 545 + if (prog_fd >= 0) { 546 + pr_warn("Error in %s(): Program loading unexpectedly succeeded.\n", __func__); 547 + return -EINVAL; 548 + } 549 + 550 + /* 551 + * Feature is allowed if we're not failing with the error message 552 + * "direct value offset of %u is not allowed" removed in 553 + * 12a1fe6e12db ("bpf/verifier: Do not limit maximum direct offset into arena map"). 554 + * We should instead fail with "invalid access to map value pointer". 555 + * Ensure we match with one of the two and we're not failing with a 556 + * different, unexpected message. 557 + */ 558 + if (strstr(log_buf, "direct value offset of")) 559 + return 0; 560 + 561 + if (!strstr(log_buf, "invalid access to map value pointer")) { 562 + pr_warn("Error in %s(): Program unexpectedly failed with message: %s.\n", 563 + __func__, log_buf); 564 + return ret; 565 + } 566 + 567 + return 1; 568 + } 569 + 509 570 typedef int (*feature_probe_fn)(int /* token_fd */); 510 571 511 572 static struct kern_feature_cache feature_cache; ··· 641 580 }, 642 581 [FEAT_BTF_QMARK_DATASEC] = { 643 582 "BTF DATASEC names starting from '?'", probe_kern_btf_qmark_datasec, 583 + }, 584 + [FEAT_LDIMM64_FULL_RANGE_OFF] = { 585 + "full range LDIMM64 support", probe_ldimm64_full_range_off, 644 586 }, 645 587 }; 646 588
+5 -2
tools/lib/bpf/libbpf.c
··· 3009 3009 memcpy(obj->arena_data, data, data_sz); 3010 3010 obj->arena_data_sz = data_sz; 3011 3011 3012 - /* place globals at the end of the arena */ 3013 - obj->arena_data_off = mmap_sz - data_alloc_sz; 3012 + /* place globals at the end of the arena (if supported) */ 3013 + if (kernel_supports(obj, FEAT_LDIMM64_FULL_RANGE_OFF)) 3014 + obj->arena_data_off = mmap_sz - data_alloc_sz; 3015 + else 3016 + obj->arena_data_off = 0; 3014 3017 3015 3018 /* make bpf_map__init_value() work for ARENA maps */ 3016 3019 map->mmaped = obj->arena_data;
+2
tools/lib/bpf/libbpf_internal.h
··· 392 392 FEAT_ARG_CTX_TAG, 393 393 /* Kernel supports '?' at the front of datasec names */ 394 394 FEAT_BTF_QMARK_DATASEC, 395 + /* Kernel supports LDIMM64 imm offsets past 512 MiB. */ 396 + FEAT_LDIMM64_FULL_RANGE_OFF, 395 397 __FEAT_CNT, 396 398 }; 397 399