Allow NetworkStack permissions in netd

The signature permission held by the NetworkStack is equivalent to all
of CONNECTIVITY_INTERNAL, NETWORK_STACK, USE_RESTRICTED_NETWORKS and
NETWORK_BYPASS_PRIVATE_DNS.

Test: Boots, WiFi working with NetworkStack not having platform
      signature perms

Change-Id: Ibd2be7eae9bbe851467be9be12177ca685a1bf23
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index f607069..902c8f5 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -40,6 +40,7 @@
 #include "InterfaceController.h"
 #include "NetdConstants.h"  // SHA256_SIZE
 #include "NetdNativeService.h"
+#include "NetdPermissions.h"
 #include "Permission.h"
 #include "Process.h"
 #include "RouteController.h"
@@ -57,13 +58,9 @@
 namespace net {
 
 namespace {
-
-const char CONNECTIVITY_INTERNAL[] = "android.permission.CONNECTIVITY_INTERNAL";
-const char NETWORK_STACK[] = "android.permission.NETWORK_STACK";
-const char DUMP[] = "android.permission.DUMP";
 const char OPT_SHORT[] = "--short";
 
-binder::Status checkPermission(const char *permission) {
+binder::Status checkAnyPermission(const std::vector<const char*>& permissions) {
     pid_t pid = IPCThreadState::self()->getCallingPid();
     uid_t uid = IPCThreadState::self()->getCallingUid();
 
@@ -73,39 +70,37 @@
     //
     // From a security perspective, there is currently no difference, because:
     // 1. The only permissions we check in netd's binder interface are CONNECTIVITY_INTERNAL
-    //    and NETWORK_STACK, which the system server will always need to have.
+    //    and NETWORK_STACK, which the system server always has (or MAINLINE_NETWORK_STACK, which
+    //    is equivalent to having both CONNECTIVITY_INTERNAL and NETWORK_STACK).
     // 2. AID_SYSTEM always has all permissions. See ActivityManager#checkComponentPermission.
-    if (uid == AID_SYSTEM || checkPermission(String16(permission), pid, uid)) {
+    if (uid == AID_SYSTEM) {
         return binder::Status::ok();
-    } else {
-        auto err = StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission);
-        return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(err.c_str()));
     }
+
+    for (const char* permission : permissions) {
+        if (checkPermission(String16(permission), pid, uid)) {
+            return binder::Status::ok();
+        }
+    }
+
+    auto err = StringPrintf("UID %d / PID %d does not have any of the following permissions: %s",
+                            uid, pid, android::base::Join(permissions, ',').c_str());
+    return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, err.c_str());
 }
 
-#define ENFORCE_DEBUGGABLE() {                              \
-    char value[PROPERTY_VALUE_MAX + 1];                     \
-    if (property_get("ro.debuggable", value, nullptr) != 1  \
-            || value[0] != '1') {                           \
-        return binder::Status::fromExceptionCode(           \
-            binder::Status::EX_SECURITY,                    \
-            String8("Not available in production builds.")  \
-        );                                                  \
-    }                                                       \
-}
+#define ENFORCE_ANY_PERMISSION(...)                                \
+    do {                                                           \
+        binder::Status status = checkAnyPermission({__VA_ARGS__}); \
+        if (!status.isOk()) {                                      \
+            return status;                                         \
+        }                                                          \
+    } while (0)
 
-#define ENFORCE_PERMISSION(permission) {                    \
-    binder::Status status = checkPermission((permission));  \
-    if (!status.isOk()) {                                   \
-        return status;                                      \
-    }                                                       \
-}
-
-#define NETD_LOCKING_RPC(permission, lock)                  \
-    ENFORCE_PERMISSION(permission);                         \
+#define NETD_LOCKING_RPC(lock, ... /* permissions */) \
+    ENFORCE_ANY_PERMISSION(__VA_ARGS__);              \
     std::lock_guard _lock(lock);
 
-#define NETD_BIG_LOCK_RPC(permission) NETD_LOCKING_RPC((permission), gBigNetdLock)
+#define NETD_BIG_LOCK_RPC(... /* permissions */) NETD_LOCKING_RPC(gBigNetdLock, __VA_ARGS__)
 
 #define RETURN_BINDER_STATUS_IF_NOT_OK(logEntry, res) \
     do {                                              \
@@ -115,6 +110,12 @@
         }                                             \
     } while (0)
 
+#define ENFORCE_INTERNAL_PERMISSIONS() \
+    ENFORCE_ANY_PERMISSION(PERM_CONNECTIVITY_INTERNAL, PERM_MAINLINE_NETWORK_STACK)
+
+#define ENFORCE_NETWORK_STACK_PERMISSIONS() \
+    ENFORCE_ANY_PERMISSION(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK)
+
 void logErrorStatus(netdutils::LogEntry& logEntry, const netdutils::Status& status) {
     gLog.log(logEntry.returns(status.code()).withAutomaticDuration());
 }
@@ -156,7 +157,7 @@
 }
 
 status_t NetdNativeService::dump(int fd, const Vector<String16> &args) {
-    const binder::Status dump_permission = checkPermission(DUMP);
+    const binder::Status dump_permission = checkAnyPermission({PERM_DUMP});
     if (!dump_permission.isOk()) {
         const String8 msg(dump_permission.toString8());
         write(fd, msg.string(), msg.size());
@@ -222,7 +223,7 @@
 }
 
 binder::Status NetdNativeService::isAlive(bool *alive) {
-    NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
+    NETD_BIG_LOCK_RPC(PERM_CONNECTIVITY_INTERNAL, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
 
     *alive = true;
@@ -233,7 +234,8 @@
 
 binder::Status NetdNativeService::firewallReplaceUidChain(const std::string& chainName,
         bool isWhitelist, const std::vector<int32_t>& uids, bool *ret) {
-    NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->firewallCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_CONNECTIVITY_INTERNAL,
+                     PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(chainName)
@@ -248,7 +250,8 @@
 }
 
 binder::Status NetdNativeService::bandwidthEnableDataSaver(bool enable, bool *ret) {
-    NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_CONNECTIVITY_INTERNAL,
+                     PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(enable);
 
     int err = gCtls->bandwidthCtrl.enableDataSaver(enable);
@@ -259,7 +262,7 @@
 
 binder::Status NetdNativeService::bandwidthSetInterfaceQuota(const std::string& ifName,
                                                              int64_t bytes) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName).arg(bytes);
 
     int res = gCtls->bandwidthCtrl.setInterfaceQuota(ifName, bytes);
@@ -269,7 +272,7 @@
 }
 
 binder::Status NetdNativeService::bandwidthRemoveInterfaceQuota(const std::string& ifName) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
 
     int res = gCtls->bandwidthCtrl.removeInterfaceQuota(ifName);
@@ -280,7 +283,7 @@
 
 binder::Status NetdNativeService::bandwidthSetInterfaceAlert(const std::string& ifName,
                                                              int64_t bytes) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName).arg(bytes);
 
     int res = gCtls->bandwidthCtrl.setInterfaceAlert(ifName, bytes);
@@ -290,7 +293,7 @@
 }
 
 binder::Status NetdNativeService::bandwidthRemoveInterfaceAlert(const std::string& ifName) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
 
     int res = gCtls->bandwidthCtrl.removeInterfaceAlert(ifName);
@@ -300,7 +303,7 @@
 }
 
 binder::Status NetdNativeService::bandwidthSetGlobalAlert(int64_t bytes) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(bytes);
 
     int res = gCtls->bandwidthCtrl.setGlobalAlert(bytes);
@@ -310,7 +313,7 @@
 }
 
 binder::Status NetdNativeService::bandwidthAddNaughtyApp(int32_t uid) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid);
 
     std::vector<std::string> appStrUids = {std::to_string(abs(uid))};
@@ -321,7 +324,7 @@
 }
 
 binder::Status NetdNativeService::bandwidthRemoveNaughtyApp(int32_t uid) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid);
 
     std::vector<std::string> appStrUids = {std::to_string(abs(uid))};
@@ -332,7 +335,7 @@
 }
 
 binder::Status NetdNativeService::bandwidthAddNiceApp(int32_t uid) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid);
 
     std::vector<std::string> appStrUids = {std::to_string(abs(uid))};
@@ -343,7 +346,7 @@
 }
 
 binder::Status NetdNativeService::bandwidthRemoveNiceApp(int32_t uid) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->bandwidthCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid);
 
     std::vector<std::string> appStrUids = {std::to_string(abs(uid))};
@@ -354,7 +357,7 @@
 }
 
 binder::Status NetdNativeService::networkCreatePhysical(int32_t netId, int32_t permission) {
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId).arg(permission);
     int ret = gCtls->netCtrl.createPhysicalNetwork(netId, convertPermission(permission));
     gLog.log(entry.returns(ret).withAutomaticDuration());
@@ -362,7 +365,7 @@
 }
 
 binder::Status NetdNativeService::networkCreateVpn(int32_t netId, bool secure) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(netId, secure);
     int ret = gCtls->netCtrl.createVirtualNetwork(netId, secure);
     gLog.log(entry.returns(ret).withAutomaticDuration());
@@ -370,7 +373,7 @@
 }
 
 binder::Status NetdNativeService::networkDestroy(int32_t netId) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     // Both of these functions manage their own locking internally.
     // Clear DNS servers before delete the cache to avoid the cache being created again.
     gCtls->resolverCtrl.clearDnsServers(netId);
@@ -379,13 +382,13 @@
 }
 
 binder::Status NetdNativeService::networkAddInterface(int32_t netId, const std::string& iface) {
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     int ret = gCtls->netCtrl.addInterfaceToNetwork(netId, iface.c_str());
     return statusFromErrcode(ret);
 }
 
 binder::Status NetdNativeService::networkRemoveInterface(int32_t netId, const std::string& iface) {
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, iface.c_str());
     return statusFromErrcode(ret);
 }
@@ -407,7 +410,7 @@
 binder::Status NetdNativeService::networkAddUidRanges(
         int32_t netId, const std::vector<UidRangeParcel>& uidRangeArray) {
     // NetworkController::addUsersToNetwork is thread-safe.
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .args(netId, uidRangeParcelVecToString(uidRangeArray));
@@ -420,7 +423,7 @@
 binder::Status NetdNativeService::networkRemoveUidRanges(
         int32_t netId, const std::vector<UidRangeParcel>& uidRangeArray) {
     // NetworkController::removeUsersFromNetwork is thread-safe.
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .args(netId, uidRangeParcelVecToString(uidRangeArray));
@@ -437,7 +440,7 @@
     // the CommandListener "network" command will need to hold this lock too, not just the ones that
     // read/modify network internal state (that is sufficient for ::dump() because it doesn't
     // look at routes, but it's not enough here).
-    NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
+    NETD_BIG_LOCK_RPC(PERM_CONNECTIVITY_INTERNAL, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .args(add, uidRangeParcelVecToString(uidRangeArray));
@@ -455,7 +458,7 @@
 
 binder::Status NetdNativeService::socketDestroy(const std::vector<UidRangeParcel>& uids,
                                                 const std::vector<int32_t>& skipUids) {
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
 
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
@@ -507,7 +510,7 @@
         const std::vector<std::string>& tlsServers,
         const std::vector<std::string>& tlsFingerprints) {
     // This function intentionally does not lock within Netd, as Bionic is thread-safe.
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(netId)
@@ -543,7 +546,7 @@
         std::vector<std::string>* tlsServers, std::vector<int32_t>* params,
         std::vector<int32_t>* stats, std::vector<int32_t>* wait_for_pending_req_timeout_count) {
     // This function intentionally does not lock within Netd, as Bionic is thread-safe.
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
 
     int err = gCtls->resolverCtrl.getResolverInfo(netId, servers, domains, tlsServers, params,
                                                   stats, wait_for_pending_req_timeout_count);
@@ -555,7 +558,7 @@
 }
 
 binder::Status NetdNativeService::tetherApplyDnsInterfaces(bool *ret) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 
     *ret = gCtls->tetherCtrl.applyDnsInterfaces();
     return binder::Status::ok();
@@ -614,7 +617,7 @@
 
 binder::Status NetdNativeService::tetherGetStats(
         std::vector<TetherStatsParcel>* tetherStatsParcelVec) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
 
@@ -630,7 +633,7 @@
 
 binder::Status NetdNativeService::interfaceAddAddress(const std::string &ifName,
         const std::string &addrString, int prefixLength) {
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
 
     const int err = InterfaceController::addAddress(
             ifName.c_str(), addrString.c_str(), prefixLength);
@@ -643,7 +646,7 @@
 
 binder::Status NetdNativeService::interfaceDelAddress(const std::string &ifName,
         const std::string &addrString, int prefixLength) {
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
 
     const int err = InterfaceController::delAddress(
             ifName.c_str(), addrString.c_str(), prefixLength);
@@ -692,7 +695,7 @@
 binder::Status NetdNativeService::getProcSysNet(int32_t ipversion, int32_t which,
                                                 const std::string& ifname,
                                                 const std::string& parameter, std::string* value) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__)
                          .args(ipversion, which, ifname, parameter);
 
@@ -716,7 +719,7 @@
                                                 const std::string& ifname,
                                                 const std::string& parameter,
                                                 const std::string& value) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__)
                          .args(ipversion, which, ifname, parameter, value);
 
@@ -736,7 +739,7 @@
 
 binder::Status NetdNativeService::ipSecSetEncapSocketOwner(const ParcelFileDescriptor& socket,
                                                            int newUid) {
-    ENFORCE_PERMISSION(NETWORK_STACK)
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     gLog.log("ipSecSetEncapSocketOwner()");
 
     uid_t callerUid = IPCThreadState::self()->getCallingUid();
@@ -751,7 +754,7 @@
         int32_t inSpi,
         int32_t* outSpi) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     gLog.log("ipSecAllocateSpi()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecAllocateSpi(
                     transformId,
@@ -770,7 +773,7 @@
         const std::vector<uint8_t>& aeadKey, int32_t aeadIcvBits, int32_t encapType,
         int32_t encapLocalPort, int32_t encapRemotePort, int32_t interfaceId) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     gLog.log("ipSecAddSecurityAssociation()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecAddSecurityAssociation(
             transformId, mode, sourceAddress, destinationAddress, underlyingNetId, spi, markValue,
@@ -784,7 +787,7 @@
         const std::string& destinationAddress, int32_t spi, int32_t markValue, int32_t markMask,
         int32_t interfaceId) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     gLog.log("ipSecDeleteSecurityAssociation()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecDeleteSecurityAssociation(
             transformId, sourceAddress, destinationAddress, spi, markValue, markMask, interfaceId));
@@ -794,7 +797,7 @@
         const ParcelFileDescriptor& socket, int32_t transformId, int32_t direction,
         const std::string& sourceAddress, const std::string& destinationAddress, int32_t spi) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     gLog.log("ipSecApplyTransportModeTransform()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecApplyTransportModeTransform(
             socket.get(), transformId, direction, sourceAddress, destinationAddress, spi));
@@ -803,7 +806,7 @@
 binder::Status NetdNativeService::ipSecRemoveTransportModeTransform(
         const ParcelFileDescriptor& socket) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+    ENFORCE_INTERNAL_PERMISSIONS();
     gLog.log("ipSecRemoveTransportModeTransform()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecRemoveTransportModeTransform(socket.get()));
 }
@@ -815,7 +818,7 @@
                                                          int32_t spi, int32_t markValue,
                                                          int32_t markMask, int32_t interfaceId) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     gLog.log("ipSecAddSecurityPolicy()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecAddSecurityPolicy(
             transformId, selAddrFamily, direction, tmplSrcAddress, tmplDstAddress, spi, markValue,
@@ -827,7 +830,7 @@
         const std::string& tmplSrcAddress, const std::string& tmplDstAddress, int32_t spi,
         int32_t markValue, int32_t markMask, int32_t interfaceId) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     gLog.log("ipSecAddSecurityPolicy()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecUpdateSecurityPolicy(
             transformId, selAddrFamily, direction, tmplSrcAddress, tmplDstAddress, spi, markValue,
@@ -839,7 +842,7 @@
                                                             int32_t direction, int32_t markValue,
                                                             int32_t markMask, int32_t interfaceId) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     gLog.log("ipSecAddSecurityPolicy()");
     return asBinderStatus(gCtls->xfrmCtrl.ipSecDeleteSecurityPolicy(
             transformId, selAddrFamily, direction, markValue, markMask, interfaceId));
@@ -851,7 +854,7 @@
                                                           int32_t iKey, int32_t oKey,
                                                           int32_t interfaceId) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
 
     netdutils::Status result = gCtls->xfrmCtrl.ipSecAddTunnelInterface(
@@ -868,7 +871,7 @@
                                                              int32_t iKey, int32_t oKey,
                                                              int32_t interfaceId) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
 
     netdutils::Status result = gCtls->xfrmCtrl.ipSecAddTunnelInterface(
@@ -881,7 +884,7 @@
 
 binder::Status NetdNativeService::ipSecRemoveTunnelInterface(const std::string& deviceName) {
     // Necessary locking done in IpSecService and kernel
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
 
     netdutils::Status result = gCtls->xfrmCtrl.ipSecRemoveTunnelInterface(deviceName);
@@ -893,27 +896,27 @@
 
 binder::Status NetdNativeService::setIPv6AddrGenMode(const std::string& ifName,
                                                      int32_t mode) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     return asBinderStatus(InterfaceController::setIPv6AddrGenMode(ifName, mode));
 }
 
 binder::Status NetdNativeService::wakeupAddInterface(const std::string& ifName,
                                                      const std::string& prefix, int32_t mark,
                                                      int32_t mask) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     return asBinderStatus(gCtls->wakeupCtrl.addInterface(ifName, prefix, mark, mask));
 }
 
 binder::Status NetdNativeService::wakeupDelInterface(const std::string& ifName,
                                                      const std::string& prefix, int32_t mark,
                                                      int32_t mask) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     return asBinderStatus(gCtls->wakeupCtrl.delInterface(ifName, prefix, mark, mask));
 }
 
 binder::Status NetdNativeService::idletimerAddInterface(const std::string& ifName, int32_t timeout,
                                                         const std::string& classLabel) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->idletimerCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->idletimerCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(ifName)
@@ -928,7 +931,7 @@
 binder::Status NetdNativeService::idletimerRemoveInterface(const std::string& ifName,
                                                            int32_t timeout,
                                                            const std::string& classLabel) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->idletimerCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->idletimerCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(ifName)
@@ -941,7 +944,7 @@
 }
 
 binder::Status NetdNativeService::strictUidCleartextPenalty(int32_t uid, int32_t policyPenalty) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->strictCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->strictCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid).arg(policyPenalty);
     StrictPenalty penalty;
     switch (policyPenalty) {
@@ -964,7 +967,7 @@
 }
 
 binder::Status NetdNativeService::clatdStart(const std::string& ifName) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->clatdCtrl.mutex);
+    NETD_LOCKING_RPC(gCtls->clatdCtrl.mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
     int res = gCtls->clatdCtrl.startClatd(ifName.c_str());
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -972,7 +975,7 @@
 }
 
 binder::Status NetdNativeService::clatdStop(const std::string& ifName) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->clatdCtrl.mutex);
+    NETD_LOCKING_RPC(gCtls->clatdCtrl.mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
     int res = gCtls->clatdCtrl.stopClatd(ifName.c_str());
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -980,7 +983,7 @@
 }
 
 binder::Status NetdNativeService::ipfwdEnabled(bool* status) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     *status = (gCtls->tetherCtrl.forwardingRequestCount() > 0) ? true : false;
     gLog.log(entry.returns(*status).withAutomaticDuration());
@@ -988,7 +991,7 @@
 }
 
 binder::Status NetdNativeService::ipfwdEnableForwarding(const std::string& requester) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(requester);
     int res = (gCtls->tetherCtrl.enableForwarding(requester.c_str())) ? 0 : -EREMOTEIO;
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -996,7 +999,7 @@
 }
 
 binder::Status NetdNativeService::ipfwdDisableForwarding(const std::string& requester) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(requester);
     int res = (gCtls->tetherCtrl.disableForwarding(requester.c_str())) ? 0 : -EREMOTEIO;
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1005,7 +1008,7 @@
 
 binder::Status NetdNativeService::ipfwdAddInterfaceForward(const std::string& fromIface,
                                                            const std::string& toIface) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(fromIface).arg(toIface);
     int res = RouteController::enableTethering(fromIface.c_str(), toIface.c_str());
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1014,7 +1017,7 @@
 
 binder::Status NetdNativeService::ipfwdRemoveInterfaceForward(const std::string& fromIface,
                                                               const std::string& toIface) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(fromIface).arg(toIface);
     int res = RouteController::disableTethering(fromIface.c_str(), toIface.c_str());
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1032,7 +1035,7 @@
 
 }  // namespace
 binder::Status NetdNativeService::interfaceGetList(std::vector<std::string>* interfaceListResult) {
-    NETD_LOCKING_RPC(NETWORK_STACK, InterfaceController::mutex);
+    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
 
     const auto& ifaceList = InterfaceController::getIfaceNames();
@@ -1057,7 +1060,7 @@
 
 binder::Status NetdNativeService::interfaceGetCfg(
         const std::string& ifName, InterfaceConfigurationParcel* interfaceGetCfgResult) {
-    NETD_LOCKING_RPC(NETWORK_STACK, InterfaceController::mutex);
+    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
 
     const auto& cfgRes = InterfaceController::getCfg(ifName);
@@ -1070,7 +1073,7 @@
 }
 
 binder::Status NetdNativeService::interfaceSetCfg(const InterfaceConfigurationParcel& cfg) {
-    NETD_LOCKING_RPC(NETWORK_STACK, InterfaceController::mutex);
+    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(interfaceConfigurationParcelToString(cfg));
@@ -1084,7 +1087,7 @@
 
 binder::Status NetdNativeService::interfaceSetIPv6PrivacyExtensions(const std::string& ifName,
                                                                     bool enable) {
-    NETD_LOCKING_RPC(NETWORK_STACK, InterfaceController::mutex);
+    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(ifName, enable);
     int res = InterfaceController::setIPv6PrivacyExtensions(ifName.c_str(), enable);
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1092,7 +1095,7 @@
 }
 
 binder::Status NetdNativeService::interfaceClearAddrs(const std::string& ifName) {
-    NETD_LOCKING_RPC(NETWORK_STACK, InterfaceController::mutex);
+    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
     int res = InterfaceController::clearAddrs(ifName.c_str());
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1100,7 +1103,7 @@
 }
 
 binder::Status NetdNativeService::interfaceSetEnableIPv6(const std::string& ifName, bool enable) {
-    NETD_LOCKING_RPC(NETWORK_STACK, InterfaceController::mutex);
+    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(ifName, enable);
     int res = InterfaceController::setEnableIPv6(ifName.c_str(), enable);
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1108,7 +1111,7 @@
 }
 
 binder::Status NetdNativeService::interfaceSetMtu(const std::string& ifName, int32_t mtuValue) {
-    NETD_LOCKING_RPC(NETWORK_STACK, InterfaceController::mutex);
+    NETD_LOCKING_RPC(InterfaceController::mutex, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(ifName, mtuValue);
     std::string mtu = std::to_string(mtuValue);
     int res = InterfaceController::setMtu(ifName.c_str(), mtu.c_str());
@@ -1117,7 +1120,7 @@
 }
 
 binder::Status NetdNativeService::tetherStart(const std::vector<std::string>& dhcpRanges) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(dhcpRanges);
     if (dhcpRanges.size() % 2 == 1) {
         return statusFromErrcode(-EINVAL);
@@ -1128,7 +1131,7 @@
 }
 
 binder::Status NetdNativeService::tetherStop() {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     int res = gCtls->tetherCtrl.stopTethering();
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1136,7 +1139,7 @@
 }
 
 binder::Status NetdNativeService::tetherIsEnabled(bool* enabled) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     *enabled = gCtls->tetherCtrl.isTetheringStarted();
     gLog.log(entry.returns(*enabled).withAutomaticDuration());
@@ -1144,7 +1147,7 @@
 }
 
 binder::Status NetdNativeService::tetherInterfaceAdd(const std::string& ifName) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
     int res = gCtls->tetherCtrl.tetherInterface(ifName.c_str());
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1152,7 +1155,7 @@
 }
 
 binder::Status NetdNativeService::tetherInterfaceRemove(const std::string& ifName) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
     int res = gCtls->tetherCtrl.untetherInterface(ifName.c_str());
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1160,7 +1163,7 @@
 }
 
 binder::Status NetdNativeService::tetherInterfaceList(std::vector<std::string>* ifList) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     for (const auto& ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
         ifList->push_back(ifname);
@@ -1171,7 +1174,7 @@
 
 binder::Status NetdNativeService::tetherDnsSet(int32_t netId,
                                                const std::vector<std::string>& dnsAddrs) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId).arg(dnsAddrs);
     int res = gCtls->tetherCtrl.setDnsForwarders(netId, dnsAddrs);
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1179,7 +1182,7 @@
 }
 
 binder::Status NetdNativeService::tetherDnsList(std::vector<std::string>* dnsList) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     for (const auto& fwdr : gCtls->tetherCtrl.getDnsForwarders()) {
         dnsList->push_back(fwdr);
@@ -1192,7 +1195,7 @@
                                                   const std::string& destination,
                                                   const std::string& nextHop) {
     // Public methods of NetworkController are thread-safe.
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(netId)
@@ -1210,7 +1213,7 @@
 binder::Status NetdNativeService::networkRemoveRoute(int32_t netId, const std::string& ifName,
                                                      const std::string& destination,
                                                      const std::string& nextHop) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(netId)
@@ -1228,7 +1231,7 @@
 binder::Status NetdNativeService::networkAddLegacyRoute(int32_t netId, const std::string& ifName,
                                                         const std::string& destination,
                                                         const std::string& nextHop, int32_t uid) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(netId)
@@ -1248,7 +1251,7 @@
                                                            const std::string& destination,
                                                            const std::string& nextHop,
                                                            int32_t uid) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .arg(netId)
@@ -1265,7 +1268,7 @@
 }
 
 binder::Status NetdNativeService::networkGetDefault(int32_t* netId) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     *netId = gCtls->netCtrl.getDefaultNetwork();
     gLog.log(entry.returns(*netId).withAutomaticDuration());
@@ -1273,7 +1276,7 @@
 }
 
 binder::Status NetdNativeService::networkSetDefault(int32_t netId) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId);
     int res = gCtls->netCtrl.setDefaultNetwork(netId);
     gLog.log(entry.returns(res).withAutomaticDuration());
@@ -1281,7 +1284,7 @@
 }
 
 binder::Status NetdNativeService::networkClearDefault() {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     unsigned netId = NETID_UNSET;
     int res = gCtls->netCtrl.setDefaultNetwork(netId);
@@ -1306,7 +1309,7 @@
 
 binder::Status NetdNativeService::networkSetPermissionForNetwork(int32_t netId,
                                                                  int32_t permission) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(netId).arg(permission);
     std::vector<unsigned> netIds = {(unsigned) netId};
     int res = gCtls->netCtrl.setPermissionForNetworks(convertPermission(permission), netIds);
@@ -1316,7 +1319,7 @@
 
 binder::Status NetdNativeService::networkSetPermissionForUser(int32_t permission,
                                                               const std::vector<int32_t>& uids) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(permission).arg(uids);
     gCtls->netCtrl.setPermissionForUsers(convertPermission(permission), intsToUids(uids));
     gLog.log(entry.withAutomaticDuration());
@@ -1324,7 +1327,7 @@
 }
 
 binder::Status NetdNativeService::networkClearPermissionForUser(const std::vector<int32_t>& uids) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uids);
     Permission permission = Permission::PERMISSION_NONE;
     gCtls->netCtrl.setPermissionForUsers(permission, intsToUids(uids));
@@ -1333,7 +1336,7 @@
 }
 
 binder::Status NetdNativeService::NetdNativeService::networkSetProtectAllow(int32_t uid) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid);
     std::vector<uid_t> uids = {(uid_t) uid};
     gCtls->netCtrl.allowProtect(uids);
@@ -1342,7 +1345,7 @@
 }
 
 binder::Status NetdNativeService::networkSetProtectDeny(int32_t uid) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid);
     std::vector<uid_t> uids = {(uid_t) uid};
     gCtls->netCtrl.denyProtect(uids);
@@ -1351,7 +1354,7 @@
 }
 
 binder::Status NetdNativeService::networkCanProtect(int32_t uid, bool* ret) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(uid);
     *ret = gCtls->netCtrl.canProtect((uid_t) uid);
     gLog.log(entry.returns(*ret).withAutomaticDuration());
@@ -1360,7 +1363,7 @@
 
 binder::Status NetdNativeService::trafficSetNetPermForUids(int32_t permission,
                                                            const std::vector<int32_t>& uids) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(permission).arg(uids);
     gCtls->trafficCtrl.setPermissionForUids(permission, intsToUids(uids));
     gLog.log(entry.withAutomaticDuration());
@@ -1408,7 +1411,7 @@
 }  // namespace
 
 binder::Status NetdNativeService::firewallSetFirewallType(int32_t firewallType) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry =
             gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(typeToString(firewallType));
     auto type = static_cast<FirewallType>(firewallType);
@@ -1420,7 +1423,7 @@
 
 binder::Status NetdNativeService::firewallSetInterfaceRule(const std::string& ifName,
                                                            int32_t firewallRule) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .args(ifName, ruleToString(firewallRule));
@@ -1433,7 +1436,7 @@
 
 binder::Status NetdNativeService::firewallSetUidRule(int32_t childChain, int32_t uid,
                                                      int32_t firewallRule) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .args(chainToString(childChain), uid, ruleToString(firewallRule));
@@ -1446,7 +1449,7 @@
 }
 
 binder::Status NetdNativeService::firewallEnableChildChain(int32_t childChain, bool enable) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry()
                          .prettyFunction(__PRETTY_FUNCTION__)
                          .args(chainToString(childChain), enable);
@@ -1459,7 +1462,7 @@
 
 binder::Status NetdNativeService::tetherAddForward(const std::string& intIface,
                                                    const std::string& extIface) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(intIface, extIface);
 
     int res = gCtls->tetherCtrl.enableNat(intIface.c_str(), extIface.c_str());
@@ -1469,7 +1472,7 @@
 
 binder::Status NetdNativeService::tetherRemoveForward(const std::string& intIface,
                                                       const std::string& extIface) {
-    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    NETD_LOCKING_RPC(gCtls->tetherCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(intIface, extIface);
 
     int res = gCtls->tetherCtrl.disableNat(intIface.c_str(), extIface.c_str());
@@ -1479,7 +1482,7 @@
 
 binder::Status NetdNativeService::setTcpRWmemorySize(const std::string& rmemValues,
                                                      const std::string& wmemValues) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(rmemValues, wmemValues);
     if (!WriteStringToFile(rmemValues, TCP_RMEM_PROC_FILE)) {
         int ret = -errno;
@@ -1497,7 +1500,7 @@
 }
 
 binder::Status NetdNativeService::getPrefix64(int netId, std::string* _aidl_return) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
 
     netdutils::IPPrefix prefix{};
     int err = gCtls->resolverCtrl.getPrefix64(netId, &prefix);
@@ -1511,7 +1514,7 @@
 
 binder::Status NetdNativeService::registerUnsolicitedEventListener(
         const android::sp<android::net::INetdUnsolicitedEventListener>& listener) {
-    ENFORCE_PERMISSION(NETWORK_STACK);
+    ENFORCE_NETWORK_STACK_PERMISSIONS();
     auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
     gCtls->eventReporter.registerUnsolEventListener(listener);
     gLog.log(entry.withAutomaticDuration());