Avoid deadlock when installing app

Symptom:
System crash is occurred by deadlock

Root cause:
ActivityManagerService's APIs usually hold a lock of itself instance.

In this case, four threads tried to take the same lock and it caused
deadlock.
Following three objects are in a three-cornered deadlocked.
- ActivityManagerService's instance
- PackageInstallerSession.mLock
- PackageManagerService.mPackages

Solution:
Call checkUidPermission before taking a lock of ActivityManagerService's
instance.

Fixes: 32425801
Test: manual
Author: Kazuki Nakayama <kazuki.x.nakayama@sonymobile.com>
Change-Id: I71ce57b1b8f3e0e9ba64b94a7b1f210b702efb6a
This commit is contained in:
Shunta Sato
2016-10-19 15:58:52 +09:00
committed by Wale Ogunwale
parent 9ac082f8bb
commit 55af6c5f70
2 changed files with 10 additions and 8 deletions

View File

@@ -2810,14 +2810,13 @@ public final class ActiveServices {
}
List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum, int flags,
int callingUid, boolean allowed) {
int callingUid, boolean allowed, boolean canInteractAcrossUsers) {
ArrayList<ActivityManager.RunningServiceInfo> res
= new ArrayList<ActivityManager.RunningServiceInfo>();
final long ident = Binder.clearCallingIdentity();
try {
if (ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, callingUid)
== PERMISSION_GRANTED) {
if (canInteractAcrossUsers) {
int[] users = mAm.mUserController.getUsers();
for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(users[ui]);

View File

@@ -17506,12 +17506,15 @@ public class ActivityManagerService extends IActivityManager.Stub
public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
int flags) {
enforceNotIsolatedCaller("getServices");
synchronized (this) {
final int callingUid = Binder.getCallingUid();
final boolean allowed = isGetTasksAllowed("getServices", Binder.getCallingPid(),
callingUid);
return mServices.getRunningServiceInfoLocked(maxNum, flags, callingUid, allowed);
final int callingUid = Binder.getCallingUid();
final boolean canInteractAcrossUsers = (ActivityManager.checkUidPermission(
INTERACT_ACROSS_USERS_FULL, callingUid) == PERMISSION_GRANTED);
final boolean allowed = isGetTasksAllowed("getServices", Binder.getCallingPid(),
callingUid);
synchronized (this) {
return mServices.getRunningServiceInfoLocked(maxNum, flags, callingUid,
allowed, canInteractAcrossUsers);
}
}