OSDN Git Service

Block adb from changing certain settings value when corresponding user
authoryuemingw <yuemingw@google.com>
Tue, 30 Jan 2018 17:27:54 +0000 (17:27 +0000)
committeryuemingw <yuemingw@google.com>
Fri, 23 Feb 2018 16:04:45 +0000 (16:04 +0000)
restriction is on.

Check calling uid in isSettingRestrictedForUser(which is called by settingsprovider),
 and only allow system_uid when certain user restriction is on, so that user won't be
able to change these settings with adb:
Settings.Secure.LOCATION_MODE,
Settings.Secure.PROVIDERS_ALLOWED,
Settings.System.SCREEN_BRIGHTNESS,
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_OFF_TIMEOUT,
Settings.Global.AUTO_TIME,
Settings.Global.AUTO_TIME_ZONE.
This check also prevents 3rd party apps from modifying system settings value
when corresponding user restriction is on.
In addition, any attempt to change AUTO_TIME will also go through the check
for dpm.getAutoTimeRequired().

Test: manually by running the adb command with restriction set and not set
Bug: 72549013
Bug: 72548203
Bug: 72548533
Bug: 72686466
Bug: 72687105
Bug: 72940551
Bug: 72940562

Change-Id: Idfe0f1758d57958b836207ab3d55b2a292e1ae0d

core/java/android/os/IUserManager.aidl
core/java/android/os/UserManager.java
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
services/core/java/com/android/server/pm/UserManagerService.java
services/core/java/com/android/server/pm/UserRestrictionsUtils.java

index 5e23932..ad0d9fd 100644 (file)
@@ -101,4 +101,5 @@ interface IUserManager {
     boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userHandle, in IntentSender target);
     long getUserStartRealtime();
     long getUserUnlockRealtime();
+    boolean isSettingRestrictedForUser(String setting, int userId, String value);
 }
index 1856200..1248b54 100644 (file)
@@ -2731,6 +2731,25 @@ public class UserManager {
     }
 
     /**
+     * Checks whether changing a setting to a value is prohibited by the corresponding user
+     * restriction.
+     *
+     * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#applyUserRestriction(
+     * Context, int, String, boolean)}, which should be in sync with this method.
+     *
+     * @return true if the change is prohibited, false if the change is allowed.
+     *
+     * @hide
+     */
+    public boolean isSettingRestrictedForUser(String setting, int userId, String value) {
+        try {
+            return mService.isSettingRestrictedForUser(setting, userId, value);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * @hide
      * User that enforces a restriction.
      *
index bbb4fc8..2d06135 100644 (file)
 
 package com.android.providers.settings;
 
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SYSTEM_UID;
+
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -60,9 +64,9 @@ import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
-import android.provider.SettingsValidators;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
+import android.provider.SettingsValidators;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -96,13 +100,10 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
+
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 
-import static android.os.Process.ROOT_UID;
-import static android.os.Process.SHELL_UID;
-import static android.os.Process.SYSTEM_UID;
-
 
 /**
  * <p>
@@ -1017,8 +1018,7 @@ public class SettingsProvider extends ContentProvider {
 
         // If this is a setting that is currently restricted for this user, do not allow
         // unrestricting changes.
-        if (name != null && isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
-                Binder.getCallingUid())) {
+        if (name != null && mUserManager.isSettingRestrictedForUser(name, callingUserId, value)) {
             return false;
         }
 
@@ -1325,8 +1325,7 @@ public class SettingsProvider extends ContentProvider {
 
         // If this is a setting that is currently restricted for this user, do not allow
         // unrestricting changes.
-        if (name != null && isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
-                Binder.getCallingUid())) {
+        if (name != null && mUserManager.isSettingRestrictedForUser(name, callingUserId, value)) {
             return false;
         }
 
@@ -1466,6 +1465,10 @@ public class SettingsProvider extends ContentProvider {
         // Resolve the userId on whose behalf the call is made.
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
 
+        if (name != null && mUserManager.isSettingRestrictedForUser(name, callingUserId, value)) {
+            return false;
+        }
+
         // Enforce what the calling package can mutate the system settings.
         enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name, callingUserId);
 
@@ -1579,106 +1582,6 @@ public class SettingsProvider extends ContentProvider {
         return false;
     }
 
-    /**
-     * Checks whether changing a setting to a value is prohibited by the corresponding user
-     * restriction.
-     *
-     * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#applyUserRestriction(
-     * Context, int, String, boolean)}, which should be in sync with this method.
-     *
-     * @return true if the change is prohibited, false if the change is allowed.
-     */
-    private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId,
-            String value, int callingUid) {
-        String restriction;
-        boolean checkAllUser = false;
-        switch (setting) {
-            case Settings.Secure.LOCATION_MODE:
-                // Note LOCATION_MODE will be converted into LOCATION_PROVIDERS_ALLOWED
-                // in android.provider.Settings.Secure.putStringForUser(), so we shouldn't come
-                // here normally, but we still protect it here from a direct provider write.
-                if (String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(value)) return false;
-                restriction = UserManager.DISALLOW_SHARE_LOCATION;
-                break;
-
-            case Settings.Secure.LOCATION_PROVIDERS_ALLOWED:
-                // See SettingsProvider.updateLocationProvidersAllowedLocked.  "-" is to disable
-                // a provider, which should be allowed even if the user restriction is set.
-                if (value != null && value.startsWith("-")) return false;
-                restriction = UserManager.DISALLOW_SHARE_LOCATION;
-                break;
-
-            case Settings.Secure.INSTALL_NON_MARKET_APPS:
-                if ("0".equals(value)) return false;
-                restriction = UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
-                break;
-
-            case Settings.Global.ADB_ENABLED:
-                if ("0".equals(value)) return false;
-                restriction = UserManager.DISALLOW_DEBUGGING_FEATURES;
-                break;
-
-            case Settings.Global.PACKAGE_VERIFIER_ENABLE:
-            case Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB:
-                if ("1".equals(value)) return false;
-                restriction = UserManager.ENSURE_VERIFY_APPS;
-                break;
-
-            case Settings.Global.PREFERRED_NETWORK_MODE:
-                restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
-                break;
-
-            case Settings.Secure.ALWAYS_ON_VPN_APP:
-            case Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN:
-                // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn
-                final int appId = UserHandle.getAppId(callingUid);
-                if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
-                    return false;
-                }
-                restriction = UserManager.DISALLOW_CONFIG_VPN;
-                break;
-
-            case Settings.Global.SAFE_BOOT_DISALLOWED:
-                if ("1".equals(value)) return false;
-                restriction = UserManager.DISALLOW_SAFE_BOOT;
-                break;
-
-            case Settings.Global.AIRPLANE_MODE_ON:
-                if ("0".equals(value)) return false;
-                restriction = UserManager.DISALLOW_AIRPLANE_MODE;
-                break;
-
-            case Settings.Secure.DOZE_ENABLED:
-            case Settings.Secure.DOZE_ALWAYS_ON:
-            case Settings.Secure.DOZE_PULSE_ON_PICK_UP:
-            case Settings.Secure.DOZE_PULSE_ON_LONG_PRESS:
-            case Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP:
-                if ("0".equals(value)) return false;
-                restriction = UserManager.DISALLOW_AMBIENT_DISPLAY;
-                break;
-
-            case Global.LOCATION_GLOBAL_KILL_SWITCH:
-                if ("0".equals(value)) return false;
-                restriction = UserManager.DISALLOW_CONFIG_LOCATION;
-                checkAllUser = true;
-                break;
-
-            default:
-                if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
-                    if ("0".equals(value)) return false;
-                    restriction = UserManager.DISALLOW_DATA_ROAMING;
-                    break;
-                }
-                return false;
-        }
-
-        if (checkAllUser) {
-            return mUserManager.hasUserRestrictionOnAnyUser(restriction);
-        } else {
-            return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId));
-        }
-    }
-
     private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) {
         return resolveOwningUserIdLocked(userId, sSecureCloneToManagedSettings, setting);
     }
@@ -1878,8 +1781,9 @@ public class SettingsProvider extends ContentProvider {
      * But helper functions in android.providers.Settings can enable or disable
      * a single provider by using a "+" or "-" prefix before the provider name.
      *
-     * <p>See also {@link #isGlobalOrSecureSettingRestrictedForUser()}.  If DISALLOW_SHARE_LOCATION
-     * is set, the said method will only allow values with the "-" prefix.
+     * <p>See also {@link UserManager#isSettingRestrictedForUser()}.
+     * If DISALLOW_SHARE_LOCATION is set, the said method will only allow values with
+     * the "-" prefix.
      *
      * @returns whether the enabled location providers changed.
      */
index de7e21a..4d658a0 100644 (file)
@@ -31,6 +31,7 @@ import android.app.IActivityManager;
 import android.app.IStopUserCallback;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -71,6 +72,7 @@ import android.os.UserManager.EnforcingUser;
 import android.os.UserManagerInternal;
 import android.os.UserManagerInternal.UserRestrictionsListener;
 import android.os.storage.StorageManager;
+import android.provider.Settings;
 import android.security.GateKeeper;
 import android.service.gatekeeper.IGateKeeperService;
 import android.util.AtomicFile;
@@ -4038,4 +4040,158 @@ public class UserManagerService extends IUserManager.Stub {
                     + " does not match the calling uid " + callingUid);
         }
     }
+
+    @Override
+    public boolean isSettingRestrictedForUser(String setting, int userId, String value) {
+        final int callingUid = Binder.getCallingUid();
+        if (setting == null) {
+            return false;
+        }
+        String restriction;
+        boolean checkAllUser = false;
+        switch (setting) {
+            case android.provider.Settings.Secure.LOCATION_MODE:
+                if (hasUserRestriction(UserManager.DISALLOW_CONFIG_LOCATION, userId)
+                        && callingUid != Process.SYSTEM_UID) {
+                    return true;
+                } else if (String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(value)) {
+                    // Note LOCATION_MODE will be converted into LOCATION_PROVIDERS_ALLOWED
+                    // in android.provider.Settings.Secure.putStringForUser(), so we shouldn't come
+                    // here normally, but we still protect it here from a direct provider write.
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_SHARE_LOCATION;
+                break;
+
+            case android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED:
+                if (hasUserRestriction(UserManager.DISALLOW_CONFIG_LOCATION, userId)
+                        && callingUid != Process.SYSTEM_UID) {
+                    return true;
+                } else if (value != null && value.startsWith("-")) {
+                    // See SettingsProvider.updateLocationProvidersAllowedLocked.  "-" is to disable
+                    // a provider, which should be allowed even if the user restriction is set.
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_SHARE_LOCATION;
+                break;
+
+            case android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS:
+                if ("0".equals(value)) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
+                break;
+
+            case android.provider.Settings.Global.ADB_ENABLED:
+                if ("0".equals(value)) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_DEBUGGING_FEATURES;
+                break;
+
+            case android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE:
+            case android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB:
+                if ("1".equals(value)) {
+                    return false;
+                }
+                restriction = UserManager.ENSURE_VERIFY_APPS;
+                break;
+
+            case android.provider.Settings.Global.PREFERRED_NETWORK_MODE:
+                restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
+                break;
+
+            case android.provider.Settings.Secure.ALWAYS_ON_VPN_APP:
+            case android.provider.Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN:
+                // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn
+                final int appId = UserHandle.getAppId(callingUid);
+                if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_CONFIG_VPN;
+                break;
+
+            case android.provider.Settings.Global.SAFE_BOOT_DISALLOWED:
+                if ("1".equals(value)) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_SAFE_BOOT;
+                break;
+
+            case android.provider.Settings.Global.AIRPLANE_MODE_ON:
+                if ("0".equals(value)) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_AIRPLANE_MODE;
+                break;
+
+            case android.provider.Settings.Secure.DOZE_ENABLED:
+            case android.provider.Settings.Secure.DOZE_ALWAYS_ON:
+            case android.provider.Settings.Secure.DOZE_PULSE_ON_PICK_UP:
+            case android.provider.Settings.Secure.DOZE_PULSE_ON_LONG_PRESS:
+            case android.provider.Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP:
+                if ("0".equals(value)) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_AMBIENT_DISPLAY;
+                break;
+
+            case android.provider.Settings.Global.LOCATION_GLOBAL_KILL_SWITCH:
+                if ("0".equals(value)) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_CONFIG_LOCATION;
+                checkAllUser = true;
+                break;
+
+            case android.provider.Settings.System.SCREEN_BRIGHTNESS:
+            case android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE:
+                if (callingUid == Process.SYSTEM_UID) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_CONFIG_BRIGHTNESS;
+                break;
+
+            case android.provider.Settings.Global.AUTO_TIME:
+                DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+                if (dpm != null && dpm.getAutoTimeRequired()
+                        && "0".equals(value)) {
+                    return true;
+                } else if (callingUid == Process.SYSTEM_UID) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
+                break;
+
+            case android.provider.Settings.Global.AUTO_TIME_ZONE:
+                if (callingUid == Process.SYSTEM_UID) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
+                break;
+
+            case android.provider.Settings.System.SCREEN_OFF_TIMEOUT:
+                if (callingUid == Process.SYSTEM_UID) {
+                    return false;
+                }
+                restriction = UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT;
+                break;
+
+            default:
+                if (setting.startsWith(Settings.Global.DATA_ROAMING)) {
+                    if ("0".equals(value)) {
+                        return false;
+                    }
+                    restriction = UserManager.DISALLOW_DATA_ROAMING;
+                    break;
+                }
+                return false;
+        }
+
+        if (checkAllUser) {
+            return hasUserRestrictionOnAnyUser(restriction);
+        } else {
+            return hasUserRestriction(restriction, userId);
+        }
+    }
 }
index 41570c4..462e8e3 100644 (file)
@@ -439,8 +439,7 @@ public class UserRestrictionsUtils {
     /**
      * Apply each user restriction.
      *
-     * <p>See also {@link
-     * com.android.providers.settings.SettingsProvider#isGlobalOrSecureSettingRestrictedForUser},
+     * <p>See also {@link android.os.UserManager#isSettingRestrictedForUser()},
      * which should be in sync with this method.
      */
     private static void applyUserRestriction(Context context, int userId, String key,