summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Michael Mikhail <michaelmikhil@google.com> 2023-05-26 16:36:04 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2023-05-26 16:36:04 +0000
commitdb86e3e4cd6999f640ebeea9e9281bbda4f3d712 (patch)
tree8fe2e555345713c6ad4be5d6d42ec910703b65f4
parent6a3ea2b6c5a17b133ac04e169846c0d600a52e0a (diff)
parent18a0a0920f26dcf8baa5e452b5e8eee88ca34d97 (diff)
Merge "Verify URI permissions in MediaMetadata" into sc-dev am: 2a93c53d21 am: 18a0a0920f
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23207574 Change-Id: Ib99f95e993605db953cb5706596be271e0a27324 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java53
1 files changed, 44 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 53592baee6b7..82dd478aa028 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -22,6 +22,8 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.PendingIntent;
import android.content.ComponentName;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -63,6 +65,9 @@ import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
+import com.android.server.LocalServices;
+import com.android.server.uri.UriGrantsManagerInternal;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -77,6 +82,10 @@ import java.util.concurrent.CopyOnWriteArrayList;
// TODO(jaewan): Do not call service method directly -- introduce listener instead.
public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionRecordImpl {
private static final String TAG = "MediaSessionRecord";
+ private static final String[] ART_URIS = new String[] {
+ MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
+ MediaMetadata.METADATA_KEY_ART_URI,
+ MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI};
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
/**
@@ -130,6 +139,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
private final SessionStub mSession;
private final SessionCb mSessionCb;
private final MediaSessionService mService;
+ private final UriGrantsManagerInternal mUgmInternal;
private final Context mContext;
private final boolean mVolumeAdjustmentForRemoteGroupSessions;
@@ -191,6 +201,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mAudioAttrs = DEFAULT_ATTRIBUTES;
mPolicies = policies;
+ mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions);
@@ -1013,21 +1024,45 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription)
throws RemoteException {
synchronized (mLock) {
- MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata)
- .build();
- // This is to guarantee that the underlying bundle is unparceled
- // before we set it to prevent concurrent reads from throwing an
- // exception
- if (temp != null) {
- temp.size();
- }
- mMetadata = temp;
mDuration = duration;
mMetadataDescription = metadataDescription;
+ mMetadata = sanitizeMediaMetadata(metadata);
}
mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
}
+ private MediaMetadata sanitizeMediaMetadata(MediaMetadata metadata) {
+ if (metadata == null) {
+ return null;
+ }
+ MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder(metadata);
+ for (String key: ART_URIS) {
+ String uriString = metadata.getString(key);
+ if (TextUtils.isEmpty(uriString)) {
+ continue;
+ }
+ Uri uri = Uri.parse(uriString);
+ if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ continue;
+ }
+ try {
+ mUgmInternal.checkGrantUriPermission(getUid(),
+ getPackageName(),
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ ContentProvider.getUserIdFromUri(uri, getUserId()));
+ } catch (SecurityException e) {
+ metadataBuilder.putString(key, null);
+ }
+ }
+ MediaMetadata sanitizedMetadata = metadataBuilder.build();
+ // sanitizedMetadata.size() guarantees that the underlying bundle is unparceled
+ // before we set it to prevent concurrent reads from throwing an
+ // exception
+ sanitizedMetadata.size();
+ return sanitizedMetadata;
+ }
+
@Override
public void setPlaybackState(PlaybackState state) throws RemoteException {
int oldState = mPlaybackState == null