From dd4bd2d655d6287bd1ad627c3597ef34cef0f43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 7 Aug 2024 12:27:18 -0700 Subject: [PATCH] BpfLoader: split legacy bpfloader into 3 phases, simplify arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Should make integration with BpfLoader written in rust easier. While at it add simple wrappers around ALOG{V,D,I,W,E}(), which may come in handy as bpfloader runs early enough that logging must be to the kernel dmesg ringbuffer instead... Test: TreeHugger Signed-off-by: Maciej Żenczykowski Change-Id: Ia49c605bae63241b74d04e2e0f58fd089c23993d --- loader/BpfLoader.cpp | 7 +++-- loader/Loader.cpp | 55 ++++++++++++++++++++++++++------- loader/include/libbpf_android.h | 25 +++++++++++++-- 3 files changed, 71 insertions(+), 16 deletions(-) diff --git a/loader/BpfLoader.cpp b/loader/BpfLoader.cpp index a44d354..f180f4e 100644 --- a/loader/BpfLoader.cpp +++ b/loader/BpfLoader.cpp @@ -16,6 +16,9 @@ #include -int main(int argc, char** argv, char * const envp[]) { - return android::bpf::legacyBpfLoader(argc, argv, envp); +__noreturn int main() { + initLogging(); + legacyBpfLoader(); + execNetBpfLoadDone(); + // unreachable } diff --git a/loader/Loader.cpp b/loader/Loader.cpp index 4dd64b7..cdeca4e 100644 --- a/loader/Loader.cpp +++ b/loader/Loader.cpp @@ -975,27 +975,58 @@ int createSysFsBpfSubDir(const char* const prefix) { return 0; } -int legacyBpfLoader(int __unused argc, char** argv, char * const envp[]) { - base::InitLogging(argv, &base::KernelLogger); +} // namespace bpf +} // namespace android +// ----- extern C stuff for rust below here ----- + +void initLogging() { + // since we only ever get called from mainline NetBpfLoad + // (see packages/modules/Connectivity/netbpfload/NetBpfLoad.cpp around line 516) + // and there no arguments, so we can just pretend/assume this is the case. + const char* argv[] = {"/system/bin/bpfloader", NULL}; + android::base::InitLogging(const_cast(argv), &android::base::KernelLogger); +} + +void legacyBpfLoader() { // Load all ELF objects, create programs and maps, and pin them - for (const auto& location : locations) { - if (createSysFsBpfSubDir(location.prefix) || loadAllElfObjects(location)) { + for (const auto& location : android::bpf::locations) { + if (android::bpf::createSysFsBpfSubDir(location.prefix) || + android::bpf::loadAllElfObjects(location)) { ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS FROM %s ===", location.dir); 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 ---"); sleep(20); - return 120; + exit(120); } } - - const char * args[] = { "/apex/com.android.tethering/bin/netbpfload", "done", NULL, }; - execve(args[0], (char**)args, envp); - ALOGE("FATAL: execve(): %d[%s]", errno, strerror(errno)); - return 121; } -} // namespace bpf -} // namespace android +void execNetBpfLoadDone() { + const char* args[] = {"/apex/com.android.tethering/bin/netbpfload", "done", NULL}; + execve(args[0], (char**)args, environ); + ALOGE("FATAL: execve(): %d[%s]", errno, strerror(errno)); + exit(121); +} + +void logVerbose(const char* msg) { + ALOGV("%s", msg); +} + +void logDebug(const char* msg) { + ALOGD("%s", msg); +} + +void logInfo(const char* msg) { + ALOGI("%s", msg); +} + +void logWarn(const char* msg) { + ALOGW("%s", msg); +} + +void logError(const char* msg) { + ALOGE("%s", msg); +} diff --git a/loader/include/libbpf_android.h b/loader/include/libbpf_android.h index df4e32c..fbdae6f 100644 --- a/loader/include/libbpf_android.h +++ b/loader/include/libbpf_android.h @@ -17,6 +17,8 @@ #pragma once +#ifdef __cplusplus + #include #include @@ -37,7 +39,26 @@ int loadProg(const char* elfPath, bool* isCritical, const Location &location = { // Exposed for testing unsigned int readSectionUint(const char* name, std::ifstream& elfFile, unsigned int defVal); -int legacyBpfLoader(int argc, char** argv, char * const envp[]); - } // namespace bpf } // namespace android + +extern "C" { +#else // __cplusplus +#define __noreturn +#endif // __cplusplus + +// The C++ portion of the BpfLoader is exposed as 3 functions to be called in order. +void initLogging(); +void legacyBpfLoader(); +__noreturn void execNetBpfLoadDone(); + +// For logging from rust +void logVerbose(const char* msg); +void logDebug(const char* msg); +void logInfo(const char* msg); +void logWarn(const char* msg); +void logError(const char* msg); + +#ifdef __cplusplus +} // extern C +#endif