diff options
| author | 2024-02-11 21:21:07 +0000 | |
|---|---|---|
| committer | 2024-02-12 21:08:52 +0000 | |
| commit | 16175f003669f36700b1a3fa5373e7f8eb323666 (patch) | |
| tree | 161c65982f4c791c9f3884fadcb2af159358a1ca | |
| parent | 1bb44936fe3a9d7feded47bd1deacec04b187a5a (diff) | |
Add EXTRA_STREAM to requireContentUriPermissionFromCaller
The Activity Manifest attribute requireContentUriPermissionFromCaller
only works for content URIs passed in Intent#getData and
Intent#getClipData. This change adds Intent#EXTRA_STREAM to that list as
it is one of the common ways for apps to pass URIs.
EXTRA_STREAM only works for URIs that the system can unparcel. If
unparcel fails, i.e. a BadParcelableException is thrown, the item is
still preserved as a LazyValue with the underlying parcel.
Bug: 293467489
Test: atest CtsContentTestCases:android.content.cts.ActivityRequireContentUriPermissionFromCallerTest
Change-Id: Idcd3b38adfd3e2ebad7e69f40d1cb822c4a0e6e4
| -rw-r--r-- | core/res/res/values/attrs_manifest.xml | 3 | ||||
| -rw-r--r-- | services/core/java/com/android/server/uri/UriGrantsManagerService.java | 50 |
2 files changed, 47 insertions, 6 deletions
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 47410125fd65..340368a108b0 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -3287,7 +3287,8 @@ {@link java.lang.SecurityException}. <p> Note that the enforcement works for content URIs inside - {@link android.content.Intent#getData} and {@link android.content.Intent#getClipData}. + {@link android.content.Intent#getData}, {@link android.content.Intent#EXTRA_STREAM}, + and {@link android.content.Intent#getClipData}. @FlaggedApi("android.security.content_uri_permission_apis") --> <attr name="requireContentUriPermissionFromCaller" format="string"> <!-- Default, no specific permissions are required. --> diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index d2f6701e313e..4af8c616b2bc 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -65,6 +65,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.net.Uri; +import android.os.BadParcelableException; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -630,16 +631,24 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub implements if (intent == null) { return null; } - Uri data = intent.getData(); - ClipData clip = intent.getClipData(); - if (data == null && clip == null) { - return null; - } + // Default userId for uris in the intent (if they don't specify it themselves) int contentUserHint = intent.getContentUserHint(); if (contentUserHint == UserHandle.USER_CURRENT) { contentUserHint = UserHandle.getUserId(callingUid); } + + if (android.security.Flags.contentUriPermissionApis()) { + enforceRequireContentUriPermissionFromCallerOnIntentExtraStream(intent, contentUserHint, + mode, callingUid, requireContentUriPermissionFromCaller); + } + + Uri data = intent.getData(); + ClipData clip = intent.getClipData(); + if (data == null && clip == null) { + return null; + } + int targetUid; if (needed != null) { targetUid = needed.targetUid; @@ -733,6 +742,37 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub implements } } + private void enforceRequireContentUriPermissionFromCallerOnIntentExtraStream(Intent intent, + int contentUserHint, int mode, int callingUid, + @RequiredContentUriPermission Integer requireContentUriPermissionFromCaller) { + try { + final Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri.class); + if (uri != null) { + final GrantUri grantUri = GrantUri.resolve(contentUserHint, uri, mode); + enforceRequireContentUriPermissionFromCaller( + requireContentUriPermissionFromCaller, grantUri, callingUid); + } + } catch (BadParcelableException e) { + Slog.w(TAG, "Failed to unparcel an URI in EXTRA_STREAM, skipping" + + " requireContentUriPermissionFromCaller: " + e); + } + + try { + final ArrayList<Uri> uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, + Uri.class); + if (uris != null) { + for (int i = uris.size() - 1; i >= 0; i--) { + final GrantUri grantUri = GrantUri.resolve(contentUserHint, uris.get(i), mode); + enforceRequireContentUriPermissionFromCaller( + requireContentUriPermissionFromCaller, grantUri, callingUid); + } + } + } catch (BadParcelableException e) { + Slog.w(TAG, "Failed to unparcel an ArrayList of URIs in EXTRA_STREAM, skipping" + + " requireContentUriPermissionFromCaller: " + e); + } + } + @GuardedBy("mLock") private void readGrantedUriPermissionsLocked() { if (DEBUG) Slog.v(TAG, "readGrantedUriPermissions()"); |