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

Commit 051f3b7a authored by Nicolas Prevot's avatar Nicolas Prevot
Browse files

Use correct user id when checking uri grants for notification.

An application is allowed to notify a change to a uri if it
has a grant to this uri. Use the correct user id to check
this grant.

BUG:19312280
Change-Id: I8bad2e65325fdfef4907d7b71b4f264dff567217
parent 430894d1
Loading
Loading
Loading
Loading
+38 −13
Original line number Diff line number Diff line
@@ -20,9 +20,11 @@ import android.Manifest;
import android.accounts.Account;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentService;
@@ -296,12 +298,13 @@ public final class ContentService extends IContentService.Stub {
        final int callingUserHandle = UserHandle.getCallingUserId();
        // Registering an observer for any user other than the calling user requires uri grant or
        // cross user permission
        if (callingUserHandle != userHandle &&
                mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
        if (callingUserHandle != userHandle) {
            if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle)
                    != PackageManager.PERMISSION_GRANTED) {
                enforceCrossUserPermission(userHandle,
                        "no permission to observe other users' provider view");
            }
        }

        if (userHandle < 0) {
            if (userHandle == UserHandle.USER_CURRENT) {
@@ -360,11 +363,12 @@ public final class ContentService extends IContentService.Stub {
        final int pid = Binder.getCallingPid();
        final int callingUserHandle = UserHandle.getCallingUserId();
        // Notify for any user other than the caller requires uri grant or cross user permission
        if (callingUserHandle != userHandle &&
                mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                        != PackageManager.PERMISSION_GRANTED) {
        if (callingUserHandle != userHandle) {
            if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
                    userHandle) != PackageManager.PERMISSION_GRANTED) {
                enforceCrossUserPermission(userHandle, "no permission to notify other users");
            }
        }

        // We passed the permission check; resolve pseudouser targets as appropriate
        if (userHandle < 0) {
@@ -389,9 +393,18 @@ public final class ContentService extends IContentService.Stub {
            for (int i=0; i<numCalls; i++) {
                ObserverCall oc = calls.get(i);
                try {
                    oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
                    // If the uri does not belong to the same user as the observer: we must add
                    // the userId to the uri. Otherewise the observer would think the uri belongs
                    // to his user.
                    final Uri tempUri;
                    if (oc.mObserverUserId != userHandle) {
                        tempUri = ContentProvider.maybeAddUserId(uri, userHandle);
                    } else {
                        tempUri = uri;
                    }
                    oc.mObserver.onChange(oc.mSelfChange, tempUri, userHandle);
                    if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
                            + uri);
                            + tempUri);
                } catch (RemoteException ex) {
                    synchronized (mRootNode) {
                        Log.w(TAG, "Found dead observer, removing");
@@ -427,6 +440,15 @@ public final class ContentService extends IContentService.Stub {
        }
    }

    private int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, int userHandle) {
        try {
            return ActivityManagerNative.getDefault().checkUriPermission(
                    uri, pid, uid, modeFlags, userHandle, null);
        } catch (RemoteException e) {
            return PackageManager.PERMISSION_DENIED;
        }
    }

    public void notifyChange(Uri uri, IContentObserver observer,
                             boolean observerWantsSelfNotifications, boolean syncToNetwork) {
        notifyChange(uri, observer, observerWantsSelfNotifications,
@@ -444,11 +466,13 @@ public final class ContentService extends IContentService.Stub {
        final ObserverNode mNode;
        final IContentObserver mObserver;
        final boolean mSelfChange;
        final int mObserverUserId;

        ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) {
        ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange, int observerUserId) {
            mNode = node;
            mObserver = observer;
            mSelfChange = selfChange;
            mObserverUserId = observerUserId;
        }
    }

@@ -1361,7 +1385,8 @@ public final class ContentService extends IContentService.Stub {
                    if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf
                            + " flags=" + Integer.toHexString(flags)
                            + " desc=" + entry.notifyForDescendants);
                    calls.add(new ObserverCall(this, entry.observer, selfChange));
                    calls.add(new ObserverCall(this, entry.observer, selfChange,
                            UserHandle.getUserId(entry.uid)));
                }
            }
        }