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

Commit 8d8a0038 authored by Hai Zhang's avatar Hai Zhang
Browse files

Revert "Revert "Fix privapp permission allowlisting.""

This reverts commit e54ab067.

Reason for revert: Added the missing allowlist entries

Bug: 179996437
Change-Id: Id26f8405468fd62d87c7cb93eabbcee78021bbd8
parent 71e1b819
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -46,6 +46,13 @@ import java.util.stream.Stream;
public class CollectionUtils {
    private CollectionUtils() { /* cannot be instantiated */ }

    /**
     * @see Collection#contains(Object)
     */
    public static <T> boolean contains(@Nullable Collection<T> collection, T element) {
        return collection != null && collection.contains(element);
    }

    /**
     * Returns a list of items from the provided list that match the given condition.
     *
+108 −97
Original line number Diff line number Diff line
@@ -2590,6 +2590,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        boolean runtimePermissionsRevoked = false;
        int[] updatedUserIds = EMPTY_INT_ARRAY;

        ArraySet<String> isPrivilegedPermissionAllowlisted = null;
        ArraySet<String> shouldGrantSignaturePermission = null;
        ArraySet<String> shouldGrantInternalPermission = null;
        final List<String> requestedPermissions = pkg.getRequestedPermissions();
@@ -2604,7 +2605,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            if (permission == null) {
                continue;
            }
            if (permission.isSignature() && (shouldGrantSignaturePermission(pkg, permission)
            if (permission.isPrivileged()
                    && checkPrivilegedPermissionAllowlist(pkg, ps, permission)) {
                if (isPrivilegedPermissionAllowlisted == null) {
                    isPrivilegedPermissionAllowlisted = new ArraySet<>();
                }
                isPrivilegedPermissionAllowlisted.add(permissionName);
            }
            if (permission.isSignature() && (shouldGrantPermissionBySignature(pkg, permission)
                    || shouldGrantPermissionByProtectionFlags(pkg, ps, permission))) {
                if (shouldGrantSignaturePermission == null) {
                    shouldGrantSignaturePermission = new ArraySet<>();
@@ -2830,13 +2838,17 @@ public class PermissionManagerService extends IPermissionManager.Stub {

                    if ((bp.isNormal() && shouldGrantNormalPermission)
                            || (bp.isSignature()
                                    && ((shouldGrantSignaturePermission != null
                                            && shouldGrantSignaturePermission.contains(permName))
                                    && (!bp.isPrivileged() || CollectionUtils.contains(
                                            isPrivilegedPermissionAllowlisted, permName))
                                    && (CollectionUtils.contains(shouldGrantSignaturePermission,
                                            permName)
                                            || ((bp.isDevelopment() || bp.isRole())
                                                    && origState.isPermissionGranted(permName))))
                            || (bp.isInternal()
                                    && ((shouldGrantInternalPermission != null
                                            && shouldGrantInternalPermission.contains(permName))
                                    && (!bp.isPrivileged() || CollectionUtils.contains(
                                            isPrivilegedPermissionAllowlisted, permName))
                                    && (CollectionUtils.contains(shouldGrantInternalPermission,
                                            permName)
                                            || ((bp.isDevelopment() || bp.isRole())
                                                    && origState.isPermissionGranted(permName))))) {
                        // Grant an install permission.
@@ -3343,7 +3355,92 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        return allowed;
    }

    private boolean shouldGrantSignaturePermission(@NonNull AndroidPackage pkg,
    private boolean checkPrivilegedPermissionAllowlist(@NonNull AndroidPackage pkg,
            @NonNull PackageSetting packageSetting, @NonNull Permission permission) {
        if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
            return true;
        }
        final String packageName = pkg.getPackageName();
        if (Objects.equals(packageName, PLATFORM_PACKAGE_NAME)) {
            return true;
        }
        if (!pkg.isPrivileged()) {
            return true;
        }
        if (!Objects.equals(permission.getPackageName(), PLATFORM_PACKAGE_NAME)) {
            return true;
        }
        final String permissionName = permission.getName();
        if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) {
            return true;
        }
        // Only enforce the allowlist on boot
        if (!mSystemReady
                // Updated system apps do not need to be allowlisted
                && !packageSetting.getPkgState().isUpdatedSystemApp()) {
            final ApexManager apexManager = ApexManager.getInstance();
            final String containingApexPackageName =
                    apexManager.getActiveApexPackageNameContainingPackage(packageName);
            final boolean isInUpdatedApex = containingApexPackageName != null
                    && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
                    MATCH_ACTIVE_PACKAGE));
            // Apps that are in updated apexs' do not need to be allowlisted
            if (!isInUpdatedApex) {
                // it's only a reportable violation if the permission isn't explicitly
                // denied
                if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName)) {
                    return false;
                }
                Slog.w(TAG, "Privileged permission " + permissionName + " for package "
                        + packageName + " (" + pkg.getPath()
                        + ") not in privapp-permissions allowlist");
                if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
                    synchronized (mLock) {
                        if (mPrivappPermissionsViolations == null) {
                            mPrivappPermissionsViolations = new ArraySet<>();
                        }
                        mPrivappPermissionsViolations.add(packageName + " (" + pkg.getPath() + "): "
                                + permissionName);
                    }
                }
            }
        }
        return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE;
    }

    private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg,
            @NonNull String permission) {
        final SystemConfig systemConfig = SystemConfig.getInstance();
        final Set<String> permissions;
        if (pkg.isVendor()) {
            permissions = systemConfig.getVendorPrivAppPermissions(pkg.getPackageName());
        } else if (pkg.isProduct()) {
            permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName());
        } else if (pkg.isSystemExt()) {
            permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName());
        } else {
            permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName());
        }
        return CollectionUtils.contains(permissions, permission);
    }

    private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg,
            @NonNull String permission) {
        final SystemConfig systemConfig = SystemConfig.getInstance();
        final Set<String> permissions;
        if (pkg.isVendor()) {
            permissions = systemConfig.getVendorPrivAppDenyPermissions(pkg.getPackageName());
        } else if (pkg.isProduct()) {
            permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName());
        } else if (pkg.isSystemExt()) {
            permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
        } else {
            permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName());
        }
        return CollectionUtils.contains(permissions, permission);
    }

    private boolean shouldGrantPermissionBySignature(@NonNull AndroidPackage pkg,
            @NonNull Permission bp) {
        // expect single system package
        String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames(
@@ -3373,8 +3470,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
    private boolean shouldGrantPermissionByProtectionFlags(@NonNull AndroidPackage pkg,
            @NonNull PackageSetting pkgSetting, @NonNull Permission bp) {
        boolean allowed = false;
        final boolean isVendorPrivilegedPermission = bp.isVendorPrivileged();
        final boolean isPrivilegedPermission = bp.isPrivileged() || isVendorPrivilegedPermission;
        final boolean isPrivilegedPermission = bp.isPrivileged();
        final boolean isOemPermission = bp.isOem();
        if (!allowed && (isPrivilegedPermission || isOemPermission) && pkg.isSystem()) {
            final String permissionName = bp.getName();
@@ -3386,19 +3482,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.pkg;
                if (disabledPkg != null && disabledPkg.getRequestedPermissions().contains(
                        permissionName)) {
                    allowed = (isPrivilegedPermission && canGrantPrivilegedPermission(disabledPkg,
                            true, bp)) || (isOemPermission && canGrantOemPermission(disabledPkg,
                    allowed = (isPrivilegedPermission && disabledPkg.isPrivileged())
                            || (isOemPermission && canGrantOemPermission(disabledPkg,
                            permissionName));
                }
            } else {
                allowed = (isPrivilegedPermission && canGrantPrivilegedPermission(pkg, false, bp))
                allowed = (isPrivilegedPermission && pkg.isPrivileged())
                        || (isOemPermission && canGrantOemPermission(pkg, permissionName));
            }
            // In any case, don't grant a privileged permission to privileged vendor apps, if
            // the permission's protectionLevel does not have the extra 'vendorPrivileged'
            // flag.
            if (allowed && isPrivilegedPermission && !isVendorPrivilegedPermission
                    && pkg.isVendor()) {
            if (allowed && isPrivilegedPermission && !bp.isVendorPrivileged() && pkg.isVendor()) {
                Slog.w(TAG, "Permission " + permissionName
                        + " cannot be granted to privileged vendor apk " + pkg.getPackageName()
                        + " because it isn't a 'vendorPrivileged' permission.");
@@ -3541,90 +3636,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        return mPackageManagerInt.getPackageSetting(sourcePackageName);
    }

    private boolean canGrantPrivilegedPermission(@NonNull AndroidPackage pkg,
            boolean isUpdatedSystemApp, @NonNull Permission permission) {
        if (!pkg.isPrivileged()) {
            return false;
        }
        final boolean isPlatformPermission = PLATFORM_PACKAGE_NAME.equals(
                permission.getPackageName());
        if (!isPlatformPermission) {
            return true;
        }
        if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
            return true;
        }
        final String permissionName = permission.getName();
        if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) {
            return true;
        }
        // Only enforce the allowlist on boot
        if (!mSystemReady
                // Updated system apps do not need to be allowlisted
                && !isUpdatedSystemApp) {
            final ApexManager apexManager = ApexManager.getInstance();
            final String packageName = pkg.getPackageName();
            final String containingApexPackageName =
                    apexManager.getActiveApexPackageNameContainingPackage(packageName);
            final boolean isInUpdatedApex = containingApexPackageName != null
                    && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
                    MATCH_ACTIVE_PACKAGE));
            // Apps that are in updated apexs' do not need to be allowlisted
            if (!isInUpdatedApex) {
                // it's only a reportable violation if the permission isn't explicitly
                // denied
                if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName)) {
                    return false;
                }
                Slog.w(TAG, "Privileged permission " + permissionName + " for package "
                        + packageName + " (" + pkg.getPath()
                        + ") not in privapp-permissions allowlist");
                if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
                    synchronized (mLock) {
                        if (mPrivappPermissionsViolations == null) {
                            mPrivappPermissionsViolations = new ArraySet<>();
                        }
                        mPrivappPermissionsViolations.add(packageName + " (" + pkg.getPath() + "): "
                                + permissionName);
                    }
                }
            }
        }
        return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE;
    }

    private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg,
            @NonNull String permission) {
        final SystemConfig systemConfig = SystemConfig.getInstance();
        final Set<String> permissions;
        if (pkg.isVendor()) {
            permissions = systemConfig.getVendorPrivAppPermissions(pkg.getPackageName());
        } else if (pkg.isProduct()) {
            permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName());
        } else if (pkg.isSystemExt()) {
            permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName());
        } else {
            permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName());
        }
        return permissions != null && permissions.contains(permission);
    }

    private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg,
            @NonNull String permission) {
        final SystemConfig systemConfig = SystemConfig.getInstance();
        final Set<String> permissions;
        if (pkg.isVendor()) {
            permissions = systemConfig.getVendorPrivAppDenyPermissions(pkg.getPackageName());
        } else if (pkg.isProduct()) {
            permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName());
        } else if (pkg.isSystemExt()) {
            permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
        } else {
            permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName());
        }
        return permissions != null && permissions.contains(permission);
    }

    private static boolean canGrantOemPermission(AndroidPackage pkg, String permission) {
        if (!pkg.isOem()) {
            return false;