Use bpf maps to store permission information
In newer kernels, we can use cgroup socket filter to control inet socket
creation at run time instead of paranoid network kernel check. To
achieve that, we need to get the permission information from system
server when device boots or new packages are installed. This patch
provides a binder interface to do that and stores the information in a
bpf map. It also records the uids that have permission
UPDATE_DEVICE_STATS so netd no longer needs to query that from the
system server.
Bug: 111560570
Bug: 111560739
Test: netd_unit_test, netd_integration_test
Change-Id: I0c5919d85136feec44c4406ee0bd0028b131b942
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index 5aafec8..caab84f 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -43,10 +43,12 @@
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <bpf/BpfMap.h>
#include <bpf/BpfUtils.h>
#include <cutils/multiuser.h>
#include <gtest/gtest.h>
#include <logwrap/logwrap.h>
+#include <netdbpf/bpf_shared.h>
#include <netutils/ifc.h>
#include "InterfaceController.h"
@@ -101,6 +103,12 @@
static const char* IP_RULE_V6 = "-6";
static const int TEST_NETID1 = 65501;
static const int TEST_NETID2 = 65502;
+
+// Use maximum reserved appId for applications to avoid conflict with existing
+// uids.
+static const int TEST_UID1 = 99999;
+static const int TEST_UID2 = 99998;
+
constexpr int BASE_UID = AID_USER_OFFSET * 5;
static const std::string NO_SOCKET_ALLOW_RULE("! owner UID match 0-4294967294");
@@ -2806,6 +2814,36 @@
updateAndCheckTcpBuffer(mNetd, rmemValue, wmemValue);
}
+namespace {
+
+void checkUidsExist(std::vector<int32_t>& uids, bool exist) {
+ android::bpf::BpfMap<uint32_t, uint8_t> uidPermissionMap(
+ android::bpf::mapRetrieve(UID_PERMISSION_MAP_PATH, 0));
+ for (int32_t uid : uids) {
+ android::netdutils::StatusOr<uint8_t> permission = uidPermissionMap.readValue(uid);
+ if (exist) {
+ EXPECT_TRUE(isOk(permission));
+ EXPECT_EQ(ALLOW_SOCK_CREATE, permission.value());
+ } else {
+ EXPECT_FALSE(isOk(permission));
+ EXPECT_EQ(ENOENT, permission.status().code());
+ }
+ }
+}
+
+} // namespace
+
+TEST_F(BinderTest, TestInternetPermission) {
+ SKIP_IF_BPF_NOT_SUPPORTED;
+
+ std::vector<int32_t> appUids = {TEST_UID1, TEST_UID2};
+
+ mNetd->trafficSetNetPermForUids(INetd::PERMISSION_INTERNET, appUids);
+ checkUidsExist(appUids, true);
+ mNetd->trafficSetNetPermForUids(INetd::NO_PERMISSIONS, appUids);
+ checkUidsExist(appUids, false);
+}
+
TEST_F(BinderTest, UnsolEvents) {
auto testUnsolService = android::net::TestUnsolService::start();
std::string oldTunName = sTun.name();