diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-11 02:16:53 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-11 02:16:53 +0000 |
commit | 00d87c8b43518e63bb7e96e200de483f5adfc239 (patch) | |
tree | c70d383e0550ea0fcc745fb9110c9edb6aa3b438 | |
parent | 3bce5a58d0b9697a4a0242cccd5ceccbf3279b25 (diff) | |
parent | d2d03abc6da38a32a45ed3582ba61195db0840cf (diff) | |
download | ContactsProvider-android12-platform-release.tar.gz |
Merge cherrypicks of [18841655] into sc-platform-release.android-platform-12.0.0_r30android-platform-12.0.0_r29android-platform-12.0.0_r28android-platform-12.0.0_r27android-platform-12.0.0_r26android-platform-12.0.0_r25android-platform-12.0.0_r24android-platform-12.0.0_r23android-platform-12.0.0_r22android-platform-12.0.0_r21android-platform-12.0.0_r20android-platform-12.0.0_r19android-platform-12.0.0_r18android-platform-12.0.0_r17android-platform-12.0.0_r16android-platform-12.0.0_r15android-platform-12.0.0_r14android-platform-12.0.0_r13android-platform-12.0.0_r12android-platform-12.0.0_r11android-platform-12.0.0_r10android12-platform-release
Change-Id: I947f89e6736ae39f921a6a5e9c74a39e57584c48
-rw-r--r-- | src/com/android/providers/contacts/CallLogProvider.java | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java index 991413eb..589bd041 100644 --- a/src/com/android/providers/contacts/CallLogProvider.java +++ b/src/com/android/providers/contacts/CallLogProvider.java @@ -36,6 +36,7 @@ import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; +import android.database.sqlite.SQLiteTokenizer; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -54,6 +55,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.EventLog; import android.util.Log; +import android.util.EventLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ProviderAccessStats; @@ -81,6 +83,8 @@ import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.stream.Collectors; @@ -432,10 +436,11 @@ public class CallLogProvider extends ContentProvider { List<String> pathSegments = uri.getPathSegments(); String phoneNumber = pathSegments.size() >= 2 ? pathSegments.get(2) : null; if (!TextUtils.isEmpty(phoneNumber)) { - qb.appendWhere("PHONE_NUMBERS_EQUAL(number, "); - qb.appendWhereEscapeString(phoneNumber); + qb.appendWhere("PHONE_NUMBERS_EQUAL(number, ?"); qb.appendWhere(mUseStrictPhoneNumberComparation ? ", 1)" : ", 0, " + mMinMatch + ")"); + selectionArgs = copyArrayAndAppendElement(selectionArgs, + "'" + phoneNumber + "'"); } else { qb.appendWhere(Calls.NUMBER_PRESENTATION + "!=" + Calls.PRESENTATION_ALLOWED); @@ -457,12 +462,68 @@ public class CallLogProvider extends ContentProvider { final SQLiteDatabase db = mDbHelper.getReadableDatabase(); final Cursor c = qb.query(db, projection, selectionBuilder.build(), selectionArgs, null, null, sortOrder, limitClause); + + if (match == CALLS_FILTER && selectionArgs.length > 0) { + // throw SE if the user is sending requests that try to bypass voicemail permissions + examineEmptyCursorCause(c, selectionArgs[selectionArgs.length - 1]); + } + if (c != null) { c.setNotificationUri(getContext().getContentResolver(), CallLog.CONTENT_URI); } return c; } + /** + * Helper method for queryInternal that appends an extra argument to the existing selection + * arguments array. + * + * @param oldSelectionArguments the existing selection argument array in queryInternal + * @param phoneNumber the phoneNumber that was passed into queryInternal + * @return the new selection argument array with the phoneNumber as the last argument + */ + private String[] copyArrayAndAppendElement(String[] oldSelectionArguments, String phoneNumber) { + if (oldSelectionArguments == null) { + return new String[]{phoneNumber}; + } + String[] newSelectionArguments = new String[oldSelectionArguments.length + 1]; + System.arraycopy(oldSelectionArguments, 0, newSelectionArguments, 0, + oldSelectionArguments.length); + newSelectionArguments[oldSelectionArguments.length] = phoneNumber; + return newSelectionArguments; + } + + /** + * Helper that throws a Security Exception if the Cursor object is empty && the phoneNumber + * appears to have SQL. + * + * @param cursor returned from the query. + * @param phoneNumber string to check for SQL. + */ + private void examineEmptyCursorCause(Cursor cursor, String phoneNumber) { + // checks if the cursor is empty + if ((cursor == null) || !cursor.moveToFirst()) { + try { + // tokenize the phoneNumber and run each token through a checker + SQLiteTokenizer.tokenize(phoneNumber, SQLiteTokenizer.OPTION_NONE, + this::enforceStrictPhoneNumber); + } catch (IllegalArgumentException e) { + EventLog.writeEvent(0x534e4554, "224771921", Binder.getCallingUid(), + ("invalid phoneNumber passed to queryInternal")); + throw new SecurityException("invalid phoneNumber passed to queryInternal"); + } + } + } + + private void enforceStrictPhoneNumber(String token) { + boolean isAllowedKeyword = SQLiteTokenizer.isKeyword(token); + Set<String> lookupTable = Set.of("UNION", "SELECT", "FROM", "WHERE", + "GROUP", "HAVING", "WINDOW", "VALUES", "ORDER", "LIMIT"); + if (!isAllowedKeyword || lookupTable.contains(token.toUpperCase(Locale.US))) { + throw new IllegalArgumentException("Invalid token " + token); + } + } + private void queryForTesting(Uri uri) { if (!uri.getBooleanQueryParameter(PARAM_KEY_QUERY_FOR_TESTING, false)) { return; |