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:
Eric Biggers
2023-02-17 17:50:34 +00:00
parent 8128beb12a
commit c89db6f372
2 changed files with 17 additions and 45 deletions

View File

@@ -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);

View File

@@ -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);
}