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

Commit e44f60ec authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Require valid authorities for Uri notifications."

parents 80999f79 912e80d3
Loading
Loading
Loading
Loading
+65 −36
Original line number Original line Diff line number Diff line
@@ -500,6 +500,7 @@ public abstract class ContentResolver {
    public ContentResolver(Context context) {
    public ContentResolver(Context context) {
        mContext = context != null ? context : ActivityThread.currentApplication();
        mContext = context != null ? context : ActivityThread.currentApplication();
        mPackageName = mContext.getOpPackageName();
        mPackageName = mContext.getOpPackageName();
        mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
    }
    }


    /** @hide */
    /** @hide */
@@ -1868,13 +1869,18 @@ public abstract class ContentResolver {
    /**
    /**
     * Register an observer class that gets callbacks when data identified by a
     * Register an observer class that gets callbacks when data identified by a
     * given content URI changes.
     * given content URI changes.
     *
     * <p>
     * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
     * for a whole class of content.
     * notifications must be backed by a valid {@link ContentProvider}.
     * @param notifyForDescendants When false, the observer will be notified whenever a
     *
     * change occurs to the exact URI specified by <code>uri</code> or to one of the
     * @param uri The URI to watch for changes. This can be a specific row URI,
     * URI's ancestors in the path hierarchy.  When true, the observer will also be notified
     *            or a base URI for a whole class of content.
     * whenever a change occurs to the URI's descendants in the path hierarchy.
     * @param notifyForDescendants When false, the observer will be notified
     *            whenever a change occurs to the exact URI specified by
     *            <code>uri</code> or to one of the URI's ancestors in the path
     *            hierarchy. When true, the observer will also be notified
     *            whenever a change occurs to the URI's descendants in the path
     *            hierarchy.
     * @param observer The object that receives callbacks when changes occur.
     * @param observer The object that receives callbacks when changes occur.
     * @see #unregisterContentObserver
     * @see #unregisterContentObserver
     */
     */
@@ -1894,7 +1900,7 @@ public abstract class ContentResolver {
            ContentObserver observer, @UserIdInt int userHandle) {
            ContentObserver observer, @UserIdInt int userHandle) {
        try {
        try {
            getContentService().registerContentObserver(uri, notifyForDescendents,
            getContentService().registerContentObserver(uri, notifyForDescendents,
                    observer.getContentObserver(), userHandle);
                    observer.getContentObserver(), userHandle, mTargetSdkVersion);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
        }
        }
    }
    }
@@ -1918,16 +1924,22 @@ public abstract class ContentResolver {
    }
    }


    /**
    /**
     * Notify registered observers that a row was updated and attempt to sync changes
     * Notify registered observers that a row was updated and attempt to sync
     * to the network.
     * changes to the network.
     * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
     * <p>
     * By default, CursorAdapter objects will get this notification.
     * To observe events sent through this call, use
     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
     * <p>
     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
     * notifications must be backed by a valid {@link ContentProvider}.
     *
     *
     * @param uri The uri of the content that was changed.
     * @param uri The uri of the content that was changed.
     * @param observer The observer that originated the change, may be <code>null</null>.
     * @param observer The observer that originated the change, may be
     * The observer that originated the change will only receive the notification if it
     *            <code>null</null>. The observer that originated the change
     * has requested to receive self-change notifications by implementing
     *            will only receive the notification if it has requested to
     * {@link ContentObserver#deliverSelfNotifications()} to return true.
     *            receive self-change notifications by implementing
     *            {@link ContentObserver#deliverSelfNotifications()} to return
     *            true.
     */
     */
    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
        notifyChange(uri, observer, true /* sync to network */);
        notifyChange(uri, observer, true /* sync to network */);
@@ -1935,17 +1947,25 @@ public abstract class ContentResolver {


    /**
    /**
     * Notify registered observers that a row was updated.
     * Notify registered observers that a row was updated.
     * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
     * <p>
     * By default, CursorAdapter objects will get this notification.
     * To observe events sent through this call, use
     * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
     * adapter that's registered for the authority of the provided uri. No account will be
     * <p>
     * passed to the sync adapter, so all matching accounts will be synchronized.
     * If syncToNetwork is true, this will attempt to schedule a local sync
     * using the sync adapter that's registered for the authority of the
     * provided uri. No account will be passed to the sync adapter, so all
     * matching accounts will be synchronized.
     * <p>
     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
     * notifications must be backed by a valid {@link ContentProvider}.
     *
     *
     * @param uri The uri of the content that was changed.
     * @param uri The uri of the content that was changed.
     * @param observer The observer that originated the change, may be <code>null</null>.
     * @param observer The observer that originated the change, may be
     * The observer that originated the change will only receive the notification if it
     *            <code>null</null>. The observer that originated the change
     * has requested to receive self-change notifications by implementing
     *            will only receive the notification if it has requested to
     * {@link ContentObserver#deliverSelfNotifications()} to return true.
     *            receive self-change notifications by implementing
     *            {@link ContentObserver#deliverSelfNotifications()} to return
     *            true.
     * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
     * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
     * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
     * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
     */
     */
@@ -1961,17 +1981,25 @@ public abstract class ContentResolver {


    /**
    /**
     * Notify registered observers that a row was updated.
     * Notify registered observers that a row was updated.
     * To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}.
     * <p>
     * By default, CursorAdapter objects will get this notification.
     * To observe events sent through this call, use
     * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
     * adapter that's registered for the authority of the provided uri. No account will be
     * <p>
     * passed to the sync adapter, so all matching accounts will be synchronized.
     * If syncToNetwork is true, this will attempt to schedule a local sync
     * using the sync adapter that's registered for the authority of the
     * provided uri. No account will be passed to the sync adapter, so all
     * matching accounts will be synchronized.
     * <p>
     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
     * notifications must be backed by a valid {@link ContentProvider}.
     *
     *
     * @param uri The uri of the content that was changed.
     * @param uri The uri of the content that was changed.
     * @param observer The observer that originated the change, may be <code>null</null>.
     * @param observer The observer that originated the change, may be
     * The observer that originated the change will only receive the notification if it
     *            <code>null</null>. The observer that originated the change
     * has requested to receive self-change notifications by implementing
     *            will only receive the notification if it has requested to
     * {@link ContentObserver#deliverSelfNotifications()} to return true.
     *            receive self-change notifications by implementing
     *            {@link ContentObserver#deliverSelfNotifications()} to return
     *            true.
     * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
     * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
     * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
     * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
     */
     */
@@ -1997,7 +2025,7 @@ public abstract class ContentResolver {
                    uri, observer == null ? null : observer.getContentObserver(),
                    uri, observer == null ? null : observer.getContentObserver(),
                    observer != null && observer.deliverSelfNotifications(),
                    observer != null && observer.deliverSelfNotifications(),
                    syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
                    syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
                    userHandle);
                    userHandle, mTargetSdkVersion);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
        }
        }
    }
    }
@@ -2013,7 +2041,7 @@ public abstract class ContentResolver {
            getContentService().notifyChange(
            getContentService().notifyChange(
                    uri, observer == null ? null : observer.getContentObserver(),
                    uri, observer == null ? null : observer.getContentObserver(),
                    observer != null && observer.deliverSelfNotifications(), flags,
                    observer != null && observer.deliverSelfNotifications(), flags,
                    userHandle);
                    userHandle, mTargetSdkVersion);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
        }
        }
    }
    }
@@ -2932,6 +2960,7 @@ public abstract class ContentResolver {
    private final Context mContext;
    private final Context mContext;


    final String mPackageName;
    final String mPackageName;
    final int mTargetSdkVersion;


    private static final String TAG = "ContentResolver";
    private static final String TAG = "ContentResolver";


+2 −2
Original line number Original line Diff line number Diff line
@@ -42,7 +42,7 @@ interface IContentService {
     *     USER_CURRENT are properly handled.
     *     USER_CURRENT are properly handled.
     */
     */
    void registerContentObserver(in Uri uri, boolean notifyForDescendants,
    void registerContentObserver(in Uri uri, boolean notifyForDescendants,
            IContentObserver observer, int userHandle);
            IContentObserver observer, int userHandle, int targetSdkVersion);


    /**
    /**
     * Notify observers of a particular user's view of the provider.
     * Notify observers of a particular user's view of the provider.
@@ -53,7 +53,7 @@ interface IContentService {
     */
     */
    void notifyChange(in Uri uri, IContentObserver observer,
    void notifyChange(in Uri uri, IContentObserver observer,
            boolean observerWantsSelfNotifications, int flags,
            boolean observerWantsSelfNotifications, int flags,
            int userHandle);
            int userHandle, int targetSdkVersion);


    void requestSync(in Account account, String authority, in Bundle extras);
    void requestSync(in Account account, String authority, in Bundle extras);
    /**
    /**
+1 −4
Original line number Original line Diff line number Diff line
@@ -10708,10 +10708,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        } catch (RemoteException ignored) {
        } catch (RemoteException ignored) {
        }
        }
        if (cpi == null) {
        if (cpi == null) {
            // TODO: make this an outright failure in a future platform release;
            return "Failed to find provider " + authority + " for user " + userId;
            // until then anonymous content notifications are unprotected
            //return "Failed to find provider " + authority + " for user " + userId;
            return null;
        }
        }
        ProcessRecord r = null;
        ProcessRecord r = null;
+28 −9
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ import android.database.IContentObserver;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.net.Uri;
import android.os.Binder;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.os.FactoryTest;
import android.os.FactoryTest;
import android.os.IBinder;
import android.os.IBinder;
@@ -287,7 +288,7 @@ public final class ContentService extends IContentService.Stub {
     */
     */
    @Override
    @Override
    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
                                        IContentObserver observer, int userHandle) {
            IContentObserver observer, int userHandle, int targetSdkVersion) {
        if (observer == null || uri == null) {
        if (observer == null || uri == null) {
            throw new IllegalArgumentException("You must pass a valid uri and observer");
            throw new IllegalArgumentException("You must pass a valid uri and observer");
        }
        }
@@ -301,9 +302,18 @@ public final class ContentService extends IContentService.Stub {
        final String msg = LocalServices.getService(ActivityManagerInternal.class)
        final String msg = LocalServices.getService(ActivityManagerInternal.class)
                .checkContentProviderAccess(uri.getAuthority(), userHandle);
                .checkContentProviderAccess(uri.getAuthority(), userHandle);
        if (msg != null) {
        if (msg != null) {
            if (targetSdkVersion >= Build.VERSION_CODES.O) {
                throw new SecurityException(msg);
            } else {
                if (msg.startsWith("Failed to find provider")) {
                    // Sigh, we need to quietly let apps targeting older API
                    // levels notify on non-existent providers.
                } else {
                    Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
                    Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
                    return;
                    return;
                }
                }
            }
        }


        synchronized (mRootNode) {
        synchronized (mRootNode) {
            mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
            mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
@@ -316,7 +326,7 @@ public final class ContentService extends IContentService.Stub {
    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
                                        IContentObserver observer) {
                                        IContentObserver observer) {
        registerContentObserver(uri, notifyForDescendants, observer,
        registerContentObserver(uri, notifyForDescendants, observer,
                UserHandle.getCallingUserId());
                UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
    }
    }


    @Override
    @Override
@@ -340,8 +350,8 @@ public final class ContentService extends IContentService.Stub {
     */
     */
    @Override
    @Override
    public void notifyChange(Uri uri, IContentObserver observer,
    public void notifyChange(Uri uri, IContentObserver observer,
                             boolean observerWantsSelfNotifications, int flags,
            boolean observerWantsSelfNotifications, int flags, int userHandle,
                             int userHandle) {
            int targetSdkVersion) {
        if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
        if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
                + " from observer " + observer + ", flags " + Integer.toHexString(flags));
                + " from observer " + observer + ", flags " + Integer.toHexString(flags));


@@ -359,9 +369,18 @@ public final class ContentService extends IContentService.Stub {
        final String msg = LocalServices.getService(ActivityManagerInternal.class)
        final String msg = LocalServices.getService(ActivityManagerInternal.class)
                .checkContentProviderAccess(uri.getAuthority(), userHandle);
                .checkContentProviderAccess(uri.getAuthority(), userHandle);
        if (msg != null) {
        if (msg != null) {
            if (targetSdkVersion >= Build.VERSION_CODES.O) {
                throw new SecurityException(msg);
            } else {
                if (msg.startsWith("Failed to find provider")) {
                    // Sigh, we need to quietly let apps targeting older API
                    // levels notify on non-existent providers.
                } else {
                    Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
                    Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
                    return;
                    return;
                }
                }
            }
        }


        // This makes it so that future permission checks will be in the context of this
        // This makes it so that future permission checks will be in the context of this
        // process rather than the caller's process. We will restore this before returning.
        // process rather than the caller's process. We will restore this before returning.
@@ -427,7 +446,7 @@ public final class ContentService extends IContentService.Stub {
                             boolean observerWantsSelfNotifications, boolean syncToNetwork) {
                             boolean observerWantsSelfNotifications, boolean syncToNetwork) {
        notifyChange(uri, observer, observerWantsSelfNotifications,
        notifyChange(uri, observer, observerWantsSelfNotifications,
                syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
                syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
                UserHandle.getCallingUserId());
                UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
    }
    }


    /**
    /**