BpfMap - add BpfMapRO.init() support

Really we need to fix the inheritance to make
BpfMapRO the parent class of BpfMap:
but that's a far more difficult thing to do,
so in the short term we punt like this.

This makes BpfMapRO a little bit more usable,
and allows a slow transition across the codebase...

Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I1c5112db70e9e523c113cba536fbe19422b4d3f3
This commit is contained in:
Maciej Żenczykowski
2022-06-13 17:38:12 -07:00
parent 4b1b4090de
commit cf4b58f98f

View File

@@ -103,8 +103,29 @@ class BpfMap {
return {}; return {};
} }
protected:
[[clang::reinitializes]] base::Result<void> init(const char* path, int fd) {
mMapFd.reset(fd);
if (mMapFd == -1) {
return ErrnoErrorf("Pinned map not accessible or does not exist: ({})", path);
}
if (isAtLeastKernelVersion(4, 14, 0)) {
// Normally we should return an error here instead of calling abort,
// but this cannot happen at runtime without a massive code bug (K/V type mismatch)
// and as such it's better to just blow the system up and let the developer fix it.
// Crashes are much more likely to be noticed than logs and missing functionality.
if (bpfGetFdKeySize(mMapFd) != sizeof(Key)) abort();
if (bpfGetFdValueSize(mMapFd) != sizeof(Value)) abort();
}
return {};
}
public:
// Function that tries to get map from a pinned path. // Function that tries to get map from a pinned path.
[[clang::reinitializes]] base::Result<void> init(const char* path); [[clang::reinitializes]] base::Result<void> init(const char* path) {
return init(path, mapRetrieveRW(path));
}
#ifdef BPF_MAP_MAKE_VISIBLE_FOR_TESTING #ifdef BPF_MAP_MAKE_VISIBLE_FOR_TESTING
// due to Android SELinux limitations which prevent map creation by anyone besides the bpfloader // due to Android SELinux limitations which prevent map creation by anyone besides the bpfloader
@@ -209,23 +230,6 @@ class BpfMap {
base::unique_fd mMapFd; base::unique_fd mMapFd;
}; };
template <class Key, class Value>
base::Result<void> BpfMap<Key, Value>::init(const char* path) {
mMapFd.reset(mapRetrieveRW(path));
if (mMapFd == -1) {
return ErrnoErrorf("Pinned map not accessible or does not exist: ({})", path);
}
if (isAtLeastKernelVersion(4, 14, 0)) {
// Normally we should return an error here instead of calling abort,
// but this cannot happen at runtime without a massive code bug (K/V type mismatch)
// and as such it's better to just blow the system up and let the developer fix it.
// Crashes are much more likely to be noticed than logs and missing functionality.
if (bpfGetFdKeySize(mMapFd) != sizeof(Key)) abort();
if (bpfGetFdValueSize(mMapFd) != sizeof(Value)) abort();
}
return {};
}
template <class Key, class Value> template <class Key, class Value>
base::Result<void> BpfMap<Key, Value>::iterate( base::Result<void> BpfMap<Key, Value>::iterate(
const std::function<base::Result<void>(const Key& key, const BpfMap<Key, Value>& map)>& const std::function<base::Result<void>(const Key& key, const BpfMap<Key, Value>& map)>&
@@ -292,8 +296,15 @@ base::Result<void> BpfMap<Key, Value>::iterateWithValue(
template <class Key, class Value> template <class Key, class Value>
class BpfMapRO : public BpfMap<Key, Value> { class BpfMapRO : public BpfMap<Key, Value> {
public: public:
BpfMapRO<Key, Value>() {};
explicit BpfMapRO<Key, Value>(const char* pathname) explicit BpfMapRO<Key, Value>(const char* pathname)
: BpfMap<Key, Value>(pathname, BPF_F_RDONLY) {} : BpfMap<Key, Value>(pathname, BPF_F_RDONLY) {}
// Function that tries to get map from a pinned path.
[[clang::reinitializes]] base::Result<void> init(const char* path) {
return BpfMap<Key,Value>::init(path, mapRetrieveRO(path));
}
}; };
} // namespace bpf } // namespace bpf