bpf: put canonicalized section name in bpf_prog_def
Test: TreeHugger
Flag: EXEMPT mainline
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I8bc5c888f982dc872ac68840ae6c136a798384d9
diff --git a/bpf/loader/NetBpfLoad.cpp b/bpf/loader/NetBpfLoad.cpp
index acf3d9d..93547a9 100644
--- a/bpf/loader/NetBpfLoad.cpp
+++ b/bpf/loader/NetBpfLoad.cpp
@@ -110,7 +110,6 @@
static unsigned int page_size = static_cast<unsigned int>(getpagesize());
typedef struct {
- string name; // The canonicalized section name.
string program_name;
vector<char> data;
vector<char> rel_data;
@@ -383,8 +382,6 @@
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 @@
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 @@
.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 @@
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 @@
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 @@
unsigned kvers = kernelVersion();
for (int i = 0; i < (int)cs.size(); i++) {
- 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;
}
string program_name = cs[i].program_name;
@@ -1204,7 +1194,7 @@
unsigned max_kver = cs[i].prog_def->max_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 @@
unsigned bpfMaxVer = cs[i].prog_def->bpfloader_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 @@
// 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 4a2ad14..ab405c2 100644
--- a/bpf/progs/include/bpf_helpers.h
+++ b/bpf/progs/include/bpf_helpers.h
@@ -547,6 +547,7 @@
.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 f3e04b8..63c31ac 100644
--- a/bpf/progs/include/bpf_map_def.h
+++ b/bpf/progs/include/bpf_map_def.h
@@ -186,10 +186,20 @@
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<struct bpf_prog_def>);
+static_assert(std::is_standard_layout_v<struct bpf_prog_def>);
+#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");