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

Commit 4f9aad5f authored by Nate Myren's avatar Nate Myren Committed by mse1969
Browse files

[BACKPORT] V2 Merge all permissions in a shared UID for every package in that UID

Since every package can use the permissions in the shared UID, even if
the given package didn't request it, every package should be treated in
UI as if they all have the total set of requested permissions

Test: atest PermissionTest23
Bug: 435737668
Flag: EXEMPT CVE_FIX
Relnote: cve fix
Low-Coverage-Reason: security fix
BUG: 456903810
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:5dc1286825914295c86550b4321cb26397994543
Merged-In: I886add5db84b659d52d4a60b17304f017a17dc90
Change-Id: I886add5db84b659d52d4a60b17304f017a17dc90
parent 58daf3dd
Loading
Loading
Loading
Loading
+92 −2
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package com.android.permissioncontroller.permission.data

import android.app.Application
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Parcel
import android.os.UserHandle
import android.util.Log
import androidx.annotation.MainThread
@@ -94,8 +96,24 @@ class LightPackageInfoLiveData private constructor(
            return
        }
        postValue(try {
            LightPackageInfo(context.packageManager.getPackageInfo(packageName,
                PackageManager.GET_PERMISSIONS))
            val packageManager = context.packageManager
            var pI = packageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
            if (pI.sharedUserId != null && pI.applicationInfo != null) {
                val sharedPackageNames =
                    packageManager.getPackagesForUid(pI.applicationInfo!!.uid)
                val sharedPackages =
                    sharedPackageNames?.mapNotNull { otherPackageName ->
                        try {
                            val otherPi = packageManager.getPackageInfo(otherPackageName,
                                              PackageManager.GET_PERMISSIONS)
                            otherPi
                        } catch (_: PackageManager.NameNotFoundException) {
                            null
                        }
                    }
                pI = mergePermissionsInSharedUid(pI, sharedPackages)
            }
            LightPackageInfo(pI)
        } catch (e: PackageManager.NameNotFoundException) {
            Log.w(LOG_TAG, "Package \"$packageName\" not found")
            invalidateSingle(packageName to user)
@@ -179,5 +197,77 @@ class LightPackageInfoLiveData private constructor(
            return LightPackageInfoLiveData(PermissionControllerApplication.get(),
                key.first, key.second)
        }
        @JvmStatic
        fun mergePermissionsInSharedUid(
            base: PackageInfo,
            flags: Int,
            packageManager: PackageManager
        ): PackageInfo {
            if (base.sharedUserId != null && base.applicationInfo != null) {
                val sharedPackageNames =
                    packageManager.getPackagesForUid(base.applicationInfo!!.uid)
                val sharedPackages =
                    sharedPackageNames?.mapNotNull { otherPackageName ->
                        try {
                            val otherPi = packageManager.getPackageInfo(otherPackageName, flags)
                            otherPi
                        } catch (_: PackageManager.NameNotFoundException) {
                            null
                        }
                    }
                return mergePermissionsInSharedUid(base, sharedPackages)
            }
            return base
        }

        fun mergePermissionsInSharedUid(
            base: PackageInfo,
            otherPackages: List<PackageInfo>?
        ): PackageInfo {
            if (
                otherPackages == null || base.applicationInfo == null || base.sharedUserId == null
            ) {
                return base
            }

            val allPackages =
                if (base in otherPackages) otherPackages
                else otherPackages.toMutableList().apply { add(base) }
            val permissionStates = mutableMapOf<String, Int>()
            allPackages.forEach { packageInfo ->
                if (
                    packageInfo.applicationInfo?.uid != base.applicationInfo?.uid ||
                        packageInfo.requestedPermissions == null
                ) {
                    return@forEach
                }
                packageInfo.requestedPermissions!!.forEachIndexed { index, permission ->
                    val existingFlags = permissionStates.getOrDefault(permission, 0)
                    permissionStates[permission] =
                        existingFlags or packageInfo.requestedPermissionsFlags!![index]
                }
            }
            val requestedPermissions = permissionStates.keys.toTypedArray()
            val requestedPermissionsFlags = IntArray(requestedPermissions.size)
            requestedPermissions.forEachIndexed { index, permission ->
                requestedPermissionsFlags[index] = permissionStates[permission]!!
            }
            val packageCopy = copyPackageInfo(base)
            packageCopy.requestedPermissions = requestedPermissions
            packageCopy.requestedPermissionsFlags = requestedPermissionsFlags
            return packageCopy
        }

        fun copyPackageInfo(original: PackageInfo): PackageInfo {
            val parcel = Parcel.obtain()
            try {
                original.writeToParcel(parcel, 0)
                parcel.setDataPosition(0)
                val copy = PackageInfo.CREATOR.createFromParcel(parcel)
                return copy
            } finally {
                parcel.recycle()
            }
        }
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -76,7 +76,13 @@ class PermStateLiveData private constructor(

        val packageInfo = currentPackageInfo
        val permissionGroup = groupLiveData.value
        if (packageInfo == null || permissionGroup == null) {
        if (
            packageInfo == null ||
                permissionGroup == null ||
                !packageInfo.requestedPermissions.any { it in permissionGroup.permissionInfos }
        ) {
            // package is invalid, permission group is invalid, or the package requests no
            // permissions in the given group
            invalidateSingle(Triple(packageName, permGroupName, user))
            postValue(null)
            return
+17 −2
Original line number Diff line number Diff line
@@ -81,7 +81,22 @@ class UserPackageInfosLiveData private constructor(
        val packageInfos = app.applicationContext.packageManager
            .getInstalledPackagesAsUser(GET_PERMISSIONS or MATCH_ALL, user.identifier)

        postValue(packageInfos.map { packageInfo -> LightPackageInfo(packageInfo) })
        postValue(
            packageInfos.map { packageInfo ->
                val mergedPackageInfo =
                    if (packageInfo.sharedUserId != null) {
                        val otherPackages =
                            packageInfos.filter { it.sharedUserId == packageInfo.sharedUserId }
                        LightPackageInfoLiveData.mergePermissionsInSharedUid(
                            packageInfo,
                            otherPackages
                        )
                    } else {
                        packageInfo
                    }
                LightPackageInfo(mergedPackageInfo)
            }
        )
    }

    override fun onActive() {
+7 −3
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;

import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.data.LightPackageInfoLiveData;
import com.android.permissioncontroller.permission.service.LocationAccessCheck;
import com.android.permissioncontroller.permission.utils.ArrayUtils;
import com.android.permissioncontroller.permission.utils.LocationUtils;
@@ -204,8 +205,11 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
    public static AppPermissionGroup create(Application app, String packageName,
            String permissionGroupName, UserHandle user, boolean delayChanges) {
        try {
            PackageInfo packageInfo = Utils.getUserContext(app, user).getPackageManager()
                    .getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
            PackageManager pm = Utils.getUserContext(app, user).getPackageManager();
            int flags = PackageManager.GET_PERMISSIONS;
            PackageInfo packageInfo = pm.getPackageInfo(packageName, flags);
            PackageInfo mergedPackageInfo = LightPackageInfoLiveData.mergePermissionsInSharedUid(
                    packageInfo, flags, pm);
            PackageItemInfo groupInfo = Utils.getGroupInfo(permissionGroupName, app);
            if (groupInfo == null) {
                return null;
@@ -216,7 +220,7 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
                permissionInfos = Utils.getPermissionInfosForGroup(app.getPackageManager(),
                            groupInfo.name);
            }
            return create(app, packageInfo, groupInfo, permissionInfos, delayChanges);
            return create(app, mergedPackageInfo, groupInfo, permissionInfos, delayChanges);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
+6 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.ArrayMap;

import com.android.permissioncontroller.permission.data.LightPackageInfoLiveData;
import com.android.permissioncontroller.permission.utils.Utils;

import java.util.ArrayList;
@@ -109,10 +110,12 @@ public final class AppPermissions {

    private void loadPackageInfo() {
        try {
            mPackageInfo = mContext.createPackageContextAsUser(mPackageInfo.packageName, 0,
            PackageManager pm = mContext.createPackageContextAsUser(mPackageInfo.packageName, 0,
                    UserHandle.getUserHandleForUid(mPackageInfo.applicationInfo.uid))
                    .getPackageManager().getPackageInfo(mPackageInfo.packageName,
                            PackageManager.GET_PERMISSIONS);
                    .getPackageManager();
            int flags = PackageManager.GET_PERMISSIONS;
            PackageInfo pI = pm.getPackageInfo(mPackageInfo.packageName, flags);
            mPackageInfo = LightPackageInfoLiveData.mergePermissionsInSharedUid(pI, flags, pm);
        } catch (PackageManager.NameNotFoundException e) {
            if (mOnErrorCallback != null) {
                mOnErrorCallback.run();
Loading