DivestOS/Patches/LineageOS-17.1/android_frameworks_base/378099.patch

130 lines
5.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Mikhail <michaelmikhil@google.com>
Date: Fri, 28 Apr 2023 16:17:16 +0000
Subject: [PATCH] Verify URI permissions in MediaMetadata
Add a check for URI permission to make sure that user can access the URI
set in MediaMetadata. If permission is denied, clear the URI string set
in metadata.
Bug: 271851153
Test: atest MediaSessionTest
Test: Verified by POC app attached in bug, image of second user is not
the UMO background of the first user.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f95b7fc61d6b3bf49420ded0357bec031f8cbdcf)
Merged-In: I384f8e230c909d8fc8e5f147e2fd3558fec44626
Change-Id: I384f8e230c909d8fc8e5f147e2fd3558fec44626
---
.../server/media/MediaSessionRecord.java | 52 +++++++++++++++----
1 file changed, 43 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 e2087e6ca822..5ebbfe92dc20 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -17,6 +17,8 @@
package com.android.server.media;
import android.app.PendingIntent;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
@@ -48,11 +50,13 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.view.KeyEvent;
import com.android.server.LocalServices;
+import com.android.server.uri.UriGrantsManagerInternal;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -64,6 +68,10 @@ import java.util.List;
*/
public class MediaSessionRecord implements IBinder.DeathRecipient {
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);
/**
@@ -85,6 +93,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private final SessionStub mSession;
private final SessionCb mSessionCb;
private final MediaSessionService mService;
+ private final UriGrantsManagerInternal mUgmInternal;
private final Context mContext;
private final Object mLock = new Object();
@@ -142,6 +151,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+ mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
}
/**
@@ -870,21 +880,45 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
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