Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb9f7726 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

RingtonePlayer: URI userId must match that of caller

Prevent one user from playing media from another user
by checking that the userId of the content matches
the userId of the caller.

Bug: 300654867
Test: see POC, needs to also be tested from 2ndary user
Flag: EXEMPT for security

Change-Id: I5914270c3421650eeb97f1b329a4aeb613f57b90
parent cefb0e81
Loading
Loading
Loading
Loading
+27 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.media;

import android.annotation.Nullable;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -123,9 +124,13 @@ public class RingtonePlayer implements CoreStartable {
                boolean looping, @Nullable VolumeShaper.Configuration volumeShaperConfig)
                throws RemoteException {
            if (LOGD) {
                Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
                        + Binder.getCallingUid() + ")");
                Log.d(TAG, "play(token=" + token + ", uri=" + uri
                        + ", uid=" + Binder.getCallingUid()
                        + ") uriUserId=" + ContentProvider.getUserIdFromUri(uri)
                        + " callingUserId=" + Binder.getCallingUserHandle().getIdentifier());
            }
            enforceUriUserId(uri);

            Client client;
            synchronized (mClients) {
                client = mClients.get(token);
@@ -207,6 +212,7 @@ public class RingtonePlayer implements CoreStartable {

        @Override
        public String getTitle(Uri uri) {
            enforceUriUserId(uri);
            final UserHandle user = Binder.getCallingUserHandle();
            return Ringtone.getTitle(getContextForUser(user), uri,
                    false /*followSettingsUri*/, false /*allowRemote*/);
@@ -239,6 +245,25 @@ public class RingtonePlayer implements CoreStartable {
            }
            throw new SecurityException("Uri is not ringtone, alarm, or notification: " + uri);
        }

        /**
         * Must be called from the Binder calling thread.
         * Ensures caller is from the same userId as the content they're trying to access.
         * @param uri the URI to check
         * @throws SecurityException when non-system call or userId in uri differs from the
         *                           caller's userId
         */
        private void enforceUriUserId(Uri uri) throws SecurityException {
            final int uriUserId = ContentProvider.getUserIdFromUri(uri);
            final int callerUserId = Binder.getCallingUserHandle().getIdentifier();
            // for a non-system call, verify the URI to play belongs to the same user as the caller
            if (UserHandle.isApp(Binder.getCallingUid()) && uriUserId != callerUserId) {
                throw new SecurityException("Illegal access to uri=" + uri
                        + " content associated with user=" + uriUserId
                        + ", request originates from user=" + callerUserId);
            }
        }

    };

    private Context getContextForUser(UserHandle user) {