Loading core/java/android/os/storage/StorageManager.java +11 −7 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ import java.util.concurrent.atomic.AtomicInteger; @SystemService(Context.STORAGE_SERVICE) public class StorageManager { private static final String TAG = "StorageManager"; private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); /** {@hide} */ public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical"; Loading Loading @@ -1652,13 +1653,11 @@ public class StorageManager { /** * Check that given app holds both permission and appop. * * @return {@code null} if the permission and appop are held, otherwise * returns a string indicating why access was denied. * @hide */ private boolean checkPermissionAndAppOp(boolean enforce, int pid, int uid, String packageName, String permission, int op) { if (mContext.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { public static boolean checkPermissionAndAppOp(Context context, boolean enforce, int pid, int uid, String packageName, String permission, int op) { if (context.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { if (enforce) { throw new SecurityException( "Permission " + permission + " denied for package " + packageName); Loading @@ -1667,7 +1666,7 @@ public class StorageManager { } } final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); final AppOpsManager appOps = context.getSystemService(AppOpsManager.class); final int mode = appOps.noteOpNoThrow(op, uid, packageName); switch (mode) { case AppOpsManager.MODE_ALLOWED: Loading @@ -1688,6 +1687,11 @@ public class StorageManager { } } private boolean checkPermissionAndAppOp(boolean enforce, int pid, int uid, String packageName, String permission, int op) { return checkPermissionAndAppOp(mContext, enforce, pid, uid, packageName, permission, op); } // 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. Loading services/core/java/com/android/server/StorageManagerService.java +75 −31 Original line number Diff line number Diff line Loading @@ -17,10 +17,14 @@ package com.android.server; import static android.Manifest.permission.INSTALL_PACKAGES; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_MEDIA_STORAGE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_LEGACY_STORAGE; import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES; import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN; import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; import static android.content.pm.PackageManager.GET_PERMISSIONS; Loading Loading @@ -280,6 +284,7 @@ class StorageManagerService extends IStorageManager.Stub private static final boolean EMULATE_FBE_SUPPORTED = true; private static final String TAG = "StorageManagerService"; private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark"; private static final String TAG_STORAGE_TRIM = "storage_trim"; Loading Loading @@ -3863,23 +3868,67 @@ class StorageManagerService extends IStorageManager.Stub } private int getMountMode(int uid, String packageName) { final int mode = getMountModeInternal(uid, packageName); if (LOCAL_LOGV) { Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/" + UserHandle.formatUid(uid)); } return mode; } private int getMountModeInternal(int uid, String packageName) { try { // Get some easy cases out of the way first if (Process.isIsolated(uid)) { return Zygote.MOUNT_EXTERNAL_NONE; } if (mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) { if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { return Zygote.MOUNT_EXTERNAL_NONE; } // Determine if caller is holding runtime permission final boolean hasRead = StorageManager.checkPermissionAndAppOp(mContext, false, 0, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE); final boolean hasWrite = StorageManager.checkPermissionAndAppOp(mContext, false, 0, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE); final boolean hasStorage = hasRead || hasWrite; // We're only willing to give out broad access if they also hold // runtime permission; this is a firm CDD requirement final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED; if (hasFull && hasStorage) { return Zygote.MOUNT_EXTERNAL_FULL; } else if (mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid, packageName) == MODE_ALLOWED) { return Zygote.MOUNT_EXTERNAL_LEGACY; } else if (mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid) == PERMISSION_GRANTED || mIAppOpsService.checkOperation( OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) { } // We're only willing to give out installer access if they also hold // runtime permission; this is a firm CDD requirement final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid) == PERMISSION_GRANTED; final boolean hasInstallOp = mIAppOpsService.checkOperation(OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED; if ((hasInstall || hasInstallOp) && hasStorage) { return Zygote.MOUNT_EXTERNAL_INSTALLER; } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { return Zygote.MOUNT_EXTERNAL_NONE; } // Otherwise we're willing to give out sandboxed or non-sandboxed if // they hold the runtime permission final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid, packageName) == MODE_ALLOWED; final boolean hasGreylist = isLegacyGreylisted(packageName); if ((hasLegacy || hasGreylist) && hasStorage) { return Zygote.MOUNT_EXTERNAL_LEGACY; } else { return Zygote.MOUNT_EXTERNAL_WRITE; } } catch (RemoteException e) { // Should not happen } return Zygote.MOUNT_EXTERNAL_NONE; } private boolean isLegacyGreylisted(String packageName) { // TODO: decide legacy defaults at install time based on signals if (ENABLE_LEGACY_GREYLIST) { // STOPSHIP: remove this temporary workaround once developers // fix bugs where they're opening _data paths in native code Loading @@ -3898,15 +3947,10 @@ class StorageManagerService extends IStorageManager.Stub case "ak.alizandro.smartaudiobookplayer": // b/129084042 case "com.campmobile.snow": // b/128803870 case "com.qnap.qfile": // b/126374406 return Zygote.MOUNT_EXTERNAL_LEGACY; } return true; } return Zygote.MOUNT_EXTERNAL_WRITE; } } catch (RemoteException e) { // Should not happen } return Zygote.MOUNT_EXTERNAL_NONE; return false; } private static class Callbacks extends Handler { Loading Loading
core/java/android/os/storage/StorageManager.java +11 −7 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ import java.util.concurrent.atomic.AtomicInteger; @SystemService(Context.STORAGE_SERVICE) public class StorageManager { private static final String TAG = "StorageManager"; private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); /** {@hide} */ public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical"; Loading Loading @@ -1652,13 +1653,11 @@ public class StorageManager { /** * Check that given app holds both permission and appop. * * @return {@code null} if the permission and appop are held, otherwise * returns a string indicating why access was denied. * @hide */ private boolean checkPermissionAndAppOp(boolean enforce, int pid, int uid, String packageName, String permission, int op) { if (mContext.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { public static boolean checkPermissionAndAppOp(Context context, boolean enforce, int pid, int uid, String packageName, String permission, int op) { if (context.checkPermission(permission, pid, uid) != PERMISSION_GRANTED) { if (enforce) { throw new SecurityException( "Permission " + permission + " denied for package " + packageName); Loading @@ -1667,7 +1666,7 @@ public class StorageManager { } } final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); final AppOpsManager appOps = context.getSystemService(AppOpsManager.class); final int mode = appOps.noteOpNoThrow(op, uid, packageName); switch (mode) { case AppOpsManager.MODE_ALLOWED: Loading @@ -1688,6 +1687,11 @@ public class StorageManager { } } private boolean checkPermissionAndAppOp(boolean enforce, int pid, int uid, String packageName, String permission, int op) { return checkPermissionAndAppOp(mContext, enforce, pid, uid, packageName, permission, op); } // 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. Loading
services/core/java/com/android/server/StorageManagerService.java +75 −31 Original line number Diff line number Diff line Loading @@ -17,10 +17,14 @@ package com.android.server; import static android.Manifest.permission.INSTALL_PACKAGES; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_MEDIA_STORAGE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_LEGACY_STORAGE; import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES; import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN; import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; import static android.content.pm.PackageManager.GET_PERMISSIONS; Loading Loading @@ -280,6 +284,7 @@ class StorageManagerService extends IStorageManager.Stub private static final boolean EMULATE_FBE_SUPPORTED = true; private static final String TAG = "StorageManagerService"; private static final boolean LOCAL_LOGV = Log.isLoggable(TAG, Log.VERBOSE); private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark"; private static final String TAG_STORAGE_TRIM = "storage_trim"; Loading Loading @@ -3863,23 +3868,67 @@ class StorageManagerService extends IStorageManager.Stub } private int getMountMode(int uid, String packageName) { final int mode = getMountModeInternal(uid, packageName); if (LOCAL_LOGV) { Slog.v(TAG, "Resolved mode " + mode + " for " + packageName + "/" + UserHandle.formatUid(uid)); } return mode; } private int getMountModeInternal(int uid, String packageName) { try { // Get some easy cases out of the way first if (Process.isIsolated(uid)) { return Zygote.MOUNT_EXTERNAL_NONE; } if (mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) { if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { return Zygote.MOUNT_EXTERNAL_NONE; } // Determine if caller is holding runtime permission final boolean hasRead = StorageManager.checkPermissionAndAppOp(mContext, false, 0, uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE); final boolean hasWrite = StorageManager.checkPermissionAndAppOp(mContext, false, 0, uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE); final boolean hasStorage = hasRead || hasWrite; // We're only willing to give out broad access if they also hold // runtime permission; this is a firm CDD requirement final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED; if (hasFull && hasStorage) { return Zygote.MOUNT_EXTERNAL_FULL; } else if (mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid, packageName) == MODE_ALLOWED) { return Zygote.MOUNT_EXTERNAL_LEGACY; } else if (mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid) == PERMISSION_GRANTED || mIAppOpsService.checkOperation( OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) { } // We're only willing to give out installer access if they also hold // runtime permission; this is a firm CDD requirement final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES, uid) == PERMISSION_GRANTED; final boolean hasInstallOp = mIAppOpsService.checkOperation(OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED; if ((hasInstall || hasInstallOp) && hasStorage) { return Zygote.MOUNT_EXTERNAL_INSTALLER; } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { return Zygote.MOUNT_EXTERNAL_NONE; } // Otherwise we're willing to give out sandboxed or non-sandboxed if // they hold the runtime permission final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE, uid, packageName) == MODE_ALLOWED; final boolean hasGreylist = isLegacyGreylisted(packageName); if ((hasLegacy || hasGreylist) && hasStorage) { return Zygote.MOUNT_EXTERNAL_LEGACY; } else { return Zygote.MOUNT_EXTERNAL_WRITE; } } catch (RemoteException e) { // Should not happen } return Zygote.MOUNT_EXTERNAL_NONE; } private boolean isLegacyGreylisted(String packageName) { // TODO: decide legacy defaults at install time based on signals if (ENABLE_LEGACY_GREYLIST) { // STOPSHIP: remove this temporary workaround once developers // fix bugs where they're opening _data paths in native code Loading @@ -3898,15 +3947,10 @@ class StorageManagerService extends IStorageManager.Stub case "ak.alizandro.smartaudiobookplayer": // b/129084042 case "com.campmobile.snow": // b/128803870 case "com.qnap.qfile": // b/126374406 return Zygote.MOUNT_EXTERNAL_LEGACY; } return true; } return Zygote.MOUNT_EXTERNAL_WRITE; } } catch (RemoteException e) { // Should not happen } return Zygote.MOUNT_EXTERNAL_NONE; return false; } private static class Callbacks extends Handler { Loading