diff options
author | Robin Lee <rgl@google.com> | 2014-03-24 15:11:35 +0000 |
---|---|---|
committer | Robin Lee <rgl@google.com> | 2014-03-28 15:09:49 +0000 |
commit | 5c921daa72c6915d036a03b3bda91725a3e30539 (patch) | |
tree | 2602aca2ec9175d073e6b885a5a08c785c12aed1 /services/devicepolicy | |
parent | 7638b1f3b56d8176e401a4067b18749682635f0c (diff) | |
download | frameworks_base-5c921daa72c6915d036a03b3bda91725a3e30539.zip frameworks_base-5c921daa72c6915d036a03b3bda91725a3e30539.tar.gz frameworks_base-5c921daa72c6915d036a03b3bda91725a3e30539.tar.bz2 |
Fix privilege escalation for preferred activities
Passing in the name of an actual admin should be enough to pass the
security check as it was. This is now fixed as the caller is not
given the opportunity to spoof its own name any more.
Change-Id: Id8be4ca4c8bf3751a1ee8125cf119fa100c81d22
Diffstat (limited to 'services/devicepolicy')
-rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 128 |
1 files changed, 65 insertions, 63 deletions
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index f186b2c..983ca2d 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -170,7 +170,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int mActivePasswordNonLetter = 0; int mFailedPasswordAttempts = 0; - int mUserHandle;; + int mUserHandle; int mPasswordOwner = -1; long mLastMaximumTimeToLock = -1; @@ -722,6 +722,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int callingUid = Binder.getCallingUid(); final int userHandle = UserHandle.getUserId(callingUid); final DevicePolicyData policy = getUserData(userHandle); + + List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>(); + + // Build a list of admins for this uid matching the given ComponentName if (who != null) { ActiveAdmin admin = policy.mAdminMap.get(who); if (admin == null) { @@ -731,22 +735,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { throw new SecurityException("Admin " + who + " is not owned by uid " + Binder.getCallingUid()); } - if (!admin.info.usesPolicy(reqPolicy)) { - throw new SecurityException("Admin " + admin.info.getComponent() - + " did not specify uses-policy for: " - + admin.info.getTagForPolicy(reqPolicy)); - } - return admin; + candidates.add(admin); } else { - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) { + for (ActiveAdmin admin : policy.mAdminList) { + if (admin.getUid() == callingUid) { + candidates.add(admin); + } + } + } + + // Try to find an admin which can use reqPolicy + for (ActiveAdmin admin : candidates) { + boolean ownsDevice = isDeviceOwner(admin.info.getPackageName()); + boolean ownsProfile = (getProfileOwner(userHandle) != null + && getProfileOwner(userHandle).equals(admin.info.getPackageName())); + + if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) { + if (ownsDevice) { + return admin; + } + } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) { + if (ownsDevice || ownsProfile) { + return admin; + } + } else { + if (admin.info.usesPolicy(reqPolicy)) { return admin; } } + } + + if (who != null) { + throw new SecurityException("Admin " + candidates.get(0).info.getComponent() + + " did not specify uses-policy for: " + + candidates.get(0).info.getTagForPolicy(reqPolicy)); + } else { throw new SecurityException("No active admin owned by uid " - + Binder.getCallingUid() + " for policy #" + reqPolicy); + + Binder.getCallingUid() + " for policy:" + reqPolicy); } } @@ -2966,64 +2991,41 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private boolean isProfileOwner(String packageName, int userId) { - String profileOwnerPackage = getProfileOwner(userId); - // TODO: make public and connect with isProfileOwnerApp in DPM - return profileOwnerPackage != null && profileOwnerPackage.equals(packageName); - } - - public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter, + public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter, ComponentName activity) { - int callingUserId = UserHandle.getCallingUserId(); - Slog.d(LOG_TAG,"called by user " + callingUserId); synchronized (this) { - ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId); - if (aa == null) { - throw new SecurityException("No active admin " + admin); - } else { - if (isProfileOwner(admin.getPackageName(), callingUserId) - || isDeviceOwner(admin.getPackageName())) { - IPackageManager pm = AppGlobals.getPackageManager(); - long id = Binder.clearCallingIdentity(); - try { - pm.addPersistentPreferredActivity(filter, activity, callingUserId); - } catch (RemoteException re) { - // Shouldn't happen - } finally { - restoreCallingIdentity(id); - } - } else { - throw new SecurityException("Admin " + admin + - "is not device owner or profile owner" ); - } + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + + IPackageManager pm = AppGlobals.getPackageManager(); + long id = Binder.clearCallingIdentity(); + try { + pm.addPersistentPreferredActivity(filter, activity, UserHandle.getCallingUserId()); + } catch (RemoteException re) { + // Shouldn't happen + } finally { + restoreCallingIdentity(id); } } } - public void clearPackagePersistentPreferredActivities(ComponentName admin, - String packageName) { - int callingUserId = UserHandle.getCallingUserId(); - Slog.d(LOG_TAG,"called by user " + callingUserId); + public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) { synchronized (this) { - ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId); - if (aa == null) { - throw new SecurityException("No active admin " + admin); - } else { - if (isProfileOwner(admin.getPackageName(), callingUserId) - || isDeviceOwner(admin.getPackageName())) { - IPackageManager pm = AppGlobals.getPackageManager(); - long id = Binder.clearCallingIdentity(); - try{ - pm.clearPackagePersistentPreferredActivities(packageName, callingUserId); - } catch (RemoteException re) { - // Shouldn't happen - } finally { - restoreCallingIdentity(id); - } - } else { - throw new SecurityException("Admin " + admin + - "is not device owner or profile owner" ); - } + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + + IPackageManager pm = AppGlobals.getPackageManager(); + long id = Binder.clearCallingIdentity(); + try { + pm.clearPackagePersistentPreferredActivities(packageName, UserHandle.getCallingUserId()); + } catch (RemoteException re) { + // Shouldn't happen + } finally { + restoreCallingIdentity(id); } } } |