From 157d83120d959a48e6bca3625d938566c9310811 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Thu, 24 Sep 2026 03:10:38 +0000 Subject: [PATCH] libbpf: Treat .data.rel.ro as read-only data PIC code keeps constants with pointers, e.g. vtables, in .data.rel.ro instead of .rodata. Nothing writes there after relocation. libbpf treats every .data* section as writable, while the kernel looks for pointers to functions in frozen read-only maps only. Make .data.rel.ro and .data.rel.ro.* maps read-only and frozen like .rodata and collect pointers to functions there. Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20260924031042.1690890-14-alexei.starovoitov@gmail.com --- src/libbpf.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libbpf.c b/src/libbpf.c index fc9b754..2e0cf7c 100644 --- a/src/libbpf.c +++ b/src/libbpf.c @@ -546,6 +546,7 @@ struct bpf_struct_ops { #define PERCPU_SEC ".percpu" #define BSS_SEC ".bss" #define RODATA_SEC ".rodata" +#define DATA_REL_RO_SEC ".data.rel.ro" #define KCONFIG_SEC ".kconfig" #define KSYMS_SEC ".ksyms" #define STRUCT_OPS_SEC ".struct_ops" @@ -4062,6 +4063,17 @@ static int bpf_object__elf_collect(struct bpf_object *obj) err = bpf_object__add_programs(obj, data, name, idx); if (err) return err; + } else if (strcmp(name, DATA_REL_RO_SEC) == 0 || + str_has_pfx(name, DATA_REL_RO_SEC ".")) { + /* + * Constants with pointers in them, e.g. vtables, + * that position independent code keeps here to + * have them relocated. There is nothing that + * writes to it after that. + */ + sec_desc->sec_type = SEC_RODATA; + sec_desc->shdr = sh; + sec_desc->data = data; } else if (strcmp(name, DATA_SEC) == 0 || str_has_pfx(name, DATA_SEC ".")) { sec_desc->sec_type = SEC_DATA; @@ -4114,6 +4126,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj) if (!section_have_execinstr(obj, targ_sec_idx) && strcmp(name, ".rel" RODATA_SEC) && !str_has_pfx(name, ".rel" RODATA_SEC ".") && + strcmp(name, ".rel" DATA_REL_RO_SEC) && + !str_has_pfx(name, ".rel" DATA_REL_RO_SEC ".") && strcmp(name, ".rel" STRUCT_OPS_SEC) && strcmp(name, ".rel" STRUCT_OPS_LINK_SEC) && strcmp(name, ".rel?" STRUCT_OPS_SEC) &&