Don't allow LOCK_PATTERN_* settings to be read with no permission
Eliminate the exception for the three LOCK_PATTERN_* settings in
LockSettingsService.checkDatabaseReadPermission().
To do this, make the public API android.provider.Settings.Secure stop
calling ILockSettings.getString() for these settings for apps targeting
a pre-M API level. Instead, just always return "0".
This should be very safe, since not only have pre-M target API levels
mostly been phased out, but the only one of these settings that didn't
*already* always return "0" was LOCK_PATTERN_VISIBLE. That one was
unlikely to be used by apps, as it just indicated whether the user had
the "Make pattern visible" preference enabled the last time they had a
pattern; it didn't reliably indicate whether the user actually had a
pattern. Only LOCK_PATTERN_ENABLED is known to have been used by an
app, and that has returned "0" since Android 11 due to commit
a486e2d780 (http://ag/10400376) moving the special-case handling of
LOCK_PATTERN_ENABLED into getBoolean() instead of getString().
Finally, remove the special-case handling of LOCK_PATTERN_ENABLED from
getBoolean(), as it's clearly not needed. This change removes the only
potential user, but the code was in the wrong place for it anyway.
Bug: 204903437
Merged-In: If7a47ae9c3834e6a9a14900e86bc5a68c7cbdc97
Change-Id: If7a47ae9c3834e6a9a14900e86bc5a68c7cbdc97
This commit is contained in:
@@ -99,7 +99,6 @@ import android.widget.Editor;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.widget.ILockSettings;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
@@ -6184,9 +6183,6 @@ public final class Settings {
|
||||
sProviderHolder,
|
||||
Secure.class);
|
||||
|
||||
private static ILockSettings sLockSettings = null;
|
||||
|
||||
private static boolean sIsSystemProcess;
|
||||
@UnsupportedAppUsage
|
||||
private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
|
||||
@UnsupportedAppUsage
|
||||
@@ -6350,35 +6346,25 @@ public final class Settings {
|
||||
return Global.getStringForUser(resolver, name, userHandle);
|
||||
}
|
||||
|
||||
if (MOVED_TO_LOCK_SETTINGS.contains(name)) {
|
||||
synchronized (Secure.class) {
|
||||
if (sLockSettings == null) {
|
||||
sLockSettings = ILockSettings.Stub.asInterface(
|
||||
(IBinder) ServiceManager.getService("lock_settings"));
|
||||
sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
|
||||
}
|
||||
}
|
||||
if (sLockSettings != null && !sIsSystemProcess) {
|
||||
// No context; use the ActivityThread's context as an approximation for
|
||||
// determining the target API level.
|
||||
Application application = ActivityThread.currentApplication();
|
||||
if (MOVED_TO_LOCK_SETTINGS.contains(name) && Process.myUid() != Process.SYSTEM_UID) {
|
||||
// No context; use the ActivityThread's context as an approximation for
|
||||
// determining the target API level.
|
||||
Application application = ActivityThread.currentApplication();
|
||||
|
||||
boolean isPreMnc = application != null
|
||||
&& application.getApplicationInfo() != null
|
||||
&& application.getApplicationInfo().targetSdkVersion
|
||||
<= VERSION_CODES.LOLLIPOP_MR1;
|
||||
if (isPreMnc) {
|
||||
try {
|
||||
return sLockSettings.getString(name, "0", userHandle);
|
||||
} catch (RemoteException re) {
|
||||
// Fall through
|
||||
}
|
||||
} else {
|
||||
throw new SecurityException("Settings.Secure." + name
|
||||
+ " is deprecated and no longer accessible."
|
||||
+ " See API documentation for potential replacements.");
|
||||
}
|
||||
boolean isPreMnc = application != null
|
||||
&& application.getApplicationInfo() != null
|
||||
&& application.getApplicationInfo().targetSdkVersion
|
||||
<= VERSION_CODES.LOLLIPOP_MR1;
|
||||
if (isPreMnc) {
|
||||
// Old apps used to get the three deprecated LOCK_PATTERN_* settings from
|
||||
// ILockSettings.getString(). For security reasons, we now just return a
|
||||
// stubbed-out value. Note: the only one of these three settings actually known
|
||||
// to have been used was LOCK_PATTERN_ENABLED, and ILockSettings.getString()
|
||||
// already always returned "0" for that starting in Android 11.
|
||||
return "0";
|
||||
}
|
||||
throw new SecurityException("Settings.Secure." + name + " is deprecated and no" +
|
||||
" longer accessible. See API documentation for potential replacements.");
|
||||
}
|
||||
|
||||
return sNameValueCache.getStringForUser(resolver, name, userHandle);
|
||||
|
||||
@@ -1065,18 +1065,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
|
||||
}
|
||||
|
||||
private static final String[] UNPROTECTED_SETTINGS = {
|
||||
// These three LOCK_PATTERN_* settings have traditionally been readable via the public API
|
||||
// android.provider.Settings.{System,Secure}.getString() without any permission.
|
||||
Settings.Secure.LOCK_PATTERN_ENABLED,
|
||||
Settings.Secure.LOCK_PATTERN_VISIBLE,
|
||||
Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
|
||||
};
|
||||
|
||||
private final void checkDatabaseReadPermission(String requestedKey, int userId) {
|
||||
if (ArrayUtils.contains(UNPROTECTED_SETTINGS, requestedKey)) {
|
||||
return;
|
||||
}
|
||||
if (!hasPermission(PERMISSION)) {
|
||||
throw new SecurityException("uid=" + getCallingUid() + " needs permission "
|
||||
+ PERMISSION + " to read " + requestedKey + " for user " + userId);
|
||||
@@ -1190,9 +1179,6 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defaultValue, int userId) {
|
||||
checkDatabaseReadPermission(key, userId);
|
||||
if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
|
||||
return getCredentialTypeInternal(userId) == CREDENTIAL_TYPE_PATTERN;
|
||||
}
|
||||
return mStorage.getBoolean(key, defaultValue, userId);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user