Merge "Block adb from changing certain settings value when corresponding user restriction is on." into pi-dev
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user