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

Commit fb833f38 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Detect content:// leaving apps without grants.

Developers regularly put content:// Uris into Intents, but they can
easily forget to add FLAG_GRANT_READ_URI_PERMISSION to actually
extend a permission grant to the receiving app.

Also fix NPE when path is missing.

Test: builds, boots, common actions work without triggering
Bug: 32447617, 31900890
Change-Id: Ic6054b1d73de50967cf7fe66abc293c60a41b97e
parent aac3cba5
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -853,15 +853,30 @@ public class ClipData implements Parcelable {
     * @hide
     */
    public void prepareToLeaveProcess(boolean leavingPackage) {
        prepareToLeaveProcess(leavingPackage, 0);
    }

    /**
     * Prepare this {@link ClipData} to leave an app process.
     *
     * @hide
     */
    public void prepareToLeaveProcess(boolean leavingPackage, int intentFlags) {
        final int size = mItems.size();
        for (int i = 0; i < size; i++) {
            final Item item = mItems.get(i);
            if (item.mIntent != null) {
                item.mIntent.prepareToLeaveProcess(leavingPackage);
            }
            if (item.mUri != null && StrictMode.vmFileUriExposureEnabled() && leavingPackage) {
            if (item.mUri != null && leavingPackage) {
                if (StrictMode.vmFileUriExposureEnabled()) {
                    item.mUri.checkFileUriExposed("ClipData.Item.getUri()");
                }
                if (StrictMode.vmContentUriWithoutPermissionEnabled()) {
                    item.mUri.checkContentUriWithoutPermission("ClipData.Item.getUri()",
                            intentFlags);
                }
            }
        }
    }

+12 −1
Original line number Diff line number Diff line
@@ -9009,7 +9009,7 @@ public class Intent implements Parcelable, Cloneable {
            mSelector.prepareToLeaveProcess(leavingPackage);
        }
        if (mClipData != null) {
            mClipData.prepareToLeaveProcess(leavingPackage);
            mClipData.prepareToLeaveProcess(leavingPackage, getFlags());
        }

        if (mAction != null && mData != null && StrictMode.vmFileUriExposureEnabled()
@@ -9036,6 +9036,17 @@ public class Intent implements Parcelable, Cloneable {
                    mData.checkFileUriExposed("Intent.getData()");
            }
        }

        if (mAction != null && mData != null && StrictMode.vmContentUriWithoutPermissionEnabled()
                && leavingPackage) {
            switch (mAction) {
                case ACTION_PROVIDER_CHANGED:
                    // Ignore actions that don't need to grant
                    break;
                default:
                    mData.checkContentUriWithoutPermission("Intent.getData()", getFlags());
            }
        }
    }

    /**
+15 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.net;

import android.content.Intent;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
@@ -2342,11 +2343,24 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
     * @hide
     */
    public void checkFileUriExposed(String location) {
        if ("file".equals(getScheme()) && !getPath().startsWith("/system/")) {
        if ("file".equals(getScheme())
                && (getPath() != null) && !getPath().startsWith("/system/")) {
            StrictMode.onFileUriExposed(this, location);
        }
    }

    /**
     * If this is a {@code content://} Uri without access flags, it will be
     * reported to {@link StrictMode}.
     *
     * @hide
     */
    public void checkContentUriWithoutPermission(String location, int flags) {
        if ("content".equals(getScheme()) && !Intent.isAccessUriMode(flags)) {
            StrictMode.onContentUriWithoutPermission(this, location);
        }
    }

    /**
     * Test if this is a path prefix match against the given Uri. Verifies that
     * scheme, authority, and atomic path segments match.
+17 −0
Original line number Diff line number Diff line
@@ -1797,6 +1797,13 @@ public final class StrictMode {
        return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
    }

    /**
     * @hide
     */
    public static boolean vmContentUriWithoutPermissionEnabled() {
        return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
    }

    /**
     * @hide
     */
@@ -1844,6 +1851,16 @@ public final class StrictMode {
        }
    }

    /**
     * @hide
     */
    public static void onContentUriWithoutPermission(Uri uri, String location) {
        final String message = uri + " exposed beyond app through " + location
                + " without permission grant flags; did you forget"
                + " FLAG_GRANT_READ_URI_PERMISSION?";
        onVmPolicyViolation(null, new Throwable(message));
    }

    /**
     * @hide
     */