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

Commit 20b04c7f authored by Hai Zhang's avatar Hai Zhang
Browse files

Add permission flag related methods.

Implemented methods for checking/updating permission state and
checking/updating permission flags.

Different from the old implementation, the new code has been
re-written to cleanly check or not check caller's privileges. external
facing methods will enforce necessary permissions, and then will only
call internal methods that no longer enforces permissions.

The new code also tries to gets the package state, and gets or mutates
the permission state, for only once. This ensures we are at least
consistent within package or permission.

The methods have also be restructured to do:
1. Enforce cross-user permissions.
2. Enforce method-related permissions.
3. Skip if user is not found (may happen upon user deletion).
4. Gather package state, get or mutate permission state, or call into
    internal methods that doesn't enforce caller permissions.

Log statements have also been prefixed with method names to make
debugging either - whereas exceptions already have its stacktrace.

PermissionFlags now also takes in the Permission object and correctly
handles restricted permissions, so that the restricted permission
allowlist implementation can now call it directly.

Bug: 252884423
Test: presubmit
Change-Id: Ide19bb2e286123e3c81f641f114461fcd2c04a04
parent 4b8c2445
Loading
Loading
Loading
Loading
+14 −3
Original line number Original line Diff line number Diff line
@@ -148,10 +148,21 @@ inline fun <K, V> IndexedMap<K, V>.retainAllIndexed(predicate: (Int, K, V) -> Bo
    return isChanged
    return isChanged
}
}


inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexed(transform: (K, V) -> R?): IndexedList<R> =
inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexed(
    transform: (Int, K, V) -> R?
): IndexedList<R> =
    IndexedList<R>().also { destination ->
    IndexedList<R>().also { destination ->
        forEachIndexed { _, key, value ->
        forEachIndexed { index, key, value ->
            transform(key, value)?.let { destination += it }
            transform(index, key, value)?.let { destination += it }
        }
    }

inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexedToSet(
    transform: (Int, K, V) -> R?
): IndexedSet<R> =
    IndexedSet<R>().also { destination ->
        forEachIndexed { index, key, value ->
            transform(index, key, value)?.let { destination += it }
        }
        }
    }
    }


+74 −82
Original line number Original line Diff line number Diff line
@@ -317,172 +317,164 @@ object PermissionFlags {
     */
     */
    const val MASK_EXEMPT = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT
    const val MASK_EXEMPT = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT


    /**
    fun isPermissionGranted(flags: Int): Boolean {
     * Mask for all API permission flags about permission restriction.
        if (flags.hasBits(INSTALL_GRANTED)) {
     */
    private const val API_MASK_RESTRICTION =
        PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT or
            PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT or
            PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT or
            PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION

    /**
     * Mask for all permission flags about permission restriction.
     */
    private const val MASK_RESTRICTION = INSTALLER_EXEMPT or SYSTEM_EXEMPT or
        UPGRADE_EXEMPT or RESTRICTION_REVOKED or SOFT_RESTRICTED

    fun isPermissionGranted(policyFlags: Int): Boolean {
        if (policyFlags.hasBits(INSTALL_GRANTED)) {
            return true
            return true
        }
        }
        if (policyFlags.hasBits(INSTALL_REVOKED)) {
        if (flags.hasBits(INSTALL_REVOKED)) {
            return false
            return false
        }
        }
        if (policyFlags.hasBits(PROTECTION_GRANTED)) {
        if (flags.hasBits(PROTECTION_GRANTED)) {
            return true
            return true
        }
        }
        if (policyFlags.hasBits(LEGACY_GRANTED) || policyFlags.hasBits(IMPLICIT_GRANTED)) {
        if (flags.hasBits(LEGACY_GRANTED) || flags.hasBits(IMPLICIT_GRANTED)) {
            return true
            return true
        }
        }
        if (policyFlags.hasBits(RESTRICTION_REVOKED)) {
        if (flags.hasBits(RESTRICTION_REVOKED)) {
            return false
            return false
        }
        }
        return policyFlags.hasBits(RUNTIME_GRANTED)
        return flags.hasBits(RUNTIME_GRANTED)
    }
    }


    fun isAppOpGranted(policyFlags: Int): Boolean =
    fun isAppOpGranted(flags: Int): Boolean =
        isPermissionGranted(policyFlags) && !policyFlags.hasBits(APP_OP_REVOKED)
        isPermissionGranted(flags) && !flags.hasBits(APP_OP_REVOKED)

    fun isReviewRequired(policyFlags: Int): Boolean =
        policyFlags.hasBits(LEGACY_GRANTED) && policyFlags.hasBits(IMPLICIT)


    fun toApiFlags(policyFlags: Int): Int {
    fun toApiFlags(flags: Int): Int {
        var apiFlags = 0
        var apiFlags = 0
        if (policyFlags.hasBits(USER_SET)) {
        if (flags.hasBits(USER_SET)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SET
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SET
        }
        }
        if (policyFlags.hasBits(USER_FIXED)) {
        if (flags.hasBits(USER_FIXED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_FIXED
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_FIXED
        }
        }
        if (policyFlags.hasBits(POLICY_FIXED)) {
        if (flags.hasBits(POLICY_FIXED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_POLICY_FIXED
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_POLICY_FIXED
        }
        }
        if (policyFlags.hasBits(SYSTEM_FIXED)) {
        if (flags.hasBits(SYSTEM_FIXED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
        }
        }
        if (policyFlags.hasBits(PREGRANT)) {
        if (flags.hasBits(PREGRANT)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
        }
        }
        if (policyFlags.hasBits(IMPLICIT)) {
        if (flags.hasBits(IMPLICIT)) {
            apiFlags = apiFlags or if (policyFlags.hasBits(LEGACY_GRANTED)) {
            apiFlags = apiFlags or if (flags.hasBits(LEGACY_GRANTED)) {
                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
            } else {
            } else {
                PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
                PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
            }
            }
        }
        }
        if (policyFlags.hasBits(USER_SENSITIVE_WHEN_GRANTED)) {
        if (flags.hasBits(USER_SENSITIVE_WHEN_GRANTED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
        }
        }
        if (policyFlags.hasBits(USER_SENSITIVE_WHEN_REVOKED)) {
        if (flags.hasBits(USER_SENSITIVE_WHEN_REVOKED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED
        }
        }
        if (policyFlags.hasBits(INSTALLER_EXEMPT)) {
        if (flags.hasBits(INSTALLER_EXEMPT)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
        }
        }
        if (policyFlags.hasBits(SYSTEM_EXEMPT)) {
        if (flags.hasBits(SYSTEM_EXEMPT)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
        }
        }
        if (policyFlags.hasBits(UPGRADE_EXEMPT)) {
        if (flags.hasBits(UPGRADE_EXEMPT)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT
        }
        }
        if (policyFlags.hasBits(RESTRICTION_REVOKED) || policyFlags.hasBits(SOFT_RESTRICTED)) {
        if (flags.hasBits(RESTRICTION_REVOKED) || flags.hasBits(SOFT_RESTRICTED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION
        }
        }
        if (policyFlags.hasBits(ROLE)) {
        if (flags.hasBits(ROLE)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE
        }
        }
        if (policyFlags.hasBits(APP_OP_REVOKED)) {
        if (flags.hasBits(APP_OP_REVOKED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
        }
        }
        if (policyFlags.hasBits(ONE_TIME)) {
        if (flags.hasBits(ONE_TIME)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_ONE_TIME
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_ONE_TIME
        }
        }
        if (policyFlags.hasBits(HIBERNATION)) {
        if (flags.hasBits(HIBERNATION)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_AUTO_REVOKED
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_AUTO_REVOKED
        }
        }
        if (policyFlags.hasBits(USER_SELECTED)) {
        if (flags.hasBits(USER_SELECTED)) {
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY
            apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY
        }
        }
        return apiFlags
        return apiFlags
    }
    }


    fun setRuntimePermissionGranted(policyFlags: Int, isGranted: Boolean): Int =
    fun updateRuntimePermissionGranted(flags: Int, isGranted: Boolean): Int =
        if (isGranted) policyFlags or RUNTIME_GRANTED else policyFlags andInv RUNTIME_GRANTED
        if (isGranted) flags or RUNTIME_GRANTED else flags andInv RUNTIME_GRANTED


    fun updatePolicyFlags(policyFlags: Int, apiFlagMask: Int, apiFlagValues: Int): Int {
    fun updateFlags(permission: Permission, flags: Int, apiFlagMask: Int, apiFlagValues: Int): Int {
        check(!apiFlagMask.hasAnyBit(API_MASK_RESTRICTION)) {
        val oldApiFlags = toApiFlags(flags)
            "Permission flags about permission restriction can only be directly mutated by the" +
                " policy"
        }
        val oldApiFlags = toApiFlags(policyFlags)
        val newApiFlags = (oldApiFlags andInv apiFlagMask) or (apiFlagValues and apiFlagMask)
        val newApiFlags = (oldApiFlags andInv apiFlagMask) or (apiFlagValues and apiFlagMask)
        return toPolicyFlags(policyFlags, newApiFlags)
        return fromApiFlags(newApiFlags, permission, flags)
    }
    }


    private fun toPolicyFlags(oldPolicyFlags: Int, apiFlags: Int): Int {
    private fun fromApiFlags(apiFlags: Int, permission: Permission, oldFlags: Int): Int {
        var policyFlags = 0
        var flags = 0
        policyFlags = policyFlags or (oldPolicyFlags and INSTALL_GRANTED)
        flags = flags or (oldFlags and INSTALL_GRANTED)
        policyFlags = policyFlags or (oldPolicyFlags and INSTALL_REVOKED)
        flags = flags or (oldFlags and INSTALL_REVOKED)
        policyFlags = policyFlags or (oldPolicyFlags and PROTECTION_GRANTED)
        flags = flags or (oldFlags and PROTECTION_GRANTED)
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE)) {
            policyFlags = policyFlags or ROLE
            flags = flags or ROLE
        }
        }
        policyFlags = policyFlags or (oldPolicyFlags and RUNTIME_GRANTED)
        flags = flags or (oldFlags and RUNTIME_GRANTED)
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SET)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SET)) {
            policyFlags = policyFlags or USER_SET
            flags = flags or USER_SET
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_FIXED)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_FIXED)) {
            policyFlags = policyFlags or USER_FIXED
            flags = flags or USER_FIXED
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) {
            policyFlags = policyFlags or POLICY_FIXED
            flags = flags or POLICY_FIXED
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) {
            policyFlags = policyFlags or SYSTEM_FIXED
            flags = flags or SYSTEM_FIXED
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT)) {
            policyFlags = policyFlags or PREGRANT
            flags = flags or PREGRANT
        }
        }
        policyFlags = policyFlags or (oldPolicyFlags and LEGACY_GRANTED)
        flags = flags or (oldFlags and LEGACY_GRANTED)
        policyFlags = policyFlags or (oldPolicyFlags and IMPLICIT_GRANTED)
        flags = flags or (oldFlags and IMPLICIT_GRANTED)
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) ||
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) ||
            apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)) {
            apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)) {
            policyFlags = policyFlags or IMPLICIT
            flags = flags or IMPLICIT
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)) {
            policyFlags = policyFlags or USER_SENSITIVE_WHEN_GRANTED
            flags = flags or USER_SENSITIVE_WHEN_GRANTED
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED)) {
            policyFlags = policyFlags or USER_SENSITIVE_WHEN_REVOKED
            flags = flags or USER_SENSITIVE_WHEN_REVOKED
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT)) {
            flags = flags or INSTALLER_EXEMPT
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT)) {
            flags = flags or SYSTEM_EXEMPT
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT)) {
            flags = flags or UPGRADE_EXEMPT
        }
        // We ignore whether FLAG_PERMISSION_APPLY_RESTRICTION is set here because previously
        // platform may be relying on the old restorePermissionState() to get it correct later.
        if (!flags.hasAnyBit(MASK_EXEMPT)) {
            if (permission.isHardRestricted) {
                flags = flags or RESTRICTION_REVOKED
            }
            if (permission.isSoftRestricted) {
                flags = flags or SOFT_RESTRICTED
            }
        }
        }
        // FLAG_PERMISSION_APPLY_RESTRICTION can be either REVOKED_BY_RESTRICTION when the
        // permission is hard restricted, or SOFT_RESTRICTED when the permission is soft restricted.
        // However since we should never allow indirect mutation of restriction state, we can just
        // get the flags about restriction from the old policy flags.
        policyFlags = policyFlags or (oldPolicyFlags and MASK_RESTRICTION)
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)) {
            policyFlags = policyFlags or APP_OP_REVOKED
            flags = flags or APP_OP_REVOKED
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_ONE_TIME)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_ONE_TIME)) {
            policyFlags = policyFlags or ONE_TIME
            flags = flags or ONE_TIME
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_AUTO_REVOKED)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_AUTO_REVOKED)) {
            policyFlags = policyFlags or HIBERNATION
            flags = flags or HIBERNATION
        }
        }
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY)) {
        if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY)) {
            policyFlags = policyFlags or USER_SELECTED
            flags = flags or USER_SELECTED
        }
        }
        return policyFlags
        return flags
    }
    }
}
}