OSDN Git Service

Only system can set application restrictions via UserManager
authorEsteban Talavera <etalavera@google.com>
Fri, 11 Dec 2015 15:22:34 +0000 (15:22 +0000)
committerEsteban Talavera <etalavera@google.com>
Tue, 15 Dec 2015 18:36:34 +0000 (18:36 +0000)
Preventing apps with MANAGE_USERS from managing application
restrictions via UserManager. Application restrictions should
only be set via DevicePolicyManager.setApplicationRestrictions,
or via Settings (for restricted profiles).

Bug: 22541936
Change-Id: Ieed51ef54b4c23a73f383465e9af9b3bcf18a514

core/java/android/os/UserManager.java
services/core/java/com/android/server/pm/UserManagerService.java
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java

index 1f16c4a..c5adafe 100644 (file)
@@ -1631,12 +1631,23 @@ public class UserManager {
     }
 
     /**
-     * Returns a Bundle containing any saved application restrictions for this user, for the
+     * Returns a {@code Bundle} containing any saved application restrictions for this user, for the
      * given package name. Only an application with this package name can call this method.
+     *
+     * <p>The returned {@link Bundle} consists of key-value pairs, as defined by the application,
+     * where the types of values may be:
+     * <ul>
+     * <li>{@code boolean}
+     * <li>{@code int}
+     * <li>{@code String} or {@code String[]}
+     * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]}
+     * </ul>
+     *
      * @param packageName the package name of the calling application
-     * @return a Bundle with the restrictions as key/value pairs, or null if there are no
-     * saved restrictions. The values can be of type Boolean, String or String[], depending
-     * on the restriction type, as defined by the application.
+     * @return a {@code Bundle} with the restrictions for that package, or {@code null} if there
+     * are no saved restrictions.
+     *
+     * @see #KEY_RESTRICTIONS_PENDING
      */
     public Bundle getApplicationRestrictions(String packageName) {
         try {
index 0b59c16..f5da103 100644 (file)
@@ -1123,7 +1123,7 @@ public class UserManagerService extends IUserManager.Stub {
      */
     private static final void checkManageUsersPermission(String message) {
         final int uid = Binder.getCallingUid();
-        if (uid != Process.SYSTEM_UID && uid != 0
+        if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID
                 && ActivityManager.checkComponentPermission(
                         android.Manifest.permission.MANAGE_USERS,
                         uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
@@ -1131,6 +1131,20 @@ public class UserManagerService extends IUserManager.Stub {
         }
     }
 
+    /**
+     * Enforces that only the system UID or root's UID (on any user) can make certain calls to the
+     * UserManager.
+     *
+     * @param message used as message if SecurityException is thrown
+     * @throws SecurityException if the caller is not system or root
+     */
+    private static void checkSystemOrRoot(String message) {
+        final int uid = Binder.getCallingUid();
+        if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) {
+            throw new SecurityException("Only system may: " + message);
+        }
+    }
+
     private void writeBitmapLP(UserInfo info, Bitmap bitmap) {
         try {
             File dir = new File(mUsersDir, Integer.toString(info.id));
@@ -2071,7 +2085,7 @@ public class UserManagerService extends IUserManager.Stub {
     public Bundle getApplicationRestrictionsForUser(String packageName, int userId) {
         if (UserHandle.getCallingUserId() != userId
                 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
-            checkManageUsersPermission("get application restrictions for other users/apps");
+            checkSystemOrRoot("get application restrictions for other users/apps");
         }
         synchronized (mPackagesLock) {
             // Read the restrictions from XML
@@ -2082,7 +2096,7 @@ public class UserManagerService extends IUserManager.Stub {
     @Override
     public void setApplicationRestrictions(String packageName, Bundle restrictions,
             int userId) {
-        checkManageUsersPermission("set application restrictions");
+        checkSystemOrRoot("set application restrictions");
         synchronized (mPackagesLock) {
             if (restrictions == null || restrictions.isEmpty()) {
                 cleanAppRestrictionsForPackage(packageName, userId);
index c540e05..bdaf0ab 100644 (file)
@@ -3681,7 +3681,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     public void choosePrivateKeyAlias(final int uid, final Uri uri, final String alias,
             final IBinder response) {
         // Caller UID needs to be trusted, so we restrict this method to SYSTEM_UID callers.
-        if (UserHandle.getAppId(mInjector.binderGetCallingUid()) != Process.SYSTEM_UID) {
+        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
             return;
         }
 
@@ -4991,7 +4991,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
         if (hasUserSetupCompleted(userHandle)
-                && UserHandle.getAppId(callingUid) != Process.SYSTEM_UID) {
+                && !UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
             throw new IllegalStateException("Cannot set the profile owner on a user which is "
                     + "already set-up");
         }
@@ -5051,7 +5051,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
 
     private void enforceManageUsers() {
         final int callingUid = mInjector.binderGetCallingUid();
-        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) || callingUid == 0)) {
+        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
+                || callingUid == Process.ROOT_UID)) {
             mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
         }
     }
@@ -5062,7 +5063,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
         }
         final int callingUid = mInjector.binderGetCallingUid();
         if (userHandle == UserHandle.getUserId(callingUid)) return;
-        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) || callingUid == 0)) {
+        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
+                || callingUid == Process.ROOT_UID)) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
                     + " INTERACT_ACROSS_USERS_FULL permission");
@@ -5292,7 +5294,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     @Override
     public ComponentName getRestrictionsProvider(int userHandle) {
         synchronized (this) {
-            if (mInjector.binderGetCallingUid() != Process.SYSTEM_UID) {
+            if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
                 throw new SecurityException("Only the system can query the permission provider");
             }
             DevicePolicyData userData = getUserData(userHandle);
@@ -6303,7 +6305,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
 
     @Override
     public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) {
-        if (mInjector.binderGetCallingUid() != Process.SYSTEM_UID) {
+        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
             throw new SecurityException("notifyLockTaskModeChanged can only be called by system");
         }
         synchronized (this) {