aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-08-01 21:57:43 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2022-08-01 21:57:43 +0000
commit352bfd11e28aaad81fd61e9d7b5ac0e16df64f0a (patch)
tree71e9670c9ac6729841db30473be4b7c144fcf88d
parent4e57b8fb0a06e0b743c36391841222f3460479a5 (diff)
parent6d8f8fd47416da43579666b5bd59c7c874e84976 (diff)
downloadContactsProvider-android11-gsi.tar.gz
Merge "Merge cherrypicks of [18281751] into rvc-platform-release. am: c638a78fb3" into android11-gsiandroid11-gsi
-rw-r--r--src/com/android/providers/contacts/CallLogProvider.java66
1 files changed, 64 insertions, 2 deletions
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java
index 7a610151..01728be5 100644
--- a/src/com/android/providers/contacts/CallLogProvider.java
+++ b/src/com/android/providers/contacts/CallLogProvider.java
@@ -34,6 +34,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.UserHandle;
@@ -46,6 +47,7 @@ import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.EventLog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ProviderAccessStats;
@@ -59,6 +61,9 @@ import java.io.PrintWriter;
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;
/**
@@ -352,10 +357,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);
@@ -377,12 +383,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;