summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Azhara Assanova <azharaa@google.com> 2024-02-11 21:21:07 +0000
committer Azhara Assanova <azharaa@google.com> 2024-02-12 21:08:52 +0000
commit16175f003669f36700b1a3fa5373e7f8eb323666 (patch)
tree161c65982f4c791c9f3884fadcb2af159358a1ca
parent1bb44936fe3a9d7feded47bd1deacec04b187a5a (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.xml3
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java50
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()");