From adb0f9e2a46cbbaae492b9e15e84d278a241f5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Mon, 4 Aug 2025 18:19:33 -0700 Subject: [PATCH] bpf: put canonicalized section name in bpf_prog_def MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: TreeHugger Flag: EXEMPT mainline Signed-off-by: Maciej Żenczykowski Change-Id: I8bc5c888f982dc872ac68840ae6c136a798384d9 --- bpf/loader/NetBpfLoad.cpp | 38 +++++++++++---------------------- bpf/progs/include/bpf_helpers.h | 1 + bpf/progs/include/bpf_map_def.h | 12 ++++++++++- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/bpf/loader/NetBpfLoad.cpp b/bpf/loader/NetBpfLoad.cpp index acf3d9df4f..93547a9b5c 100644 --- a/bpf/loader/NetBpfLoad.cpp +++ b/bpf/loader/NetBpfLoad.cpp @@ -110,7 +110,6 @@ inline bool isUserdebug() { static unsigned int page_size = static_cast(getpagesize()); typedef struct { - string name; // The canonicalized section name. string program_name; vector data; vector rel_data; @@ -383,8 +382,6 @@ int readCodeSections(ElfObject& elfObj, vector& cs) { if (name.find('/') != std::string::npos) abort(); // There should only be one! - cs_temp.name = name; - ret = elfObj.readSectionByIdx(i, cs_temp.data); if (ret) return ret; ALOGV("Loaded code section %d (%s)", i, name.c_str()); @@ -1050,33 +1047,27 @@ static int loadCodeSections(ElfObject& elfObj, vector& cs, const st for (int i = 0; i < (int)cs.size(); i++) { unique_fd& fd = cs[i].prog_fd; int ret; - string name = cs[i].name; if (!cs[i].prog_def.has_value()) { - ALOGE("[%d] '%s' missing program definition! bad bpf.o build?", i, name.c_str()); + ALOGE("[%d] missing program definition! bad bpf.o build?", i); return -EINVAL; } unsigned min_kver = cs[i].prog_def->min_kver; unsigned max_kver = cs[i].prog_def->max_kver; - ALOGD("cs[%d].name:%s min_kver:%x .max_kver:%x (kvers:%x)", i, name.c_str(), min_kver, - max_kver, kvers); + ALOGD("cs[%d].name:%s min_kver:%x .max_kver:%x (kvers:%x)", + i, cs[i].prog_def->name(), min_kver, max_kver, kvers); if (kvers < min_kver) continue; if (kvers >= max_kver) continue; unsigned bpfMinVer = cs[i].prog_def->bpfloader_min_ver; unsigned bpfMaxVer = cs[i].prog_def->bpfloader_max_ver; - ALOGD("cs[%d].name:%s requires bpfloader version [0x%05x,0x%05x)", i, name.c_str(), - bpfMinVer, bpfMaxVer); + ALOGD("cs[%d].name:%s requires bpfloader version [0x%05x,0x%05x)", + i, cs[i].prog_def->name(), bpfMinVer, bpfMaxVer); if (bpfloader_ver < bpfMinVer) continue; if (bpfloader_ver >= bpfMaxVer) continue; - // strip any potential $foo suffix - // this can be used to provide duplicate programs - // conditionally loaded based on running kernel version - name = name.substr(0, name.find_last_of('$')); - bool reuse = false; if (access(cs[i].prog_def->pin_location, F_OK) == 0) { fd.reset(retrieveProgram(cs[i].prog_def->pin_location)); @@ -1097,7 +1088,7 @@ static int loadCodeSections(ElfObject& elfObj, vector& cs, const st .expected_attach_type = cs[i].prog_def->attach_type, }; if (isAtLeastKernelVersion(4, 15, 0)) - strlcpy(req.prog_name, cs[i].name.c_str(), sizeof(req.prog_name)); + strlcpy(req.prog_name, cs[i].prog_def->name(), sizeof(req.prog_name)); fd.reset(bpf(BPF_PROG_LOAD, req)); // Kernel should have NULL terminated the log buffer, but force it anyway for safety @@ -1110,7 +1101,7 @@ static int loadCodeSections(ElfObject& elfObj, vector& cs, const st bool log_oneline = !strchr(log_buf, '\n'); ALOGD("BPF_PROG_LOAD call for %s (%s) returned '%s' fd: %d (%s)", elfObj.path, - cs[i].name.c_str(), log_oneline ? log_buf : "{multiline}", + cs[i].prog_def->name(), log_oneline ? log_buf : "{multiline}", fd.get(), !fd.ok() ? std::strerror(errno) : "ok"); if (!fd.ok()) { @@ -1125,10 +1116,10 @@ static int loadCodeSections(ElfObject& elfObj, vector& cs, const st if (cs[i].prog_def->optional) { ALOGW("failed program %s is marked optional - continuing...", - cs[i].name.c_str()); + cs[i].prog_def->name()); continue; } - ALOGE("non-optional program %s failed to load.", cs[i].name.c_str()); + ALOGE("non-optional program %s failed to load.", cs[i].prog_def->name()); } } @@ -1188,9 +1179,8 @@ static int prepareLoadProgs(const struct bpf_object* obj, const vectormax_kver; if (kvers < min_kver || kvers >= max_kver) { ALOGD("skipping prog %s: kernel version 0x%x is outside required range [0x%x, 0x%x)", - name.c_str(), kvers, min_kver, max_kver); + cs[i].prog_def->name(), kvers, min_kver, max_kver); bpf_program__set_autoload(prog, false); continue; } @@ -1213,7 +1203,7 @@ static int prepareLoadProgs(const struct bpf_object* obj, const vectorbpfloader_max_ver; if (bpfloader_ver < bpfMinVer || bpfloader_ver >= bpfMaxVer) { ALOGD("skipping prog %s: bpfloader 0x%05x is outside required range [0x%05x, 0x%05x)", - name.c_str(), bpfloader_ver, bpfMinVer, bpfMaxVer); + cs[i].prog_def->name(), bpfloader_ver, bpfMinVer, bpfMaxVer); bpf_program__set_autoload(prog, false); continue; } @@ -1265,11 +1255,9 @@ static int pinProgs(const struct bpf_object * obj, // This program was skipped if (!bpf_program__autoload(prog)) continue; - string name = cs[i].name; - name = name.substr(0, name.find_last_of('$')); if (access(cs[i].prog_def->pin_location, F_OK) == 0) { // TODO: Skip loading lower priority program - ALOGI("Higher priority program is already pinned, skip pinning %s", cs[i].name.c_str()); + ALOGI("Higher priority program is already pinned, skip pinning %s", cs[i].prog_def->name()); continue; } diff --git a/bpf/progs/include/bpf_helpers.h b/bpf/progs/include/bpf_helpers.h index 4a2ad1454e..ab405c2006 100644 --- a/bpf/progs/include/bpf_helpers.h +++ b/bpf/progs/include/bpf_helpers.h @@ -547,6 +547,7 @@ static long (*bpf_trace_printk)(const char* fmt, int fmt_size, ...) = (void*) BP .bpfloader_max_ver = (max_loader), \ .create_location = CREATE_LOCATION(selinux), \ .pin_location = "/sys/fs/bpf/" pindir "/prog_" BPF_OBJ_NAME "_" #TYPE "_" #NAME "\0", \ + .name_idx = __builtin_strlen("/sys/fs/bpf/" pindir "/prog_" BPF_OBJ_NAME "_"), \ }; \ SECTION(#TYPE "/" #NAME "$" #VER) \ long TYPE##_##NAME##_##VER diff --git a/bpf/progs/include/bpf_map_def.h b/bpf/progs/include/bpf_map_def.h index f3e04b8da7..63c31ac52d 100644 --- a/bpf/progs/include/bpf_map_def.h +++ b/bpf/progs/include/bpf_map_def.h @@ -186,10 +186,20 @@ struct bpf_prog_def { char create_location[BPF_DEF_CHAR_ARRAY_SIZE]; char pin_location[BPF_DEF_CHAR_ARRAY_SIZE]; + unsigned int name_idx; + +#ifdef __cplusplus + const char * name() const { return this->pin_location + this->name_idx; } +#endif }; +#ifdef __cplusplus +static_assert(std::is_pod_v); +static_assert(std::is_standard_layout_v); +#endif + // This needs to be updated whenever the above structure definition is expanded. // These asserts are here to make sure we have cross-6-arch consistency. -_Static_assert(sizeof(struct bpf_prog_def) == 36 + 2 * BPF_DEF_CHAR_ARRAY_SIZE, "wrong sizeof struct bpf_prog_def"); +_Static_assert(sizeof(struct bpf_prog_def) == 40 + 2 * BPF_DEF_CHAR_ARRAY_SIZE, "wrong sizeof struct bpf_prog_def"); _Static_assert(__alignof__(struct bpf_prog_def) == 4, "__alignof__ struct bpf_prog_def != 4"); _Static_assert(_Alignof(struct bpf_prog_def) == 4, "_Alignof struct bpf_prog_def != 4");