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");