Don't check MAINLINE_NETWORK_STACK permission for network stack
Checking permissions requires a binder IPC to the system server.
There is cross process dead lock due to binder thread exhaustion.
1. Nework stack fired a IPC to netd.
2. Netd reqired binder IPC to check permission but no free binder
thread.
3. System server is waiting the resulting call in netd.
Fix this by not checking mainline_network_stack permission if the
caller is network stack.
Bug: 149766727
Test: ON/OFF hotspot
Change-Id: I8af7d4d2ff31b7a1ab4aa56070eecf893ace81d4
Merged-In: I8af7d4d2ff31b7a1ab4aa56070eecf893ace81d4
Merged-In: I9715fa0cb7c1157d134279717222dadedf0268c5
(cherry picked from commit 6eb4fb43cff2e55eb61712b08335f0a5f42b1990)
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index 59e8b27..fb7f839 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -64,10 +64,15 @@
namespace {
const char OPT_SHORT[] = "--short";
+// The input permissions should be equivalent that this function would return ok if any of them is
+// granted.
binder::Status checkAnyPermission(const std::vector<const char*>& permissions) {
pid_t pid = IPCThreadState::self()->getCallingPid();
uid_t uid = IPCThreadState::self()->getCallingUid();
+ // TODO: Do the pure permission check in this function. Have another method
+ // (e.g. checkNetworkStackPermission) to wrap AID_SYSTEM and
+ // AID_NETWORK_STACK uid check.
// If the caller is the system UID, don't check permissions.
// Otherwise, if the system server's binder thread pool is full, and all the threads are
// blocked on a thread that's waiting for us to complete, we deadlock. http://b/69389492
@@ -79,6 +84,16 @@
if (uid == AID_SYSTEM) {
return binder::Status::ok();
}
+ // AID_NETWORK_STACK own MAINLINE_NETWORK_STACK permission, don't IPC to system server to check
+ // MAINLINE_NETWORK_STACK permission. Cross-process(netd, networkstack and system server)
+ // deadlock: http://b/149766727
+ if (uid == AID_NETWORK_STACK) {
+ for (const char* permission : permissions) {
+ if (std::strcmp(permission, PERM_MAINLINE_NETWORK_STACK) == 0) {
+ return binder::Status::ok();
+ }
+ }
+ }
for (const char* permission : permissions) {
if (checkPermission(String16(permission), pid, uid)) {