diff options
author | Hall Liu <hallliu@google.com> | 2020-01-27 15:34:04 -0800 |
---|---|---|
committer | Hall Liu <hallliu@google.com> | 2021-02-12 01:03:35 +0000 |
commit | 1b5f99d14234bd92ce3a40d1e267f8b8a1bbe3dd (patch) | |
tree | 62d1909de77ea6e079a7b69fc0fde1462c798e90 | |
parent | 2f6ca6cd85b537c8c25b2841dd5ee1ab85ecd09a (diff) | |
download | ContactsProvider-1b5f99d14234bd92ce3a40d1e267f8b8a1bbe3dd.tar.gz |
Enforce strict grammar when querying the call log
Disallow subqueries and suspicious tokens when querying from the
call log database. Also add a column to the projection so that the token
detector doesn't throw a false positive.
Bug: 143230980
Test: atest android.provider.cts.contacts.CallLogProviderTest
Change-Id: I54d2d399f449ea47aa8fb4197c718f9038da25bf
(cherry picked from commit 1e54cb39bb76f5cc12526abca99b1af017d7d3d2)
Merged-In: I54d2d399f449ea47aa8fb4197c718f9038da25bf
-rw-r--r-- | src/com/android/providers/contacts/CallLogProvider.java | 38 | ||||
-rw-r--r-- | tests/src/com/android/providers/contacts/CallLogProviderTest.java | 6 |
2 files changed, 39 insertions, 5 deletions
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java index ec1d40e9..ebe111f1 100644 --- a/src/com/android/providers/contacts/CallLogProvider.java +++ b/src/com/android/providers/contacts/CallLogProvider.java @@ -138,6 +138,7 @@ public class CallLogProvider extends ContentProvider { sCallsProjectionMap.put(Calls.FEATURES, Calls.FEATURES); sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_COMPONENT_NAME, Calls.PHONE_ACCOUNT_COMPONENT_NAME); sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ID, Calls.PHONE_ACCOUNT_ID); + sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_HIDDEN, Calls.PHONE_ACCOUNT_HIDDEN); sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ADDRESS, Calls.PHONE_ACCOUNT_ADDRESS); sCallsProjectionMap.put(Calls.NEW, Calls.NEW); sCallsProjectionMap.put(Calls.VOICEMAIL_URI, Calls.VOICEMAIL_URI); @@ -324,6 +325,13 @@ public class CallLogProvider extends ContentProvider { qb.setTables(Tables.CALLS); qb.setProjectionMap(sCallsProjectionMap); qb.setStrict(true); + // If the caller doesn't have READ_VOICEMAIL, make sure they can't + // do any SQL shenanigans to get access to the voicemails. If the caller does have the + // READ_VOICEMAIL permission, then they have sufficient permissions to access any data in + // the database, so the strict check is unnecessary. + if (!mVoicemailPermissions.callerHasReadAccess(getCallingPackage())) { + qb.setStrictGrammar(true); + } final SelectionBuilder selectionBuilder = new SelectionBuilder(selection); checkVoicemailPermissionAndAddRestriction(uri, selectionBuilder, true /*isQuery*/); @@ -529,6 +537,18 @@ public class CallLogProvider extends ContentProvider { SelectionBuilder selectionBuilder = new SelectionBuilder(selection); checkVoicemailPermissionAndAddRestriction(uri, selectionBuilder, false /*isQuery*/); + final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + qb.setTables(Tables.CALLS); + qb.setProjectionMap(sCallsProjectionMap); + qb.setStrict(true); + // If the caller doesn't have READ_VOICEMAIL, make sure they can't + // do any SQL shenanigans to get access to the voicemails. If the caller does have the + // READ_VOICEMAIL permission, then they have sufficient permissions to access any data in + // the database, so the strict check is unnecessary. + if (!mVoicemailPermissions.callerHasReadAccess(getCallingPackage())) { + qb.setStrictGrammar(true); + } + final SQLiteDatabase db = mDbHelper.getWritableDatabase(); final int matchedUriId = sURIMatcher.match(uri); switch (matchedUriId) { @@ -543,8 +563,7 @@ public class CallLogProvider extends ContentProvider { throw new UnsupportedOperationException("Cannot update URL: " + uri); } - return createDatabaseModifier(db).update(uri, Tables.CALLS, values, selectionBuilder.build(), - selectionArgs); + return qb.update(db, values, selectionBuilder.build(), selectionArgs); } private int deleteInternal(Uri uri, String selection, String[] selectionArgs) { @@ -559,14 +578,25 @@ public class CallLogProvider extends ContentProvider { SelectionBuilder selectionBuilder = new SelectionBuilder(selection); checkVoicemailPermissionAndAddRestriction(uri, selectionBuilder, false /*isQuery*/); + final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + qb.setTables(Tables.CALLS); + qb.setProjectionMap(sCallsProjectionMap); + qb.setStrict(true); + // If the caller doesn't have READ_VOICEMAIL, make sure they can't + // do any SQL shenanigans to get access to the voicemails. If the caller does have the + // READ_VOICEMAIL permission, then they have sufficient permissions to access any data in + // the database, so the strict check is unnecessary. + if (!mVoicemailPermissions.callerHasReadAccess(getCallingPackage())) { + qb.setStrictGrammar(true); + } + final SQLiteDatabase db = mDbHelper.getWritableDatabase(); final int matchedUriId = sURIMatcher.match(uri); switch (matchedUriId) { case CALLS: // TODO: Special case - We may want to forward the delete request on user 0 to the // shadow provider too. - return createDatabaseModifier(db).delete(Tables.CALLS, - selectionBuilder.build(), selectionArgs); + return qb.delete(db, selectionBuilder.build(), selectionArgs); default: throw new UnsupportedOperationException("Cannot delete that URL: " + uri); } diff --git a/tests/src/com/android/providers/contacts/CallLogProviderTest.java b/tests/src/com/android/providers/contacts/CallLogProviderTest.java index 9efdfaa4..9baf1e41 100644 --- a/tests/src/com/android/providers/contacts/CallLogProviderTest.java +++ b/tests/src/com/android/providers/contacts/CallLogProviderTest.java @@ -18,6 +18,7 @@ package com.android.providers.contacts; import android.telecom.CallerInfo; import com.android.providers.contacts.testutil.CommonDatabaseUtils; +import com.android.providers.contacts.util.ContactsPermissions; import android.content.ComponentName; import android.content.ContentProvider; @@ -59,7 +60,7 @@ public class CallLogProviderTest extends BaseContactsProvider2Test { Voicemails.DIRTY, Voicemails.DELETED}; /** Total number of columns exposed by call_log provider. */ - private static final int NUM_CALLLOG_FIELDS = 34; + private static final int NUM_CALLLOG_FIELDS = 35; private static final int MIN_MATCH = 7; @@ -194,9 +195,12 @@ public class CallLogProviderTest extends BaseContactsProvider2Test { PhoneAccountHandle subscription = new PhoneAccountHandle( sComponentName, "sub0"); + // Allow self-calls in order to add the call + ContactsPermissions.ALLOW_SELF_CALL = true; Uri uri = Calls.addCall(ci, getMockContext(), "1-800-263-7643", Calls.PRESENTATION_ALLOWED, Calls.OUTGOING_TYPE, 0, subscription, 2000, 40, null); + ContactsPermissions.ALLOW_SELF_CALL = false; assertNotNull(uri); assertEquals("0@" + CallLog.AUTHORITY, uri.getAuthority()); |