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
This commit is contained in:
Ryan Zuklie 2022-12-15 16:14:32 -08:00
parent 4a7ca6f2b1
commit ce89f50035
4 changed files with 52 additions and 2 deletions

View file

@ -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)

View file

@ -39,6 +39,7 @@ cc_library {
shared_libs: [
"libbase",
"libcutils",
"libutils",
"liblog",
"libbpf_bcc",

View file

@ -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::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<unique_fd>&
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<codeSection>& 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)) {

View file

@ -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