KernelUtils.h: isAtLeastKernelVersion(x,y,z) - default 'z' to 0

This seems to be the most common usecase.

Test: TreeHugger
Flag: EXEMPT PURE_REFACTOR
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I2de4d067b2f20680539cbddb31555864bcf957b1
This commit is contained in:
Maciej Żenczykowski 2025-09-12 08:19:40 -07:00
commit ee24054e2b

View file

@ -452,7 +452,7 @@ int readCodeSections(ElfObject& elfObj, vector<codeSection>& cs) {
}
static unsigned int sanitizeMapFlags(unsigned int map_flags) {
if (!isAtLeastKernelVersion(5, 10, 0)) map_flags &= ~BPF_F_MMAPABLE;
if (!isAtLeastKernelVersion(5, 10)) map_flags &= ~BPF_F_MMAPABLE;
return map_flags;
}
@ -464,7 +464,7 @@ static bool mapMatchesExpectations(const unique_fd& fd,
// This is because the primary failure mode we're trying to detect here
// is either a source code misconfiguration (which is likely kernel independent)
// or a newly introduced kernel feature/bug (which is unlikely to get backported to 4.9).
if (!isAtLeastKernelVersion(4, 14, 0)) return true;
if (!isAtLeastKernelVersion(4, 14)) return true;
// Assuming fd is a valid Bpf Map file descriptor then
// all the following should always succeed on a 4.14+ kernel.
@ -642,7 +642,7 @@ static int loadBtf(ElfObject &elfObj, struct btf *btf) {
if (ret) return ret;
}
if (!isAtLeastKernelVersion(5, 10, 0)) {
if (!isAtLeastKernelVersion(5, 10)) {
// Likely unnecessary on kernel 5.4 but untested.
sanitizeBtf(btf);
}
@ -778,7 +778,7 @@ static int pinMap(const borrowed_fd& fd, const struct bpf_map_def& mapDef) {
return -err;
}
if (isAtLeastKernelVersion(4, 14, 0)) {
if (isAtLeastKernelVersion(4, 14)) {
int mapId = bpfGetFdMapId(fd);
if (mapId == -1) {
const int err = errno;
@ -791,7 +791,7 @@ static int pinMap(const borrowed_fd& fd, const struct bpf_map_def& mapDef) {
}
static bool isMapTypeSupported(enum bpf_map_type type) {
if (type == BPF_MAP_TYPE_LPM_TRIE && !isAtLeastKernelVersion(4, 14, 0)) {
if (type == BPF_MAP_TYPE_LPM_TRIE && !isAtLeastKernelVersion(4, 14)) {
// On Linux Kernels older than 4.14 this map type doesn't exist - autoskip.
return false;
}
@ -799,7 +799,7 @@ static bool isMapTypeSupported(enum bpf_map_type type) {
}
static enum bpf_map_type sanitizeMapType(enum bpf_map_type type) {
if (type == BPF_MAP_TYPE_DEVMAP && !isAtLeastKernelVersion(4, 14, 0)) {
if (type == BPF_MAP_TYPE_DEVMAP && !isAtLeastKernelVersion(4, 14)) {
// On Linux Kernels older than 4.14 this map type doesn't exist, but it can kind
// of be approximated: ARRAY has the same userspace api, though it is not usable
// by the same ebpf programs. However, that's okay because the bpf_redirect_map()
@ -809,7 +809,7 @@ static enum bpf_map_type sanitizeMapType(enum bpf_map_type type) {
// Hence using an ARRAY instead of a DEVMAP simply makes life easier for userspace.
return BPF_MAP_TYPE_ARRAY;
}
if (type == BPF_MAP_TYPE_DEVMAP_HASH && !isAtLeastKernelVersion(5, 4, 0)) {
if (type == BPF_MAP_TYPE_DEVMAP_HASH && !isAtLeastKernelVersion(5, 4)) {
// On Linux Kernels older than 5.4 this map type doesn't exist, but it can kind
// of be approximated: HASH has the same userspace visible api.
// However it cannot be used by ebpf programs in the same way.
@ -829,7 +829,7 @@ static int createMaps(ElfObject& elfObj, vector<struct bpf_map_def>& md, vector<
vector<char> btfData;
struct btf *btf = NULL;
auto btfGuard = base::make_scope_guard([&btf] { if (btf) btf__free(btf); });
if (isAtLeastKernelVersion(4, 19, 0)) {
if (isAtLeastKernelVersion(4, 19)) {
// On Linux Kernels older than 4.18 BPF_BTF_LOAD command doesn't exist.
ret = elfObj.readSectionByName(".BTF", btfData);
if (ret) {
@ -906,7 +906,7 @@ static int createMaps(ElfObject& elfObj, vector<struct bpf_map_def>& md, vector<
.max_entries = max_entries,
.map_flags = sanitizeMapFlags(md[i].map_flags),
};
if (isAtLeastKernelVersion(4, 15, 0))
if (isAtLeastKernelVersion(4, 15))
strlcpy(req.map_name, md[i].name(), sizeof(req.map_name));
bool haveBtf = btf && isBtfSupported(type);
@ -1038,7 +1038,7 @@ static int pinProg(const borrowed_fd& fd, const struct bpf_prog_def& progDef) {
static int validateProg(const borrowed_fd& fd, const char* const progPinLoc,
const unsigned int bpfloader_ver) {
if (!isAtLeastKernelVersion(4, 14, 0)) {
if (!isAtLeastKernelVersion(4, 14)) {
return 0;
}
int progId = bpfGetFdProgId(fd);
@ -1110,7 +1110,7 @@ static int loadCodeSections(ElfObject& elfObj, vector<codeSection>& cs, const st
.log_buf = ptr_to_u64(log_buf),
.expected_attach_type = cs[i].prog_def->attach_type,
};
if (isAtLeastKernelVersion(4, 15, 0))
if (isAtLeastKernelVersion(4, 15))
strlcpy(req.prog_name, cs[i].prog_def->name(), sizeof(req.prog_name));
fd.reset(bpf(BPF_PROG_LOAD, req));
@ -1317,7 +1317,7 @@ static int loadProgByLibbpf(const char* const elfPath, const unsigned int bpfloa
ret = bpf_object__load(obj);
if (ret) return ret;
// On Linux Kernels older than 4.18 BPF_BTF_LOAD command doesn't exist.
if (isAtLeastKernelVersion(4, 19, 0) && bpf_object__btf_fd(obj) < 0) return -1;
if (isAtLeastKernelVersion(4, 19) && bpf_object__btf_fd(obj) < 0) return -1;
ret = pinMaps(obj, md);
if (ret) return ret;
@ -1630,41 +1630,41 @@ static int doLoad(char** argv, char * const envp[]) {
// both S and T require kernel 4.9 (and eBpf support)
// (this also guarantees 'kernelVer' isn't an invalid uninitialized 0)
if (!isAtLeastKernelVersion(4, 9, 0)) {
if (!isAtLeastKernelVersion(4, 9)) {
ALOGE("Android S & T require kernel 4.9.");
return 3;
}
// U bumps the kernel requirement up to 4.14
if (isAtLeastU && !isAtLeastKernelVersion(4, 14, 0)) {
if (isAtLeastU && !isAtLeastKernelVersion(4, 14)) {
ALOGE("Android U requires kernel 4.14.");
return 4;
}
// V bumps the kernel requirement up to 4.19
// see also: //system/netd/tests/kernel_test.cpp TestKernel419
if (isAtLeastV && !isAtLeastKernelVersion(4, 19, 0)) {
if (isAtLeastV && !isAtLeastKernelVersion(4, 19)) {
ALOGE("Android V requires kernel 4.19.");
return 5;
}
// 25Q2 bumps the kernel requirement up to 5.4
// see also: //system/netd/tests/kernel_test.cpp TestKernel54
if (isAtLeast25Q2 && !isAtLeastKernelVersion(5, 4, 0)) {
if (isAtLeast25Q2 && !isAtLeastKernelVersion(5, 4)) {
ALOGE("Android 25Q2 requires kernel 5.4.");
return 6;
}
// 25Q4 bumps the kernel requirement up to 5.10
// see also: //system/netd/tests/kernel_test.cpp TestKernel510
if (isAtLeast25Q4 && !isAtLeastKernelVersion(5, 10, 0)) {
if (isAtLeast25Q4 && !isAtLeastKernelVersion(5, 10)) {
ALOGE("Android 25Q4 requires kernel 5.10.");
return 7;
}
// Technically already required by U, but only enforce on V+
// see also: //system/netd/tests/kernel_test.cpp TestKernel64Bit
if (isAtLeastV && isKernel32Bit() && isAtLeastKernelVersion(5, 16, 0)) {
if (isAtLeastV && isKernel32Bit() && isAtLeastKernelVersion(5, 16)) {
ALOGE("Android V+ platform with 32 bit kernel version >= 5.16.0 is unsupported");
if (!isTV()) return 8;
}
@ -1675,7 +1675,7 @@ static int doLoad(char** argv, char * const envp[]) {
}
// 6.6 is highest version supported by Android V, so this is effectively W+ (sdk=36+)
if (isKernel32Bit() && isAtLeastKernelVersion(6, 7, 0)) {
if (isKernel32Bit() && isAtLeastKernelVersion(6, 7)) {
ALOGE("Android platform with 32 bit kernel version >= 6.7.0 is unsupported");
return 10;
}
@ -1740,7 +1740,7 @@ static int doLoad(char** argv, char * const envp[]) {
* Note, however, that TV and Wear devices will continue to support 32-bit userspace
* on ARM64.
*/
if (isUserspace32bit() && isAtLeastKernelVersion(6, 2, 0)) {
if (isUserspace32bit() && isAtLeastKernelVersion(6, 2)) {
// Stuff won't work reliably, but...
if (isArm() && (isTV() || isWear())) {
// exempt Arm TV or Wear devices (arm32 ABI is far less problematic than x86-32)
@ -1765,7 +1765,7 @@ static int doLoad(char** argv, char * const envp[]) {
// Since officially Android only supports LTS, 6.13+ really means 6.18+,
// and won't be supported before 2026, most likely Android 17 / 26Q2.
// 6.13+ (implying 26Q2+) requires 64-bit userspace.
if (isUserspace32bit() && isAtLeastKernelVersion(6, 13, 0)) {
if (isUserspace32bit() && isAtLeastKernelVersion(6, 13)) {
// due to previous check only reachable on Arm && (<=T kernel uprev || TV || Wear)
ALOGE("64-bit userspace required on 6.13+ kernels.");
return 14;
@ -1804,7 +1804,7 @@ static int doLoad(char** argv, char * const envp[]) {
// (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)
if (!writeFile("/proc/sys/kernel/unprivileged_bpf_disabled", "0\n") &&
isAtLeastKernelVersion(5, 13, 0)) return 23;
isAtLeastKernelVersion(5, 13)) return 23;
}
if (isAtLeastU) {
@ -1858,7 +1858,7 @@ static int doLoad(char** argv, char * const envp[]) {
ALOGE("bpfGetNextMapId(zero) returned %u (errno %d)", mapId, errno);
return 33;
}
} else if (isAtLeastKernelVersion(4, 14, 0)) { // implies S through U QPR2
} else if (isAtLeastKernelVersion(4, 14)) { // implies S through U QPR2
// bpfGetNext{Prog,Map}Id require 4.14+
// furthermore since we're not running as root, we're not the initial
// platform bpfloader, so there may already be some maps & programs.
@ -1883,7 +1883,7 @@ static int doLoad(char** argv, char * const envp[]) {
// and thus it should return 0 with errno == ENOENT.
ALOGE("bpfGetNextMapId(final %d) returned %d errno %d", mapId, next, errno);
if (next || errno != ENOENT) return 35;
if (isAtLeastT || isAtLeastKernelVersion(4, 20, 0)) return 36;
if (isAtLeastT || isAtLeastKernelVersion(4, 20)) return 36;
// implies Android S with 4.14 or 4.19 kernel
ALOGW("Detected kernel with invalid BPF UAPI - disabling mainline use of eBPF.");
// leave a flag that we're 'done'