Skip to content

Commit 728ff16

Browse files
etsalAlexei Starovoitov
authored andcommitted
libbpf: Add gating for arena globals relocation feature
Add feature gating for the arena globals relocation introduced in commit c1f6117. The commit depends on a previous commit in the same patchset that is absent from older kernels (12a1fe6 "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: c1f6117 ("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>
1 parent 44331bd commit 728ff16

3 files changed

Lines changed: 71 additions & 2 deletions

File tree

tools/lib/bpf/features.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,67 @@ static int probe_kern_arg_ctx_tag(int token_fd)
506506
return probe_fd(prog_fd);
507507
}
508508

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+
509570
typedef int (*feature_probe_fn)(int /* token_fd */);
510571

511572
static struct kern_feature_cache feature_cache;
@@ -581,6 +642,9 @@ static struct kern_feature_desc {
581642
[FEAT_BTF_QMARK_DATASEC] = {
582643
"BTF DATASEC names starting from '?'", probe_kern_btf_qmark_datasec,
583644
},
645+
[FEAT_LDIMM64_FULL_RANGE_OFF] = {
646+
"full range LDIMM64 support", probe_ldimm64_full_range_off,
647+
},
584648
};
585649

586650
bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_id)

tools/lib/bpf/libbpf.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3009,8 +3009,11 @@ static int init_arena_map_data(struct bpf_object *obj, struct bpf_map *map,
30093009
memcpy(obj->arena_data, data, data_sz);
30103010
obj->arena_data_sz = data_sz;
30113011

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;
30143017

30153018
/* make bpf_map__init_value() work for ARENA maps */
30163019
map->mmaped = obj->arena_data;

tools/lib/bpf/libbpf_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ enum kern_feature_id {
392392
FEAT_ARG_CTX_TAG,
393393
/* Kernel supports '?' at the front of datasec names */
394394
FEAT_BTF_QMARK_DATASEC,
395+
/* Kernel supports LDIMM64 imm offsets past 512 MiB. */
396+
FEAT_LDIMM64_FULL_RANGE_OFF,
395397
__FEAT_CNT,
396398
};
397399

0 commit comments

Comments
 (0)