diff options
author | Maciej Żenczykowski <maze@google.com> | 2020-06-15 09:40:10 +0000 |
---|---|---|
committer | Maciej Zenczykowski <maze@google.com> | 2020-06-15 10:22:36 +0000 |
commit | 45f5ffd167b6fd172866fc8f6e9fa0895fbd6528 (patch) | |
tree | 09b8c2c18a6a3cbc7e271aea65bd4805de92c903 | |
parent | 731e9939e679808a0c467689349409b32ba83d11 (diff) | |
download | bpf-45f5ffd167b6fd172866fc8f6e9fa0895fbd6528.tar.gz |
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>
Original-Change: https://android-review.googlesource.com/1335885
Merged-In: Iefa01e60cd0a9a223e96411726a199bfb4857a5a
Change-Id: Iefa01e60cd0a9a223e96411726a199bfb4857a5a
-rw-r--r-- | bpfloader/BpfLoader.cpp | 25 | ||||
-rw-r--r-- | libbpf_android/BpfLoadTest.cpp | 4 | ||||
-rw-r--r-- | libbpf_android/Loader.cpp | 10 | ||||
-rw-r--r-- | libbpf_android/include/libbpf_android.h | 2 |
4 files changed, 30 insertions, 11 deletions
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 @@ using std::string; #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 @@ void loadAllElfObjects(void) { 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 @@ class BpfLoadTest : public testing::Test { 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 @@ static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const 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 @@ int loadProg(const char* elfPath) { 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 android { 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(); |