Move UserManagerInternal into services.jar
Because SettingsProvider needs to call through the IUserManager interface there is now a method to provide restricted-access information via that route. It has the same protection as the implicit local service call surface that was previously used: only system-uid callers can invoke it. Bug: 140833849 Test: system boots & runs normally Change-Id: I05823ca57240ab10feb382c45590541212e406c1
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
package android.os;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.IUserRestrictionsListener;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.UserManager;
|
||||
import android.content.pm.UserInfo;
|
||||
@@ -75,6 +76,8 @@ interface IUserManager {
|
||||
boolean hasBaseUserRestriction(String restrictionKey, int userHandle);
|
||||
boolean hasUserRestriction(in String restrictionKey, int userHandle);
|
||||
boolean hasUserRestrictionOnAnyUser(in String restrictionKey);
|
||||
boolean isSettingRestrictedForUser(in String setting, int userId, in String value, int callingUid);
|
||||
void addUserRestrictionsListener(IUserRestrictionsListener listener);
|
||||
void setUserRestriction(String key, boolean value, int userHandle);
|
||||
void setApplicationRestrictions(in String packageName, in Bundle restrictions,
|
||||
int userHandle);
|
||||
|
||||
26
core/java/android/os/IUserRestrictionsListener.aidl
Normal file
26
core/java/android/os/IUserRestrictionsListener.aidl
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IUserRestrictionsListener {
|
||||
void onUserRestrictionsChanged(int userId, in Bundle newRestrictions, in Bundle prevRestrictions);
|
||||
}
|
||||
@@ -1985,6 +1985,38 @@ public class UserManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
* Checks whether changing the given setting to the given value is prohibited
|
||||
* by the corresponding user restriction in the given user.
|
||||
*
|
||||
* May only be called by the OS itself.
|
||||
*
|
||||
* @return {@code true} if the change is prohibited, {@code false} if the change is allowed.
|
||||
*/
|
||||
public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
|
||||
String value, int callingUid) {
|
||||
try {
|
||||
return mService.isSettingRestrictedForUser(setting, userId, value, callingUid);
|
||||
} catch (RemoteException re) {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Register a binder callback for user restrictions changes.
|
||||
* May only be called by the OS itself.
|
||||
*/
|
||||
public void addUserRestrictionsListener(final IUserRestrictionsListener listener) {
|
||||
try {
|
||||
mService.addUserRestrictionsListener(listener);
|
||||
} catch (RemoteException re) {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the serial number for a user. This is a device-unique
|
||||
* number assigned to that user; if the user is deleted and then a new
|
||||
|
||||
@@ -56,6 +56,7 @@ import android.os.DropBoxManager;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IUserRestrictionsListener;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
@@ -65,7 +66,6 @@ import android.os.SELinux;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.UserManagerInternal;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
@@ -84,7 +84,6 @@ import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.providers.settings.SettingsState.Setting;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemConfig;
|
||||
|
||||
import com.google.android.collect.Sets;
|
||||
@@ -286,8 +285,6 @@ 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;
|
||||
|
||||
@@ -317,7 +314,6 @@ 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);
|
||||
@@ -902,95 +898,100 @@ public class SettingsProvider extends ContentProvider {
|
||||
// TODO: The current design of settings looking different based on user restrictions
|
||||
// should be reworked to keep them separate and system code should check the setting
|
||||
// first followed by checking the user restriction before performing an operation.
|
||||
UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
|
||||
userManager.addUserRestrictionsListener((int userId, Bundle newRestrictions,
|
||||
Bundle prevRestrictions) -> {
|
||||
Set<String> changedRestrictions = getRestrictionDiff(prevRestrictions, newRestrictions);
|
||||
// We are changing the settings affected by restrictions to their current
|
||||
// value with a forced update to ensure that all cross profile dependencies
|
||||
// are taken into account. Also make sure the settings update to.. the same
|
||||
// value passes the security checks, so clear binder calling id.
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_SHARE_LOCATION)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getSecureSetting(
|
||||
Settings.Secure.LOCATION_MODE, userId);
|
||||
updateSecureSetting(Settings.Secure.LOCATION_MODE,
|
||||
setting != null ? setting.getValue() : null, null,
|
||||
true, userId, true);
|
||||
setting = getSecureSetting(
|
||||
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
|
||||
updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
|
||||
setting != null ? setting.getValue() : null, null,
|
||||
true, userId, true);
|
||||
IUserRestrictionsListener listener = new IUserRestrictionsListener.Stub() {
|
||||
@Override
|
||||
public void onUserRestrictionsChanged(int userId,
|
||||
Bundle newRestrictions, Bundle prevRestrictions) {
|
||||
Set<String> changedRestrictions =
|
||||
getRestrictionDiff(prevRestrictions, newRestrictions);
|
||||
// We are changing the settings affected by restrictions to their current
|
||||
// value with a forced update to ensure that all cross profile dependencies
|
||||
// are taken into account. Also make sure the settings update to.. the same
|
||||
// value passes the security checks, so clear binder calling id.
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_SHARE_LOCATION)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getSecureSetting(
|
||||
Settings.Secure.LOCATION_MODE, userId);
|
||||
updateSecureSetting(Settings.Secure.LOCATION_MODE,
|
||||
setting != null ? setting.getValue() : null, null,
|
||||
true, userId, true);
|
||||
setting = getSecureSetting(
|
||||
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
|
||||
updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
|
||||
setting != null ? setting.getValue() : null, null,
|
||||
true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
|
||||
|| changedRestrictions.contains(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getGlobalSetting(
|
||||
Settings.Global.INSTALL_NON_MARKET_APPS);
|
||||
String value = setting != null ? setting.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS,
|
||||
value, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED);
|
||||
String value = setting != null ? setting.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.ADB_ENABLED,
|
||||
value, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.ENSURE_VERIFY_APPS)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting enable = getGlobalSetting(
|
||||
Settings.Global.PACKAGE_VERIFIER_ENABLE);
|
||||
String enableValue = enable != null ? enable.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
|
||||
enableValue, null, true, userId, true);
|
||||
Setting include = getGlobalSetting(
|
||||
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
|
||||
String includeValue = include != null ? include.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
|
||||
includeValue, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getGlobalSetting(
|
||||
Settings.Global.PREFERRED_NETWORK_MODE);
|
||||
String value = setting != null ? setting.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE,
|
||||
value, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
|
||||
|| changedRestrictions.contains(
|
||||
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS);
|
||||
String value = setting != null ? setting.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS,
|
||||
value, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED);
|
||||
String value = setting != null ? setting.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.ADB_ENABLED,
|
||||
value, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.ENSURE_VERIFY_APPS)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting enable = getGlobalSetting(
|
||||
Settings.Global.PACKAGE_VERIFIER_ENABLE);
|
||||
String enableValue = enable != null ? enable.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
|
||||
enableValue, null, true, userId, true);
|
||||
Setting include = getGlobalSetting(
|
||||
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
|
||||
String includeValue = include != null ? include.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
|
||||
includeValue, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
if (changedRestrictions.contains(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
Setting setting = getGlobalSetting(
|
||||
Settings.Global.PREFERRED_NETWORK_MODE);
|
||||
String value = setting != null ? setting.getValue() : null;
|
||||
updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE,
|
||||
value, null, true, userId, true);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
mUserManager.addUserRestrictionsListener(listener);
|
||||
}
|
||||
|
||||
private static Set<String> getRestrictionDiff(Bundle prevRestrictions, Bundle newRestrictions) {
|
||||
@@ -1185,6 +1186,17 @@ public class SettingsProvider extends ContentProvider {
|
||||
MUTATION_OPERATION_RESET, false, mode);
|
||||
}
|
||||
|
||||
private boolean isSettingRestrictedForUser(String name, int userId,
|
||||
String value, int callerUid) {
|
||||
final long oldId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return (name != null
|
||||
&& mUserManager.isSettingRestrictedForUser(name, userId, value, callerUid));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(oldId);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mutateGlobalSetting(String name, String value, String tag,
|
||||
boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
|
||||
int mode) {
|
||||
@@ -1196,8 +1208,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 && mUserManagerInternal.isSettingRestrictedForUser(
|
||||
name, callingUserId, value, Binder.getCallingUid())) {
|
||||
if (isSettingRestrictedForUser(name, callingUserId, value, Binder.getCallingUid())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1505,8 +1516,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 && mUserManagerInternal.isSettingRestrictedForUser(
|
||||
name, callingUserId, value, Binder.getCallingUid())) {
|
||||
if (isSettingRestrictedForUser(name, callingUserId, value, Binder.getCallingUid())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1646,8 +1656,7 @@ 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())) {
|
||||
if (isSettingRestrictedForUser(name, callingUserId, value, Binder.getCallingUid())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.os;
|
||||
|
||||
@@ -54,6 +54,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IProgressListener;
|
||||
import android.os.IUserManager;
|
||||
import android.os.IUserRestrictionsListener;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Parcelable;
|
||||
@@ -1606,6 +1607,36 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
|
||||
String value, int callingUid) {
|
||||
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
|
||||
throw new SecurityException("Non-system caller");
|
||||
}
|
||||
return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
|
||||
value, callingUid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addUserRestrictionsListener(final IUserRestrictionsListener listener) {
|
||||
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
|
||||
throw new SecurityException("Non-system caller");
|
||||
}
|
||||
|
||||
// NOTE: unregistering not supported; only client is the settings provider,
|
||||
// which installs a single static permanent listener. If that listener goes
|
||||
// bad it implies the whole system process is going to crash.
|
||||
mLocalService.addUserRestrictionsListener(
|
||||
(int userId, Bundle newRestrict, Bundle prevRestrict) -> {
|
||||
try {
|
||||
listener.onUserRestrictionsChanged(userId, newRestrict, prevRestrict);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e("IUserRestrictionsListener",
|
||||
"Unable to invoke listener: " + re.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
@@ -4410,7 +4441,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
@Override
|
||||
public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
|
||||
String value, int callingUid) {
|
||||
return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
|
||||
return UserManagerService.this.isSettingRestrictedForUser(setting, userId,
|
||||
value, callingUid);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user