From ce89f50035e3b964e842df95c14900505abcad63 Mon Sep 17 00:00:00 2001 From: Ryan Zuklie Date: Thu, 15 Dec 2022 16:14:32 -0800 Subject: [PATCH] Add option to skip map/prog based on build type This feature allows skipping a program or map based on the type of the build. This allows things like userdebug-only programs. Bug: 246985031 Test: added test program and watched it skipped on userdebug Change-Id: I981e3447b40751926cbfd1692e13772ec582d3d4 --- bpfloader/BpfLoader.cpp | 7 ++++++ libbpf_android/Android.bp | 1 + libbpf_android/Loader.cpp | 32 +++++++++++++++++++++++-- libbpf_android/include/libbpf_android.h | 14 +++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/bpfloader/BpfLoader.cpp b/bpfloader/BpfLoader.cpp index a7748a2..be96c51 100644 --- a/bpfloader/BpfLoader.cpp +++ b/bpfloader/BpfLoader.cpp @@ -257,6 +257,13 @@ int main(int argc, char** argv) { (void)argc; android::base::InitLogging(argv, &android::base::KernelLogger); + // Ensure we can determine the Android build type. + if (!android::bpf::isEng() && !android::bpf::isUser() && !android::bpf::isUserdebug()) { + ALOGE("Failed to determine the build type: got %s, want 'eng', 'user', or 'userdebug'", + android::bpf::getBuildType().c_str()); + return 1; + } + // Linux 5.16-rc1 changed the default to 2 (disabled but changeable), but we need 0 (enabled) // (this writeFile is known to fail on at least 4.19, but always defaults to 0 on pre-5.13, // on 5.13+ it depends on CONFIG_BPF_UNPRIV_DEFAULT_OFF) diff --git a/libbpf_android/Android.bp b/libbpf_android/Android.bp index 1893c6d..dda943d 100644 --- a/libbpf_android/Android.bp +++ b/libbpf_android/Android.bp @@ -39,6 +39,7 @@ cc_library { shared_libs: [ "libbase", + "libcutils", "libutils", "liblog", "libbpf_bcc", diff --git a/libbpf_android/Loader.cpp b/libbpf_android/Loader.cpp index f1a0123..24e5a90 100644 --- a/libbpf_android/Loader.cpp +++ b/libbpf_android/Loader.cpp @@ -30,9 +30,9 @@ #include #include -// This is BpfLoader v0.31 +// This is BpfLoader v0.32 #define BPFLOADER_VERSION_MAJOR 0u -#define BPFLOADER_VERSION_MINOR 31u +#define BPFLOADER_VERSION_MINOR 32u #define BPFLOADER_VERSION ((BPFLOADER_VERSION_MAJOR << 16) | BPFLOADER_VERSION_MINOR) #include "bpf/BpfUtils.h" @@ -57,6 +57,7 @@ #include #include #include +#include #define BPF_FS_PATH "/sys/fs/bpf/" @@ -74,9 +75,20 @@ using std::optional; using std::string; using std::vector; +static std::string getBuildTypeInternal() { + char value[PROPERTY_VALUE_MAX] = {}; + (void)property_get("ro.build.type", value, "unknown"); // ignore length + return value; +} + namespace android { namespace bpf { +const std::string& getBuildType() { + static std::string t = getBuildTypeInternal(); + return t; +} + constexpr const char* lookupSelinuxContext(const domain d, const char* const unspecified = "") { switch (d) { case domain::unspecified: return unspecified; @@ -769,6 +781,14 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector& continue; } + if ((md[i].ignore_on_eng && isEng()) || (md[i].ignore_on_user && isUser()) || + (md[i].ignore_on_userdebug && isUserdebug())) { + ALOGI("skipping map %s which is ignored on %s builds", mapNames[i].c_str(), + getBuildType().c_str()); + mapFds.push_back(unique_fd()); + continue; + } + enum bpf_map_type type = md[i].type; if (type == BPF_MAP_TYPE_DEVMAP_HASH && !isAtLeastKernelVersion(5, 4, 0)) { // On Linux Kernels older than 5.4 this map type doesn't exist, but it can kind @@ -1011,6 +1031,14 @@ static int loadCodeSections(const char* elfPath, vector& cs, const bpfMinVer, bpfMaxVer); if (BPFLOADER_VERSION < bpfMinVer) continue; if (BPFLOADER_VERSION >= bpfMaxVer) continue; + + if ((cs[i].prog_def->ignore_on_eng && isEng()) || + (cs[i].prog_def->ignore_on_user && isUser()) || + (cs[i].prog_def->ignore_on_userdebug && isUserdebug())) { + ALOGD("cs[%d].name:%s is ignored on %s builds", i, name.c_str(), + getBuildType().c_str()); + } + if (unrecognized(pin_subdir)) return -ENOTDIR; if (specified(selinux_context)) { diff --git a/libbpf_android/include/libbpf_android.h b/libbpf_android/include/libbpf_android.h index 7811179..3a6d802 100644 --- a/libbpf_android/include/libbpf_android.h +++ b/libbpf_android/include/libbpf_android.h @@ -92,5 +92,19 @@ 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); +// Returns the build type string (from ro.build.type). +const std::string& getBuildType(); + +// The following functions classify the 3 Android build types. +inline bool isEng() { + return getBuildType() == "eng"; +} +inline bool isUser() { + return getBuildType() == "user"; +} +inline bool isUserdebug() { + return getBuildType() == "userdebug"; +} + } // namespace bpf } // namespace android