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

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

Block write access to media for non-owners.

The new security model in Q requires that apps can't directly write
to media they don't own.  They can still gain write access using
RecoverableSecurityException.

Bug: 130367350
Test: atest --test-mapping packages/providers/MediaProvider
Change-Id: I1fea108aeee63caa2579187be73ba2f27f2bb932
parent bf70e9cc
Loading
Loading
Loading
Loading
+34 −12
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.os.storage;

import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.OP_READ_MEDIA_AUDIO;
import static android.app.AppOpsManager.OP_READ_MEDIA_IMAGES;
@@ -1721,6 +1722,33 @@ public class StorageManager {
        return checkPermissionAndAppOp(mContext, enforce, pid, uid, packageName, permission, op);
    }

    private boolean noteAppOpAllowingLegacy(boolean enforce,
            int pid, int uid, String packageName, int op) {
        final int mode = mAppOps.noteOpNoThrow(op, uid, packageName);
        switch (mode) {
            case AppOpsManager.MODE_ALLOWED:
                return true;
            case AppOpsManager.MODE_DEFAULT:
            case AppOpsManager.MODE_IGNORED:
            case AppOpsManager.MODE_ERRORED:
                // Legacy apps technically have the access granted by this op,
                // even when the op is denied
                if ((mAppOps.checkOpNoThrow(OP_LEGACY_STORAGE, uid,
                        packageName) == AppOpsManager.MODE_ALLOWED)) return true;

                if (enforce) {
                    throw new SecurityException("Op " + AppOpsManager.opToName(op) + " "
                            + AppOpsManager.modeToName(mode) + " for package " + packageName);
                } else {
                    return false;
                }
            default:
                throw new IllegalStateException(
                        AppOpsManager.opToName(op) + " has unknown mode "
                                + AppOpsManager.modeToName(mode));
        }
    }

    // Callers must hold both the old and new permissions, so that we can
    // handle obscure cases like when an app targets Q but was installed on
    // a device that was originally running on P before being upgraded to Q.
@@ -1730,8 +1758,7 @@ public class StorageManager {
            int pid, int uid, String packageName) {
        if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false;
        mAppOps.noteOpNoThrow(OP_READ_MEDIA_AUDIO, uid, packageName);
        return true;
        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_READ_MEDIA_AUDIO);
    }

    /** {@hide} */
@@ -1739,8 +1766,7 @@ public class StorageManager {
            int pid, int uid, String packageName) {
        if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false;
        mAppOps.noteOpNoThrow(OP_WRITE_MEDIA_AUDIO, uid, packageName);
        return true;
        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_WRITE_MEDIA_AUDIO);
    }

    /** {@hide} */
@@ -1748,8 +1774,7 @@ public class StorageManager {
            int pid, int uid, String packageName) {
        if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false;
        mAppOps.noteOpNoThrow(OP_READ_MEDIA_VIDEO, uid, packageName);
        return true;
        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_READ_MEDIA_VIDEO);
    }

    /** {@hide} */
@@ -1757,8 +1782,7 @@ public class StorageManager {
            int pid, int uid, String packageName) {
        if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false;
        mAppOps.noteOpNoThrow(OP_WRITE_MEDIA_VIDEO, uid, packageName);
        return true;
        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_WRITE_MEDIA_VIDEO);
    }

    /** {@hide} */
@@ -1766,8 +1790,7 @@ public class StorageManager {
            int pid, int uid, String packageName) {
        if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE)) return false;
        mAppOps.noteOpNoThrow(OP_READ_MEDIA_IMAGES, uid, packageName);
        return true;
        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_READ_MEDIA_IMAGES);
    }

    /** {@hide} */
@@ -1775,8 +1798,7 @@ public class StorageManager {
            int pid, int uid, String packageName) {
        if (!checkPermissionAndAppOp(enforce, pid, uid, packageName,
                WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE)) return false;
        mAppOps.noteOpNoThrow(OP_WRITE_MEDIA_IMAGES, uid, packageName);
        return true;
        return noteAppOpAllowingLegacy(enforce, pid, uid, packageName, OP_WRITE_MEDIA_IMAGES);
    }

    /** {@hide} */