vendorBpfLoader: kernel is guaranteed to be 5.4+

(even 5.10+)

Test: TreeHugger
Flag: EXEMPT cleanup
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I4c9a2a222071095559b1605d4417f93eecf4667f
This commit is contained in:
Maciej Żenczykowski 2025-07-16 08:33:00 -07:00
commit 174cddec91

View file

@ -432,7 +432,7 @@ static int getSymNameByIdx(ifstream& elfFile, int index, string& name) {
}
static bool mapMatchesExpectations(const unique_fd& fd, const string& mapName,
const struct bpf_map_def& mapDef, const enum bpf_map_type type) {
const struct bpf_map_def& mapDef) {
// Assuming fd is a valid Bpf Map file descriptor then
// all the following should always succeed on a 4.14+ kernel.
// If they somehow do fail, they'll return -1 (and set errno),
@ -446,14 +446,14 @@ static bool mapMatchesExpectations(const unique_fd& fd, const string& mapName,
// DEVMAPs are readonly from the bpf program side's point of view, as such
// the kernel in kernel/bpf/devmap.c dev_map_init_map() will set the flag
int desired_map_flags = (int)mapDef.map_flags;
if (type == BPF_MAP_TYPE_DEVMAP || type == BPF_MAP_TYPE_DEVMAP_HASH)
if (mapDef.type == BPF_MAP_TYPE_DEVMAP || mapDef.type == BPF_MAP_TYPE_DEVMAP_HASH)
desired_map_flags |= BPF_F_RDONLY_PROG;
// The .h file enforces that this is a power of two, and page size will
// also always be a power of two, so this logic is actually enough to
// force it to be a multiple of the page size, as required by the kernel.
unsigned int desired_max_entries = mapDef.max_entries;
if (type == BPF_MAP_TYPE_RINGBUF) {
if (mapDef.type == BPF_MAP_TYPE_RINGBUF) {
if (desired_max_entries < page_size) desired_max_entries = page_size;
}
@ -464,7 +464,7 @@ static bool mapMatchesExpectations(const unique_fd& fd, const string& mapName,
// Another possibility is that something is misconfigured in the code:
// most likely a shared map is declared twice differently.
// But such a change should never be checked into the source tree...
if ((fd_type == type) &&
if ((fd_type == mapDef.type) &&
(fd_key_size == (int)mapDef.key_size) &&
(fd_value_size == (int)mapDef.value_size) &&
(fd_max_entries == (int)desired_max_entries) &&
@ -474,7 +474,7 @@ static bool mapMatchesExpectations(const unique_fd& fd, const string& mapName,
ALOGE("bpf map name %s mismatch: desired/found: "
"type:%d/%d key:%u/%d value:%u/%d entries:%u/%d flags:%u/%d",
mapName.c_str(), type, fd_type, mapDef.key_size, fd_key_size, mapDef.value_size,
mapName.c_str(), mapDef.type, fd_type, mapDef.key_size, fd_key_size, mapDef.value_size,
fd_value_size, mapDef.max_entries, fd_max_entries, desired_map_flags, fd_map_flags);
return false;
}
@ -520,23 +520,11 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector<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
// of be approximated: HASH has the same userspace visible api.
// However it cannot be used by ebpf programs in the same way.
// Since bpf_redirect_map() only requires 4.14, a program using a DEVMAP_HASH map
// would fail to load (due to trying to redirect to a HASH instead of DEVMAP_HASH).
// One must thus tag any BPF_MAP_TYPE_DEVMAP_HASH + bpf_redirect_map() using
// programs as being 5.4+...
type = BPF_MAP_TYPE_HASH;
}
// The .h file enforces that this is a power of two, and page size will
// also always be a power of two, so this logic is actually enough to
// force it to be a multiple of the page size, as required by the kernel.
unsigned int max_entries = md[i].max_entries;
if (type == BPF_MAP_TYPE_RINGBUF) {
if (md[i].type == BPF_MAP_TYPE_RINGBUF) {
if (max_entries < page_size) max_entries = page_size;
}
@ -556,7 +544,7 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>&
reuse = true;
} else {
union bpf_attr req = {
.map_type = type,
.map_type = md[i].type,
.key_size = md[i].key_size,
.value_size = md[i].value_size,
.max_entries = max_entries,
@ -573,7 +561,7 @@ static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>&
// When reusing a pinned map, we need to check the map type/sizes/etc match, but for
// safety (since reuse code path is rare) run these checks even if we just created it.
// We assume failure is due to pinned map mismatch, hence the 'NOT UNIQUE' return code.
if (!mapMatchesExpectations(fd, mapNames[i], md[i], type)) return -ENOTUNIQ;
if (!mapMatchesExpectations(fd, mapNames[i], md[i])) return -ENOTUNIQ;
if (!reuse) {
ret = bpfFdPin(fd, mapPinLoc.c_str());