BpfHandler: add 25Q2+ netd map create and write test
Adding this to make sure we have 'unprivileged_bpf_disabled = 0'
This is currently set by NetBpfLoad, but if we remove that things currently work.
However with this change the device then fails to boot:
$ adbz logcat -s -d *:* | egrep -i -C10 bpf
I NetdUpdatable: libnetd_updatable_init: Initializing
I NetdUpdatable: BPF programs are loaded
I NetdUpdatable: initMaps successfully
E NetdUpdatable: libnetd_updatable_init: Failed: (1) [Operation not permitted] : map create failed
This is because even though system/netd/server/netd.rc has:
service netd /system/bin/netd
class main
capabilities CHOWN DAC_OVERRIDE DAC_READ_SEARCH FOWNER IPC_LOCK KILL NET_ADMIN NET_BIND_SERVICE NET_RAW SETUID SETGID
user root
group root net_admin
and we thus run as root/root with CAP_NET_ADMIN, but we do *NOT* have CAP_BPF nor CAP_SYS_ADMIN.
This means netd is considered 'unprivileged' from the point of view of that sysctl.
Creating maps from outside the bpfloader (ie. netd/system server/network stack)
is required for map-in-map.
While the sepolicy for netd.te map_create is in V, there is no real
need for this test on V atm, doing this to prevent *future* regressions.
A rollout purely to the not yet existing 25Q2+ is safer.
Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Ia39c74cfb1707e88b0aa534ddf42139b1698d5d6
diff --git a/bpf/netd/BpfHandler.cpp b/bpf/netd/BpfHandler.cpp
index bcd0cba..58ac931 100644
--- a/bpf/netd/BpfHandler.cpp
+++ b/bpf/netd/BpfHandler.cpp
@@ -274,6 +274,16 @@
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+
+ int key = 1;
+ int value = 123;
+ unique_fd map(bpf::createMap(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 2, 0));
+ if (!map.ok()) return statusFromErrno(errno, fmt::format("map create failed"));
+ int rv = bpf::writeToMapEntry(map, &key, &value, BPF_ANY);
+ if (rv) return statusFromErrno(errno, fmt::format("map write failed (rv={})", rv));
+ }
+
return netdutils::status::ok;
}