Load Bpf Program With Expected Attach Type

Move to bcc_prog_load_xattr() so that expected attach
type can be passed in when loading program.

Change-Id: I72533dd8805fa75287e12e828ee12315c0f8cd2d
diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp
index eb48cd0..fd223a2 100644
--- a/libbpf_android/Loader.cpp
+++ b/libbpf_android/Loader.cpp
@@ -30,9 +30,9 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-// This is BpfLoader v0.9
+// This is BpfLoader v0.10
 #define BPFLOADER_VERSION_MAJOR 0u
-#define BPFLOADER_VERSION_MINOR 9u
+#define BPFLOADER_VERSION_MINOR 10u
 #define BPFLOADER_VERSION ((BPFLOADER_VERSION_MAJOR << 16) | BPFLOADER_VERSION_MINOR)
 
 #include "bpf/BpfUtils.h"
@@ -59,6 +59,9 @@
 // Size of the BPF log buffer for verifier logging
 #define BPF_LOAD_LOG_SZ 0xfffff
 
+// Unspecified attach type is 0 which is BPF_CGROUP_INET_INGRESS.
+#define BPF_ATTACH_TYPE_UNSPEC BPF_CGROUP_INET_INGRESS
+
 using android::base::StartsWith;
 using android::base::unique_fd;
 using std::ifstream;
@@ -84,6 +87,7 @@
 typedef struct {
     const char* name;
     enum bpf_prog_type type;
+    enum bpf_attach_type expected_attach_type;
 } sectionType;
 
 /*
@@ -97,19 +101,21 @@
  * Instead use the DEFINE_(BPF|XDP)_(PROG|MAP)... & LICENSE/CRITICAL macros.
  */
 sectionType sectionNameTypes[] = {
-        {"cgroupskb/", BPF_PROG_TYPE_CGROUP_SKB},
-        {"cgroupsock/", BPF_PROG_TYPE_CGROUP_SOCK},
-        {"cgroupsockaddr/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR},
-        {"kprobe/", BPF_PROG_TYPE_KPROBE},
-        {"schedact/", BPF_PROG_TYPE_SCHED_ACT},
-        {"schedcls/", BPF_PROG_TYPE_SCHED_CLS},
-        {"skfilter/", BPF_PROG_TYPE_SOCKET_FILTER},
-        {"tracepoint/", BPF_PROG_TYPE_TRACEPOINT},
-        {"xdp/", BPF_PROG_TYPE_XDP},
+        {"bind4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND},
+        {"bind6/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND},
+        {"cgroupskb/", BPF_PROG_TYPE_CGROUP_SKB, BPF_ATTACH_TYPE_UNSPEC},
+        {"cgroupsock/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_ATTACH_TYPE_UNSPEC},
+        {"kprobe/", BPF_PROG_TYPE_KPROBE, BPF_ATTACH_TYPE_UNSPEC},
+        {"schedact/", BPF_PROG_TYPE_SCHED_ACT, BPF_ATTACH_TYPE_UNSPEC},
+        {"schedcls/", BPF_PROG_TYPE_SCHED_CLS, BPF_ATTACH_TYPE_UNSPEC},
+        {"skfilter/", BPF_PROG_TYPE_SOCKET_FILTER, BPF_ATTACH_TYPE_UNSPEC},
+        {"tracepoint/", BPF_PROG_TYPE_TRACEPOINT, BPF_ATTACH_TYPE_UNSPEC},
+        {"xdp/", BPF_PROG_TYPE_XDP, BPF_ATTACH_TYPE_UNSPEC},
 };
 
 typedef struct {
     enum bpf_prog_type type;
+    enum bpf_attach_type expected_attach_type;
     string name;
     vector<char> data;
     vector<char> rel_data;
@@ -300,6 +306,12 @@
     return BPF_PROG_TYPE_UNSPEC;
 }
 
+static enum bpf_attach_type getExpectedAttachType(string& name) {
+    for (auto& snt : sectionNameTypes)
+        if (StartsWith(name, snt.name)) return snt.expected_attach_type;
+    return BPF_ATTACH_TYPE_UNSPEC;
+}
+
 /* If ever needed
 static string getSectionName(enum bpf_prog_type type)
 {
@@ -311,18 +323,6 @@
 }
 */
 
-static bool isRelSection(codeSection& cs, string& name) {
-    for (auto& snt : sectionNameTypes) {
-        if (snt.type != cs.type) continue;
-
-        if (StartsWith(name, string(".rel") + snt.name))
-            return true;
-        else
-            return false;
-    }
-    return false;
-}
-
 static int readProgDefs(ifstream& elfFile, vector<struct bpf_prog_def>& pd,
                         size_t sizeOfBpfProgDef) {
     vector<char> pdData;
@@ -426,27 +426,30 @@
         if (ret) return ret;
 
         enum bpf_prog_type ptype = getSectionType(name);
-        if (ptype != BPF_PROG_TYPE_UNSPEC) {
-            string oldName = name;
+        if (ptype == BPF_PROG_TYPE_UNSPEC) continue;
 
-            // convert all slashes to underscores
-            std::replace(name.begin(), name.end(), '/', '_');
+        // This must be done before '/' is replaced with '_'.
+        cs_temp.expected_attach_type = getExpectedAttachType(name);
 
-            cs_temp.type = ptype;
-            cs_temp.name = name;
+        string oldName = name;
 
-            ret = readSectionByIdx(elfFile, i, cs_temp.data);
-            if (ret) return ret;
-            ALOGD("Loaded code section %d (%s)\n", i, name.c_str());
+        // convert all slashes to underscores
+        std::replace(name.begin(), name.end(), '/', '_');
 
-            vector<string> csSymNames;
-            ret = getSectionSymNames(elfFile, oldName, csSymNames, STT_FUNC);
-            if (ret || !csSymNames.size()) return ret;
-            for (size_t i = 0; i < progDefNames.size(); ++i) {
-                if (!progDefNames[i].compare(csSymNames[0] + "_def")) {
-                    cs_temp.prog_def = pd[i];
-                    break;
-                }
+        cs_temp.type = ptype;
+        cs_temp.name = name;
+
+        ret = readSectionByIdx(elfFile, i, cs_temp.data);
+        if (ret) return ret;
+        ALOGD("Loaded code section %d (%s)\n", i, name.c_str());
+
+        vector<string> csSymNames;
+        ret = getSectionSymNames(elfFile, oldName, csSymNames, STT_FUNC);
+        if (ret || !csSymNames.size()) return ret;
+        for (size_t i = 0; i < progDefNames.size(); ++i) {
+            if (!progDefNames[i].compare(csSymNames[0] + "_def")) {
+                cs_temp.prog_def = pd[i];
+                break;
             }
         }
 
@@ -455,7 +458,7 @@
             ret = getSymName(elfFile, shTable[i + 1].sh_name, name);
             if (ret) return ret;
 
-            if (isRelSection(cs_temp, name)) {
+            if (name == (".rel" + oldName)) {
                 ret = readSectionByIdx(elfFile, i + 1, cs_temp.rel_data);
                 if (ret) return ret;
                 ALOGD("Loaded relo section %d (%s)\n", i, name.c_str());
@@ -827,9 +830,18 @@
         } else {
             vector<char> log_buf(BPF_LOAD_LOG_SZ, 0);
 
-            fd = bcc_prog_load(cs[i].type, name.c_str(), (struct bpf_insn*)cs[i].data.data(),
-                               cs[i].data.size(), license.c_str(), kvers, 0, log_buf.data(),
-                               log_buf.size());
+            struct bpf_load_program_attr attr = {
+                .prog_type = cs[i].type,
+                .name = name.c_str(),
+                .insns = (struct bpf_insn*)cs[i].data.data(),
+                .license = license.c_str(),
+                .log_level = 0,
+                .expected_attach_type = cs[i].expected_attach_type,
+            };
+
+            fd = bcc_prog_load_xattr(&attr, cs[i].data.size(), log_buf.data(), log_buf.size(),
+                    true);
+
             ALOGD("bpf_prog_load lib call for %s (%s) returned fd: %d (%s)\n", elfPath,
                   cs[i].name.c_str(), fd, (fd < 0 ? std::strerror(errno) : "no error"));