summaryrefslogtreecommitdiffstats
path: root/services/devicepolicy
diff options
context:
space:
mode:
authorRobin Lee <rgl@google.com>2014-03-24 15:11:35 +0000
committerRobin Lee <rgl@google.com>2014-03-28 15:09:49 +0000
commit5c921daa72c6915d036a03b3bda91725a3e30539 (patch)
tree2602aca2ec9175d073e6b885a5a08c785c12aed1 /services/devicepolicy
parent7638b1f3b56d8176e401a4067b18749682635f0c (diff)
downloadframeworks_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.java128
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);
}
}
}