Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19d708a0 authored by Yueming Wang's avatar Yueming Wang Committed by android-build-merger
Browse files

Merge "Block adb from changing certain settings value when corresponding user...

Merge "Block adb from changing certain settings value when corresponding user restriction is on." into pi-dev
am: aecd9616

Change-Id: I1adecc989ee77fe578e08b484edc57669937df99
parents 2c10f2e6 aecd9616
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.os;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;

@@ -206,4 +207,18 @@ public abstract class UserManagerInternal {
     * itself.
     */
    public abstract int getProfileParentId(int userId);

    /**
     * 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 {@code true} if the change is prohibited, {@code false} if the change is allowed.
     *
     * @hide
     */
    public abstract boolean isSettingRestrictedForUser(String setting, int userId, String value,
            int callingUid);
}
+21 −111
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

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>
@@ -272,6 +273,8 @@ public class SettingsProvider extends ContentProvider {
    // We have to call in the user manager with no lock held,
    private volatile UserManager mUserManager;

    private UserManagerInternal mUserManagerInternal;

    // We have to call in the package manager with no lock held,
    private volatile IPackageManager mPackageManager;

@@ -306,6 +309,7 @@ public class SettingsProvider extends ContentProvider {

        synchronized (mLock) {
            mUserManager = UserManager.get(getContext());
            mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
            mPackageManager = AppGlobals.getPackageManager();
            mHandlerThread = new HandlerThread(LOG_TAG,
                    Process.THREAD_PRIORITY_BACKGROUND);
@@ -1017,8 +1021,8 @@ 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 && mUserManagerInternal.isSettingRestrictedForUser(
                name, callingUserId, value, Binder.getCallingUid())) {
            return false;
        }

@@ -1325,8 +1329,8 @@ 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 && mUserManagerInternal.isSettingRestrictedForUser(
                name, callingUserId, value, Binder.getCallingUid())) {
            return false;
        }

@@ -1466,6 +1470,11 @@ public class SettingsProvider extends ContentProvider {
        // Resolve the userId on whose behalf the call is made.
        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);

        if (name != null && mUserManagerInternal.isSettingRestrictedForUser(
                name, callingUserId, value, Binder.getCallingUid())) {
            return false;
        }

        // Enforce what the calling package can mutate the system settings.
        enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name, callingUserId);

@@ -1579,106 +1588,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 +1787,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 com.android.server.pm.UserRestrictionsUtils#isSettingRestrictedForUser()}.
     * If DISALLOW_SHARE_LOCATION is set, the said method will only allow values with
     * the "-" prefix.
     *
     * @returns whether the enabled location providers changed.
     */
+9 −0
Original line number Diff line number Diff line
@@ -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;
@@ -3971,6 +3973,13 @@ public class UserManagerService extends IUserManager.Stub {
                return profileParent.id;
            }
        }

        @Override
        public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
                String value, int callingUid) {
            return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
                    value, callingUid);
        }
    }

    /* Remove all the users except of the system one. */
+157 −2
Original line number Diff line number Diff line
@@ -23,11 +23,13 @@ import com.android.internal.util.Preconditions;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -439,8 +441,7 @@ public class UserRestrictionsUtils {
    /**
     * Apply each user restriction.
     *
     * <p>See also {@link
     * com.android.providers.settings.SettingsProvider#isGlobalOrSecureSettingRestrictedForUser},
     * <p>See also {@link #isSettingRestrictedForUser()},
     * which should be in sync with this method.
     */
    private static void applyUserRestriction(Context context, int userId, String key,
@@ -597,6 +598,160 @@ public class UserRestrictionsUtils {
        }
    }

    public static boolean isSettingRestrictedForUser(Context context, @NonNull String setting,
            int userId, String value, int callingUid) {
        Preconditions.checkNotNull(setting);
        final UserManager mUserManager = context.getSystemService(UserManager.class);
        String restriction;
        boolean checkAllUser = false;
        switch (setting) {
            case android.provider.Settings.Secure.LOCATION_MODE:
                if (mUserManager.hasUserRestriction(
                        UserManager.DISALLOW_CONFIG_LOCATION, UserHandle.of(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 (mUserManager.hasUserRestriction(
                        UserManager.DISALLOW_CONFIG_LOCATION, UserHandle.of(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 = context.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 mUserManager.hasUserRestrictionOnAnyUser(restriction);
        } else {
            return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId));
        }
    }

    public static void dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions) {
        boolean noneSet = true;
        if (restrictions != null) {