Don't call into system_server for permissions check
With the recently added permission information in traffic controller,
netd can check if the calling process has permission UPDATE_DEVICE_STATS
without calling into system_server. Update the code path and add some
test cases for it.
Bug: 111560570
Bug: 111560739
Test: netd_unit_test, netd_integration_test
Change-Id: I79eee1321f32154e91466f023f7952db23df8494
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index 9aaa9fa..a30f9dd 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -92,6 +92,10 @@
return matchType;
}
+bool TrafficController::hasUpdateDeviceStatsPermission(uid_t uid) {
+ return mPrivilegedUser.find(uid) != mPrivilegedUser.end();
+}
+
const std::string UidPermissionTypeToString(uint8_t permission) {
std::string permissionType;
FLAG_MSG_TRANS(permissionType, ALLOW_SOCK_CREATE, permission);
@@ -299,7 +303,11 @@
return netdutils::status::ok;
}
-int TrafficController::tagSocket(int sockFd, uint32_t tag, uid_t uid) {
+int TrafficController::tagSocket(int sockFd, uint32_t tag, uid_t uid, uid_t callingUid) {
+ if (uid != callingUid && !hasUpdateDeviceStatsPermission(callingUid)) {
+ return -EPERM;
+ }
+
if (!ebpfSupported) {
if (legacy_tagSocket(sockFd, tag, uid)) return -errno;
return 0;
@@ -337,9 +345,11 @@
return -res.code();
}
-int TrafficController::setCounterSet(int counterSetNum, uid_t uid) {
+int TrafficController::setCounterSet(int counterSetNum, uid_t uid, uid_t callingUid) {
if (counterSetNum < 0 || counterSetNum >= OVERFLOW_COUNTERSET) return -EINVAL;
- Status res;
+
+ if (!hasUpdateDeviceStatsPermission(callingUid)) return -EPERM;
+
if (!ebpfSupported) {
if (legacy_setCounterSet(counterSetNum, uid)) return -errno;
return 0;
@@ -357,7 +367,7 @@
}
}
uint8_t tmpCounterSetNum = (uint8_t)counterSetNum;
- res = mUidCounterSetMap.writeValue(uid, tmpCounterSetNum, BPF_ANY);
+ Status res = mUidCounterSetMap.writeValue(uid, tmpCounterSetNum, BPF_ANY);
if (!isOk(res)) {
ALOGE("Failed to set the counterSet: %s, fd: %d", strerror(res.code()),
mUidCounterSetMap.getMap().get());
@@ -369,7 +379,9 @@
// This method only get called by system_server when an app get uinstalled, it
// is called inside removeUidsLocked() while holding mStatsLock. So it is safe
// to iterate and modify the stats maps.
-int TrafficController::deleteTagData(uint32_t tag, uid_t uid) {
+int TrafficController::deleteTagData(uint32_t tag, uid_t uid, uid_t callingUid) {
+ if (!hasUpdateDeviceStatsPermission(callingUid)) return -EPERM;
+
if (!ebpfSupported) {
if (legacy_deleteTagData(tag, uid)) return -errno;
return 0;