bpf: move isAtLeastX to BpfUtils.h

Partially due to:
  https://android-review.googlesource.com/c/platform/bionic/+/3497280

Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I74a626c45d641e226d7f71e00d0b542c5701417d
This commit is contained in:
Maciej Żenczykowski 2025-02-24 14:50:09 -08:00
commit 732386394e
5 changed files with 33 additions and 61 deletions

View file

@ -26,6 +26,7 @@
#include <sys/socket.h>
#include <sys/utsname.h>
#include <android-base/properties.h>
#include <log/log.h>
#include "KernelUtils.h"
@ -33,6 +34,16 @@
namespace android {
namespace bpf {
const bool unreleased = (base::GetProperty("ro.build.version.codename", "REL") != "REL");
const int api_level = unreleased ? 10000 : android_get_device_api_level();
const bool isAtLeastR = (api_level >= 30);
const bool isAtLeastS = (api_level >= 31);
// Sv2 is 32
const bool isAtLeastT = (api_level >= 33);
const bool isAtLeastU = (api_level >= 34);
const bool isAtLeastV = (api_level >= 35);
const bool isAtLeast25Q2 = (api_level >= 36);
// See kernel's net/core/sock_diag.c __sock_gen_cookie()
// the implementation of which guarantees 0 will never be returned,
// primarily because 0 is used to mean not yet initialized,

View file

@ -1414,37 +1414,6 @@ static bool isWear() {
static int doLoad(char** argv, char * const envp[]) {
const bool runningAsRoot = !getuid(); // true iff U QPR3 or V+
// Any released device will have codename REL instead of a 'real' codename.
// For safety: default to 'REL' so we default to unreleased=false on failure.
const bool unreleased = (GetProperty("ro.build.version.codename", "REL") != "REL");
// goog/main device_api_level is bumped *way* before aosp/main api level
// (the latter only gets bumped during the push of goog/main to aosp/main)
//
// Since we develop in AOSP, we want it to behave as if it was bumped too.
//
// Note that AOSP doesn't really have a good api level (for example during
// early V dev cycle, it would have *all* of T, some but not all of U, and some V).
// One could argue that for our purposes AOSP api level should be infinite or 10000.
//
// This could also cause api to be increased in goog/main or other branches,
// but I can't imagine a case where this would be a problem: the problem
// is rather a too low api level, rather than some ill defined high value.
// For example as I write this aosp is 34/U, and goog is 35/V,
// we want to treat both goog & aosp as 35/V, but it's harmless if we
// treat goog as 36 because that value isn't yet defined to mean anything,
// and we thus never compare against it.
//
// Also note that 'android_get_device_api_level()' is what the
// //system/core/init/apex_init_util.cpp
// apex init .XXrc parsing code uses for XX filtering, and that code
// (now) similarly uses __ANDROID_API_FUTURE__ for non 'REL' codenames.
const int api_level = unreleased ? __ANDROID_API_FUTURE__ : android_get_device_api_level();
const bool isAtLeastT = (api_level >= __ANDROID_API_T__);
const bool isAtLeastU = (api_level >= __ANDROID_API_U__);
const bool isAtLeastV = (api_level >= __ANDROID_API_V__);
const bool isAtLeast25Q2 = (api_level > __ANDROID_API_V__); // TODO: fix >
const int first_api_level = GetIntProperty("ro.board.first_api_level", api_level);
// last in U QPR2 beta1
@ -1591,7 +1560,7 @@ static int doLoad(char** argv, char * const envp[]) {
if (isArm() && (isTV() || isWear())) {
// exempt Arm TV or Wear devices (arm32 ABI is far less problematic than x86-32)
ALOGW("[Arm TV/Wear] 32-bit userspace unsupported on 6.2+ kernels.");
} else if (first_api_level <= __ANDROID_API_T__ && isArm()) {
} else if (first_api_level <= 33 /*T*/ && isArm()) {
// also exempt Arm devices upgrading with major kernel rev from T-
// might possibly be better for them to run with a newer kernel...
ALOGW("[Arm KernelUpRev] 32-bit userspace unsupported on 6.2+ kernels.");

View file

@ -22,7 +22,6 @@
#include <inttypes.h>
#include <android-base/unique_fd.h>
#include <android-modules-utils/sdk_level.h>
#include <bpf/WaitForProgsLoaded.h>
#include <log/log.h>
#include <netdutils/UidConstants.h>
@ -37,6 +36,10 @@ using base::unique_fd;
using base::WaitForProperty;
using bpf::getSocketCookie;
using bpf::isAtLeastKernelVersion;
using bpf::isAtLeastT;
using bpf::isAtLeastU;
using bpf::isAtLeastV;
using bpf::isAtLeast25Q2;
using bpf::queryProgram;
using bpf::retrieveProgram;
using netdutils::Status;
@ -72,18 +75,11 @@ static Status checkProgramAccessible(const char* programPath) {
return netdutils::status::ok;
}
// Checks if the device is running on release version of Android 25Q2 or newer.
static bool isAtLeast25Q2() {
return android_get_device_api_level() >= 36 ||
(android_get_device_api_level() == 35 &&
modules::sdklevel::detail::IsAtLeastPreReleaseCodename("Baklava"));
}
static Status initPrograms(const char* cg2_path) {
if (!cg2_path) return Status("cg2_path is NULL");
// This code was mainlined in T, so this should be trivially satisfied.
if (!modules::sdklevel::IsAtLeastT()) return Status("S- platform is unsupported");
if (!isAtLeastT) return Status("S- platform is unsupported");
// S requires eBPF support which was only added in 4.9, so this should be satisfied.
if (!isAtLeastKernelVersion(4, 9, 0)) {
@ -91,22 +87,22 @@ static Status initPrograms(const char* cg2_path) {
}
// U bumps the kernel requirement up to 4.14
if (modules::sdklevel::IsAtLeastU() && !isAtLeastKernelVersion(4, 14, 0)) {
if (isAtLeastU && !isAtLeastKernelVersion(4, 14, 0)) {
return Status("U+ platform with kernel version < 4.14.0 is unsupported");
}
// U mandates this mount point (though it should also be the case on T)
if (modules::sdklevel::IsAtLeastU() && !!strcmp(cg2_path, "/sys/fs/cgroup")) {
if (isAtLeastU && !!strcmp(cg2_path, "/sys/fs/cgroup")) {
return Status("U+ platform with cg2_path != /sys/fs/cgroup is unsupported");
}
// V bumps the kernel requirement up to 4.19
if (modules::sdklevel::IsAtLeastV() && !isAtLeastKernelVersion(4, 19, 0)) {
if (isAtLeastV && !isAtLeastKernelVersion(4, 19, 0)) {
return Status("V+ platform with kernel version < 4.19.0 is unsupported");
}
// 25Q2 bumps the kernel requirement up to 5.4
if (isAtLeast25Q2() && !isAtLeastKernelVersion(5, 4, 0)) {
if (isAtLeast25Q2 && !isAtLeastKernelVersion(5, 4, 0)) {
return Status("25Q2+ platform with kernel version < 5.4.0 is unsupported");
}
@ -135,7 +131,7 @@ static Status initPrograms(const char* cg2_path) {
cg_fd, BPF_CGROUP_INET_SOCK_RELEASE));
}
if (modules::sdklevel::IsAtLeastV()) {
if (isAtLeastV) {
// V requires 4.19+, so technically this 2nd 'if' is not required, but it
// doesn't hurt us to try to support AOSP forks that try to support older kernels.
if (isAtLeastKernelVersion(4, 19, 0)) {
@ -180,7 +176,7 @@ static Status initPrograms(const char* cg2_path) {
if (queryProgram(cg_fd, BPF_CGROUP_INET_SOCK_RELEASE) <= 0) abort();
}
if (modules::sdklevel::IsAtLeastV()) {
if (isAtLeastV) {
// V requires 4.19+, so technically this 2nd 'if' is not required, but it
// doesn't hurt us to try to support AOSP forks that try to support older kernels.
if (isAtLeastKernelVersion(4, 19, 0)) {
@ -266,14 +262,13 @@ Status BpfHandler::init(const char* cg2_path) {
// ...unless someone changed 'exec_start bpfloader' to 'start bpfloader'
// in the rc file.
//
// TODO: should be: if (!modules::sdklevel::IsAtLeastW())
if (android_get_device_api_level() <= __ANDROID_API_V__) waitForBpf();
if (!isAtLeast25Q2) waitForBpf();
RETURN_IF_NOT_OK(initPrograms(cg2_path));
RETURN_IF_NOT_OK(initMaps());
if (android_get_device_api_level() > __ANDROID_API_V__) {
// make sure netd can create & write maps. sepolicy is V+, but enough to enforce on 25Q2+
if (isAtLeast25Q2) {
// Make sure netd can create & write maps. sepolicy is V+, but enough to enforce on 25Q2+
int key = 1;
int value = 123;
unique_fd map(bpf::createMap(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 2, 0));

View file

@ -31,6 +31,12 @@ using std::set;
using std::string;
using android::bpf::isAtLeastKernelVersion;
using android::bpf::isAtLeastR;
using android::bpf::isAtLeastS;
using android::bpf::isAtLeastT;
using android::bpf::isAtLeastU;
using android::bpf::isAtLeastV;
using android::bpf::isAtLeast25Q2;
#define PLATFORM "/sys/fs/bpf/"
#define TETHERING "/sys/fs/bpf/tethering/"
@ -42,16 +48,6 @@ using android::bpf::isAtLeastKernelVersion;
class BpfExistenceTest : public ::testing::Test {
};
const bool unreleased = (android::base::GetProperty("ro.build.version.codename", "REL") != "REL");
const int api_level = unreleased ? 10000 : android_get_device_api_level();
const bool isAtLeastR = (api_level >= 30);
const bool isAtLeastS = (api_level >= 31);
// Sv2 is 32
const bool isAtLeastT = (api_level >= 33);
const bool isAtLeastU = (api_level >= 34);
const bool isAtLeastV = (api_level >= 35);
const bool isAtLeast25Q2 = (api_level >= 36);
// Part of Android R platform (for 4.9+), but mainlined in S
static const set<string> PLATFORM_ONLY_IN_R = {
PLATFORM "map_offload_tether_ingress_map",

View file

@ -22,6 +22,7 @@ cc_library_shared {
],
shared_libs: [
"libbase",
"liblog",
"libnativehelper",
"libnetdutils",