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
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 @@
     (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 @@
 
     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 <sys/wait.h>
 #include <unistd.h>
 
-// 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 <android-base/file.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <cutils/properties.h>
 
 #define BPF_FS_PATH "/sys/fs/bpf/"
 
@@ -74,9 +75,20 @@
 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 @@
             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 @@
               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 @@
 // 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