Skip to content

Commit f300bab

Browse files
author
Nicolas Prevot
committed
Validate that the authority of incoming uris matches.
BUG: 16864837 Change-Id: I2d4473985777b9525b101c1b02ad2395342b9722
1 parent faa4b3c commit f300bab

1 file changed

Lines changed: 71 additions & 19 deletions

File tree

core/java/android/content/ContentProvider.java

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
9797

9898
private Context mContext = null;
9999
private int mMyUid;
100+
101+
// Since most Providers have only one authority, we keep both a String and a String[] to improve
102+
// performance.
103+
private String mAuthority;
104+
private String[] mAuthorities;
100105
private String mReadPermission;
101106
private String mWritePermission;
102107
private PathPermission[] mPathPermissions;
@@ -193,7 +198,7 @@ public String getProviderName() {
193198
public Cursor query(String callingPkg, Uri uri, String[] projection,
194199
String selection, String[] selectionArgs, String sortOrder,
195200
ICancellationSignal cancellationSignal) {
196-
getAndEnforceUserId(uri);
201+
validateIncomingUri(uri);
197202
uri = getUriWithoutUserId(uri);
198203
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
199204
return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
@@ -211,14 +216,15 @@ public Cursor query(String callingPkg, Uri uri, String[] projection,
211216

212217
@Override
213218
public String getType(Uri uri) {
214-
getAndEnforceUserId(uri);
219+
validateIncomingUri(uri);
215220
uri = getUriWithoutUserId(uri);
216221
return ContentProvider.this.getType(uri);
217222
}
218223

219224
@Override
220225
public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
221-
int userId = getAndEnforceUserId(uri);
226+
validateIncomingUri(uri);
227+
int userId = getUserIdFromUri(uri);
222228
uri = getUriWithoutUserId(uri);
223229
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
224230
return rejectInsert(uri, initialValues);
@@ -233,7 +239,7 @@ public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
233239

234240
@Override
235241
public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
236-
getAndEnforceUserId(uri);
242+
validateIncomingUri(uri);
237243
uri = getUriWithoutUserId(uri);
238244
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
239245
return 0;
@@ -254,20 +260,22 @@ public ContentProviderResult[] applyBatch(String callingPkg,
254260
final int[] userIds = new int[numOperations];
255261
for (int i = 0; i < numOperations; i++) {
256262
ContentProviderOperation operation = operations.get(i);
257-
userIds[i] = getAndEnforceUserId(operation.getUri());
263+
Uri uri = operation.getUri();
264+
validateIncomingUri(uri);
265+
userIds[i] = getUserIdFromUri(uri);
258266
if (userIds[i] != UserHandle.USER_CURRENT) {
259267
// Removing the user id from the uri.
260268
operation = new ContentProviderOperation(operation, true);
261269
operations.set(i, operation);
262270
}
263271
if (operation.isReadOperation()) {
264-
if (enforceReadPermission(callingPkg, operation.getUri())
272+
if (enforceReadPermission(callingPkg, uri)
265273
!= AppOpsManager.MODE_ALLOWED) {
266274
throw new OperationApplicationException("App op not allowed", 0);
267275
}
268276
}
269277
if (operation.isWriteOperation()) {
270-
if (enforceWritePermission(callingPkg, operation.getUri())
278+
if (enforceWritePermission(callingPkg, uri)
271279
!= AppOpsManager.MODE_ALLOWED) {
272280
throw new OperationApplicationException("App op not allowed", 0);
273281
}
@@ -290,7 +298,7 @@ public ContentProviderResult[] applyBatch(String callingPkg,
290298

291299
@Override
292300
public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
293-
getAndEnforceUserId(uri);
301+
validateIncomingUri(uri);
294302
uri = getUriWithoutUserId(uri);
295303
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
296304
return 0;
@@ -306,7 +314,7 @@ public int delete(String callingPkg, Uri uri, String selection, String[] selecti
306314
@Override
307315
public int update(String callingPkg, Uri uri, ContentValues values, String selection,
308316
String[] selectionArgs) {
309-
getAndEnforceUserId(uri);
317+
validateIncomingUri(uri);
310318
uri = getUriWithoutUserId(uri);
311319
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
312320
return 0;
@@ -323,7 +331,7 @@ public int update(String callingPkg, Uri uri, ContentValues values, String selec
323331
public ParcelFileDescriptor openFile(
324332
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
325333
throws FileNotFoundException {
326-
getAndEnforceUserId(uri);
334+
validateIncomingUri(uri);
327335
uri = getUriWithoutUserId(uri);
328336
enforceFilePermission(callingPkg, uri, mode);
329337
final String original = setCallingPackage(callingPkg);
@@ -339,7 +347,7 @@ public ParcelFileDescriptor openFile(
339347
public AssetFileDescriptor openAssetFile(
340348
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
341349
throws FileNotFoundException {
342-
getAndEnforceUserId(uri);
350+
validateIncomingUri(uri);
343351
uri = getUriWithoutUserId(uri);
344352
enforceFilePermission(callingPkg, uri, mode);
345353
final String original = setCallingPackage(callingPkg);
@@ -363,15 +371,15 @@ public Bundle call(String callingPkg, String method, String arg, Bundle extras)
363371

364372
@Override
365373
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
366-
getAndEnforceUserId(uri);
374+
validateIncomingUri(uri);
367375
uri = getUriWithoutUserId(uri);
368376
return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
369377
}
370378

371379
@Override
372380
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
373381
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
374-
getAndEnforceUserId(uri);
382+
validateIncomingUri(uri);
375383
uri = getUriWithoutUserId(uri);
376384
enforceFilePermission(callingPkg, uri, "r");
377385
final String original = setCallingPackage(callingPkg);
@@ -390,7 +398,8 @@ public ICancellationSignal createCancellationSignal() {
390398

391399
@Override
392400
public Uri canonicalize(String callingPkg, Uri uri) {
393-
int userId = getAndEnforceUserId(uri);
401+
validateIncomingUri(uri);
402+
int userId = getUserIdFromUri(uri);
394403
uri = getUriWithoutUserId(uri);
395404
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
396405
return null;
@@ -405,7 +414,8 @@ public Uri canonicalize(String callingPkg, Uri uri) {
405414

406415
@Override
407416
public Uri uncanonicalize(String callingPkg, Uri uri) {
408-
int userId = getAndEnforceUserId(uri);
417+
validateIncomingUri(uri);
418+
int userId = getUserIdFromUri(uri);
409419
uri = getUriWithoutUserId(uri);
410420
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
411421
return null;
@@ -619,6 +629,36 @@ public final String getCallingPackage() {
619629
return pkg;
620630
}
621631

632+
/**
633+
* Change the authorities of the ContentProvider.
634+
* This is normally set for you from its manifest information when the provider is first
635+
* created.
636+
* @hide
637+
* @param authorities the semi-colon separated authorities of the ContentProvider.
638+
*/
639+
protected final void setAuthorities(String authorities) {
640+
if (authorities.indexOf(';') == -1) {
641+
mAuthority = authorities;
642+
mAuthorities = null;
643+
} else {
644+
mAuthority = null;
645+
mAuthorities = authorities.split(";");
646+
}
647+
}
648+
649+
/** @hide */
650+
protected final boolean matchesOurAuthorities(String authority) {
651+
if (mAuthority != null) {
652+
return mAuthority.equals(authority);
653+
}
654+
int length = mAuthorities.length;
655+
for (int i = 0; i < length; i++) {
656+
if (mAuthorities[i].equals(authority)) return true;
657+
}
658+
return false;
659+
}
660+
661+
622662
/**
623663
* Change the permission required to read data from the content
624664
* provider. This is normally set for you from its manifest information
@@ -1634,6 +1674,7 @@ private void attachInfo(Context context, ProviderInfo info, boolean testing) {
16341674
setWritePermission(info.writePermission);
16351675
setPathPermissions(info.pathPermissions);
16361676
mExported = info.exported;
1677+
setAuthorities(info.authority);
16371678
}
16381679
ContentProvider.this.onCreate();
16391680
}
@@ -1727,14 +1768,25 @@ public void shutdown() {
17271768
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
17281769
writer.println("nothing to dump");
17291770
}
1771+
17301772
/** @hide */
1731-
private int getAndEnforceUserId(Uri uri) {
1732-
int userId = getUserIdFromUri(uri, UserHandle.USER_CURRENT);
1773+
private void validateIncomingUri(Uri uri) throws SecurityException {
1774+
String auth = uri.getAuthority();
1775+
int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
17331776
if (userId != UserHandle.USER_CURRENT && userId != mContext.getUserId()) {
17341777
throw new SecurityException("trying to query a ContentProvider in user "
1735-
+ mContext.getUserId() + "with a uri belonging to user " + userId);
1778+
+ mContext.getUserId() + " with a uri belonging to user " + userId);
1779+
}
1780+
if (!matchesOurAuthorities(getAuthorityWithoutUserId(auth))) {
1781+
String message = "The authority of the uri " + uri + " does not match the one of the "
1782+
+ "contentProvider: ";
1783+
if (mAuthority != null) {
1784+
message += mAuthority;
1785+
} else {
1786+
message += mAuthorities;
1787+
}
1788+
throw new SecurityException(message);
17361789
}
1737-
return userId;
17381790
}
17391791

17401792
/** @hide */

0 commit comments

Comments
 (0)