From d7b8621bde44857ebb07130693a00f5f777887d4 Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Mon, 16 Jun 2014 13:15:38 -0400 Subject: [PATCH] Change lock-task DPM authorization to packages Switch the DPM lock-task authorization to be controlled by a package rather than a component. Change-Id: Ife9bed068f31ff2449b4451ab69d3586a3f09d89 --- api/current.txt | 4 +- .../app/admin/DevicePolicyManager.java | 26 +++--- .../app/admin/IDevicePolicyManager.aidl | 6 +- .../server/am/ActivityManagerService.java | 50 +++++++---- .../server/am/ActivityStackSupervisor.java | 2 +- .../DevicePolicyManagerService.java | 89 ++++++++++--------- 6 files changed, 101 insertions(+), 76 deletions(-) diff --git a/api/current.txt b/api/current.txt index a09a853a4419f..e931331b67b28 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5229,7 +5229,7 @@ package android.app.admin { method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationBlocked(android.content.ComponentName, java.lang.String); method public boolean isDeviceOwnerApp(java.lang.String); - method public boolean isLockTaskPermitted(android.content.ComponentName); + method public boolean isLockTaskPermitted(java.lang.String); method public boolean isMasterVolumeMuted(android.content.ComponentName); method public boolean isProfileOwnerApp(java.lang.String); method public void lockNow(); @@ -5243,7 +5243,7 @@ package android.app.admin { method public void setCameraDisabled(android.content.ComponentName, boolean); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public void setKeyguardDisabledFeatures(android.content.ComponentName, int); - method public void setLockTaskComponents(android.content.ComponentName[]) throws java.lang.SecurityException; + method public void setLockTaskPackages(java.lang.String[]) throws java.lang.SecurityException; method public void setMasterVolumeMuted(android.content.ComponentName, boolean); method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int); method public void setMaximumTimeToLock(android.content.ComponentName, long); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index e80c7616204fb..ae1a4e7428e62 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -18,6 +18,7 @@ package android.app.admin; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -2340,15 +2341,20 @@ public class DevicePolicyManager { } /** - * Sets which components may enter lock task mode. + * Sets which packages may enter lock task mode. + * + *

Any packages that shares uid with an allowed package will also be allowed + * to activate lock task. * * This function can only be called by the device owner or the profile owner. - * @param components The list of components allowed to enter lock task mode + * @param packages The list of packages allowed to enter lock task mode + * + * @see Activity#startLockTask() */ - public void setLockTaskComponents(ComponentName[] components) throws SecurityException { + public void setLockTaskPackages(String[] packages) throws SecurityException { if (mService != null) { try { - mService.setLockTaskComponents(components); + mService.setLockTaskPackages(packages); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -2356,13 +2362,13 @@ public class DevicePolicyManager { } /** - * This function returns the list of components allowed to start the lock task mode. + * This function returns the list of packages allowed to start the lock task mode. * @hide */ - public ComponentName[] getLockTaskComponents() { + public String[] getLockTaskPackages() { if (mService != null) { try { - return mService.getLockTaskComponents(); + return mService.getLockTaskPackages(); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -2373,12 +2379,12 @@ public class DevicePolicyManager { /** * This function lets the caller know whether the given component is allowed to start the * lock task mode. - * @param component The component to check + * @param pkg The package to check */ - public boolean isLockTaskPermitted(ComponentName component) { + public boolean isLockTaskPermitted(String pkg) { if (mService != null) { try { - return mService.isLockTaskPermitted(component); + return mService.isLockTaskPermitted(pkg); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index a1caa2199b1da..8272c07af031d 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -142,9 +142,9 @@ interface IDevicePolicyManager { void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); String[] getAccountTypesWithManagementDisabled(); - void setLockTaskComponents(in ComponentName[] components); - ComponentName[] getLockTaskComponents(); - boolean isLockTaskPermitted(in ComponentName component); + void setLockTaskPackages(in String[] packages); + String[] getLockTaskPackages(); + boolean isLockTaskPermitted(in String pkg); void setGlobalSetting(in ComponentName who, in String setting, in String value); void setSecureSetting(in ComponentName who, in String setting, in String value); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 697e1f203336e..1d9cf5b3c3a19 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7625,14 +7625,24 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private boolean isLockTaskAuthorized(ComponentName name) { + private boolean isLockTaskAuthorized(String pkg) { final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); - return dpm != null && dpm.isLockTaskPermitted(name); + try { + int uid = mContext.getPackageManager().getPackageUid(pkg, + Binder.getCallingUserHandle().getIdentifier()); + return (uid == Binder.getCallingUid()) && dpm != null && dpm.isLockTaskPermitted(pkg); + } catch (NameNotFoundException e) { + return false; + } } private void startLockTaskMode(TaskRecord task) { - if (!isLockTaskAuthorized(task.intent.getComponent())) { + final String pkg; + synchronized (this) { + pkg = task.intent.getComponent().getPackageName(); + } + if (!isLockTaskAuthorized(pkg)) { return; } long ident = Binder.clearCallingIdentity(); @@ -7641,6 +7651,9 @@ public final class ActivityManagerService extends ActivityManagerNative // Since we lost lock on task, make sure it is still there. task = mStackSupervisor.anyTaskForIdLocked(task.taskId); if (task != null) { + if ((mFocusedActivity == null) || (task != mFocusedActivity.task)) { + throw new IllegalArgumentException("Invalid task, not in foreground"); + } mStackSupervisor.setLockTaskModeLocked(task); } } @@ -7651,25 +7664,25 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public void startLockTaskMode(int taskId) { + final TaskRecord task; long ident = Binder.clearCallingIdentity(); try { - final TaskRecord task; synchronized (this) { task = mStackSupervisor.anyTaskForIdLocked(taskId); } - if (task != null) { - startLockTaskMode(task); - } } finally { Binder.restoreCallingIdentity(ident); } + if (task != null) { + startLockTaskMode(task); + } } @Override public void startLockTaskMode(IBinder token) { + final TaskRecord task; long ident = Binder.clearCallingIdentity(); try { - final TaskRecord task; synchronized (this) { final ActivityRecord r = ActivityRecord.forToken(token); if (r == null) { @@ -7677,24 +7690,27 @@ public final class ActivityManagerService extends ActivityManagerNative } task = r.task; } - if (task != null) { - startLockTaskMode(task); - } } finally { Binder.restoreCallingIdentity(ident); } + if (task != null) { + startLockTaskMode(task); + } } @Override public void stopLockTaskMode() { - // Check if the calling task is eligible to use lock task - final int uid = Binder.getCallingUid(); + // Verify that the user matches the package of the intent for the TaskRecord + // we are locked to. This will ensure the same caller for startLockTaskMode and + // stopLockTaskMode. try { - final String name = AppGlobals.getPackageManager().getNameForUid(uid); - if (!isLockTaskAuthorized(new ComponentName(name, name))) { - return; + String pkg = mStackSupervisor.mLockTaskModeTask.intent.getPackage(); + int uid = mContext.getPackageManager().getPackageUid(pkg, + Binder.getCallingUserHandle().getIdentifier()); + if (uid != Binder.getCallingUid()) { + throw new SecurityException("Invalid uid, expected " + uid); } - } catch (RemoteException e) { + } catch (NameNotFoundException e) { Log.d(TAG, "stopLockTaskMode " + e); return; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 66e9eb3e0134d..278fa3eec18dd 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -251,7 +251,7 @@ public final class ActivityStackSupervisor implements DisplayListener { /** If non-null then the task specified remains in front and no other tasks may be started * until the task exits or #stopLockTaskMode() is called. */ - private TaskRecord mLockTaskModeTask; + TaskRecord mLockTaskModeTask; public ActivityStackSupervisor(ActivityManagerService service) { mService = service; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4574caf203226..765a33d274919 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -195,7 +195,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { = new ArrayList(); // This is the list of component allowed to start lock task mode. - final List mLockTaskComponents = new ArrayList(); + final List mLockTaskPackages = new ArrayList(); ComponentName mRestrictionsProvider; @@ -1014,10 +1014,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.endTag(null, "active-password"); } - for (int i=0; i outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { @@ -1131,9 +1131,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { parser.getAttributeValue(null, "nonletter")); XmlUtils.skipCurrentTag(parser); } else if (LOCK_TASK_COMPONENTS_XML.equals(tag)) { - policy.mLockTaskComponents.add - (ComponentName.unflattenFromString - (parser.getAttributeValue(null, "name"))); + policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name")); XmlUtils.skipCurrentTag(parser); } else { Slog.w(LOG_TAG, "Unknown tag: " + tag); @@ -3723,38 +3721,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } /** - * Sets which componets may enter lock task mode. + * Sets which packages may enter lock task mode. * * This function can only be called by the device owner or the profile owner. * @param components The list of components allowed to enter lock task mode. */ - public void setLockTaskComponents(ComponentName[] components) throws SecurityException { + public void setLockTaskPackages(String[] packages) throws SecurityException { // Get the package names of the caller. int uid = Binder.getCallingUid(); String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); - // Check whether any of the package name is the device owner or the profile owner. - for (int i=0; i