Warn loudly and do not set bpf.progs_loaded property on critical bpf load failure.

Reasoning: critical load failures for netd bpf programs will just result
in unpredictable behaviour later on.  For example netd/systemserver
crash loops.

Test: builds
Bug: 150040815
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Iefa01e60cd0a9a223e96411726a199bfb4857a5a
diff --git a/bpfloader/BpfLoader.cpp b/bpfloader/BpfLoader.cpp
index 9e348e5..e67c469 100644
--- a/bpfloader/BpfLoader.cpp
+++ b/bpfloader/BpfLoader.cpp
@@ -53,7 +53,8 @@
 
 #define BPF_PROG_PATH "/system/etc/bpf/"
 
-void loadAllElfObjects(void) {
+int loadAllElfObjects(void) {
+    int retVal = 0;
     DIR* dir;
     struct dirent* ent;
 
@@ -64,21 +65,35 @@
 
             string progPath = BPF_PROG_PATH + s;
 
-            int ret = android::bpf::loadProg(progPath.c_str());
-            ALOGI("Attempted load object: %s, ret: %s", progPath.c_str(), std::strerror(-ret));
+            bool critical;
+            int ret = android::bpf::loadProg(progPath.c_str(), &critical);
+            if (ret) {
+                if (critical) retVal = ret;
+                ALOGE("Failed to load object: %s, ret: %s", progPath.c_str(), std::strerror(-ret));
+            } else {
+                ALOGI("Loaded object: %s", progPath.c_str());
+            }
         }
         closedir(dir);
     }
+    return retVal;
 }
 
 int main() {
     if (!android::bpf::isBpfSupported()) return 0;
 
     // Load all ELF objects, create programs and maps, and pin them
-    loadAllElfObjects();
+    if (loadAllElfObjects() != 0) {
+        ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS ===");
+        ALOGE("If this triggers reliably, you're probably missing kernel options or patches.");
+        ALOGE("If this triggers randomly, you might be hitting some memory allocation problems or "
+              "startup script race.");
+        ALOGE("--- DO NOT EXPECT SYSTEM TO BOOT SUCCESSFULLY ---");
+        return 2;
+    }
 
     if (android::base::SetProperty("bpf.progs_loaded", "1") == false) {
-        ALOGE("Failed to set bpf.progs_loaded property\n");
+        ALOGE("Failed to set bpf.progs_loaded property");
         return 1;
     }
 
diff --git a/libbpf_android/BpfLoadTest.cpp b/libbpf_android/BpfLoadTest.cpp
index 349e997..b384c11 100644
--- a/libbpf_android/BpfLoadTest.cpp
+++ b/libbpf_android/BpfLoadTest.cpp
@@ -43,7 +43,9 @@
         unlink(tp_prog_path);
         unlink(tp_map_path);
 
-        EXPECT_EQ(android::bpf::loadProg("/system/etc/bpf/bpf_load_tp_prog.o"), 0);
+        bool critical = true;
+        EXPECT_EQ(android::bpf::loadProg("/system/etc/bpf/bpf_load_tp_prog.o", &critical), 0);
+        EXPECT_EQ(false, critical);
 
         mProgFd = bpf_obj_get(tp_prog_path);
         EXPECT_GT(mProgFd, 0);
diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp
index 9f57ce6..8f5318d 100644
--- a/libbpf_android/Loader.cpp
+++ b/libbpf_android/Loader.cpp
@@ -606,19 +606,21 @@
     return 0;
 }
 
-int loadProg(const char* elfPath) {
+int loadProg(const char* elfPath, bool* isCritical) {
     vector<char> license;
     vector<char> critical;
     vector<codeSection> cs;
     vector<unique_fd> mapFds;
-    bool is_critical;
     int ret;
 
+    if (!isCritical) return -1;
+    *isCritical = false;
+
     ifstream elfFile(elfPath, ios::in | ios::binary);
     if (!elfFile.is_open()) return -1;
 
     ret = readSectionByName("critical", elfFile, critical);
-    is_critical = !ret;
+    *isCritical = !ret;
 
     ret = readSectionByName("license", elfFile, license);
     if (ret) {
@@ -626,7 +628,7 @@
         return ret;
     } else {
         ALOGD("Loading %s%s ELF object %s with license %s\n",
-              is_critical ? "critical for " : "optional", is_critical ? (char*)critical.data() : "",
+              *isCritical ? "critical for " : "optional", *isCritical ? (char*)critical.data() : "",
               elfPath, (char*)license.data());
     }
 
diff --git a/libbpf_android/include/libbpf_android.h b/libbpf_android/include/libbpf_android.h
index 0a01c85..3810d07 100644
--- a/libbpf_android/include/libbpf_android.h
+++ b/libbpf_android/include/libbpf_android.h
@@ -25,7 +25,7 @@
 namespace bpf {
 
 // BPF loader implementation. Loads an eBPF ELF object
-int loadProg(const char* elfpath);
+int loadProg(const char* elfPath, bool* isCritical);
 
 // Wait for bpfloader to load BPF programs.
 void waitForProgsLoaded();