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

Commit aecd9616 authored by Yueming Wang's avatar Yueming Wang Committed by Android (Google) Code Review
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
parents aa79f03c 1d13eaea
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) {