From 174cddec913ce009d6d3c6c18979f6af70c7b4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 16 Jul 2025 08:33:00 -0700 Subject: [PATCH] vendorBpfLoader: kernel is guaranteed to be 5.4+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (even 5.10+) Test: TreeHugger Flag: EXEMPT cleanup Signed-off-by: Maciej Żenczykowski Change-Id: I4c9a2a222071095559b1605d4417f93eecf4667f --- loader/Loader.cpp | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/loader/Loader.cpp b/loader/Loader.cpp index 57a1259..f62347d 100644 --- a/loader/Loader.cpp +++ b/loader/Loader.cpp @@ -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& 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& 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& // 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());