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

Commit 593f9b89 authored by Hai Zhang's avatar Hai Zhang
Browse files

Allowlist permissions in a better way.

All apps should be UPGRADE_EXEMPT by default, which will be replaced
by INSTALLER_EXEMPT when onPackageInstalled() is called and the
installer supplies the list of permissions to be allowlisted (most of
the times just the default of all requested permissions).

This way we can properly handle the system app case and the rollback
case, in which cases there won't be any installer to allowlist
permissions.

Bug: 263504888
Test: RestrictedPermissionsTest
Change-Id: I58d6d7aeb8db8de05c2e6ac60b51358709f06091
parent c3335445
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -856,15 +856,29 @@ class AppIdPermissionPolicy : SchemePolicy() {
                }
            }

            val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
            val isHardRestricted = permission.isHardRestricted && !isExempt
            newFlags = if (isHardRestricted) {
            val wasExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
            val wasRestricted = newFlags.hasAnyBit(PermissionFlags.MASK_RESTRICTED)
            val isExempt = if (permission.isHardOrSoftRestricted && !wasExempt && !wasRestricted) {
                // All restricted permissions start as exempt. If there's an installer for the
                // package, we will drop this UPGRADE_EXEMPT flag when we receive the
                // onPackageInstalled() callback and set up the INSTALLER_EXEMPT flags.
                // UPGRADE_EXEMPT is chosen instead of other flags because it is the same flag that
                // was assigned to pre-installed apps in RuntimePermissionsUpgradeController, and to
                // apps with missing permission state.
                // This way we make sure both pre-installed apps, and apps updated/installed after
                // a rollback snapshot is taken, can get the allowlist for permissions that won't be
                // allowlisted otherwise.
                newFlags = newFlags or PermissionFlags.UPGRADE_EXEMPT
                true
            } else {
                wasExempt
            }
            newFlags = if (permission.isHardRestricted && !isExempt) {
                newFlags or PermissionFlags.RESTRICTION_REVOKED
            } else {
                newFlags andInv PermissionFlags.RESTRICTION_REVOKED
            }
            val isSoftRestricted = permission.isSoftRestricted && !isExempt
            newFlags = if (isSoftRestricted) {
            newFlags = if (permission.isSoftRestricted && !isExempt) {
                newFlags or PermissionFlags.SOFT_RESTRICTED
            } else {
                newFlags andInv PermissionFlags.SOFT_RESTRICTED
+5 −0
Original line number Diff line number Diff line
@@ -318,6 +318,11 @@ object PermissionFlags {
     */
    const val MASK_EXEMPT = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT

    /**
     * Mask for all permission flags about permission restriction.
     */
    const val MASK_RESTRICTED = RESTRICTION_REVOKED or SOFT_RESTRICTED

    fun isPermissionGranted(flags: Int): Boolean {
        if (flags.hasBits(INSTALL_GRANTED)) {
            return true
+19 −4
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ import com.android.server.policy.SoftRestrictedPermissionPolicy
import libcore.util.EmptyArray
import java.io.FileDescriptor
import java.io.PrintWriter
import java.util.Collections
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeUnit
@@ -1583,14 +1584,12 @@ class PermissionService(
                        }
                    }

                    val isHardRestricted = permission.isHardRestricted && !isExempt
                    newFlags = if (isHardRestricted) {
                    newFlags = if (permission.isHardRestricted && !isExempt) {
                        newFlags or PermissionFlags.RESTRICTION_REVOKED
                    } else {
                        newFlags andInv PermissionFlags.RESTRICTION_REVOKED
                    }
                    val isSoftRestricted = permission.isSoftRestricted && !isExempt
                    newFlags = if (isSoftRestricted) {
                    newFlags = if (permission.isSoftRestricted && !isExempt) {
                        newFlags or PermissionFlags.SOFT_RESTRICTED
                    } else {
                        newFlags andInv PermissionFlags.SOFT_RESTRICTED
@@ -1875,6 +1874,18 @@ class PermissionService(
        params: PermissionManagerServiceInternal.PackageInstalledParams,
        userId: Int
    ) {
        if (params === PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT) {
            // TODO: We should actually stop calling onPackageInstalled() when we are passing
            //  PackageInstalledParams.DEFAULT in InstallPackageHelper, because there's actually no
            //  installer in those  cases of system app installs, and the default params won't
            //  allowlist any permissions which means the original UPGRADE_EXEMPT will be dropped
            //  without any INSTALLER_EXEMPT added. However, we can't do that right now because the
            //  old permission subsystem still depends on this method being called to set up the
            //  permission state for the first time (which we are doing in onPackageAdded() or
            //  onStorageVolumeMounted() now).
            return
        }

        synchronized(mountedStorageVolumes) {
            if (androidPackage.volumeUuid !in mountedStorageVolumes) {
                // Wait for the storage volume to be mounted and batch the state mutation there.
@@ -1900,6 +1911,10 @@ class PermissionService(
                packageManagerInternal.getPackageStateInternal(androidPackage.packageName)!!
            addAllowlistedRestrictedPermissionsUnchecked(androidPackage, packageState.appId,
                params.allowlistedRestrictedPermissions, userId)
            // Drop UPGRADE_EXEMPT for all permissions requested by this package since there's an
            // installer and the installer has made a decision.
            setAllowlistedRestrictedPermissionsUnchecked(androidPackage, packageState.appId,
                Collections.emptyList(), PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE, userId)
            setRequestedPermissionStates(packageState, userId, params.permissionStates)
        }
    }