diff options
| author | 2023-05-26 14:45:46 +0000 | |
|---|---|---|
| committer | 2023-05-26 14:45:46 +0000 | |
| commit | 83611643f20f4f1994e01d65e26ddc48d54ebdc7 (patch) | |
| tree | 941d750bd3ca7f738e8da095dbb754a7b4d7898b | |
| parent | 99698b9a359d39a03fdd9e8b603ddacb6af91128 (diff) | |
| parent | 9babf1a67a75d21e3914b14b764e310159b949fa (diff) | |
Merge "Verify URI permissions in MediaMetadata" into tm-dev am: 9babf1a67a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23183176
Change-Id: I976db257c206f8ba12ab93700953fdc6ef6fa3c1
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.java | 53 |
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 1bd50632ccbf..5c28ddd47f23 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -19,6 +19,8 @@ package com.android.server.media; import android.annotation.Nullable; 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.ParceledListSlice; @@ -57,6 +59,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; @@ -72,6 +77,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); /** @@ -125,6 +134,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; @@ -186,6 +196,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); @@ -985,21 +996,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 |