private boolean grantSignaturePermission()

in com/android/server/pm/permission/PermissionManagerService.java [1037:1237]


    private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
            BasePermission bp, PermissionsState origPermissions) {
        boolean oemPermission = bp.isOEM();
        boolean vendorPrivilegedPermission = bp.isVendorPrivileged();
        boolean privilegedPermission = bp.isPrivileged() || bp.isVendorPrivileged();
        boolean privappPermissionsDisable =
                RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;
        boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName());
        boolean platformPackage = PLATFORM_PACKAGE_NAME.equals(pkg.packageName);
        if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
                && !platformPackage && platformPermission) {
            if (!hasPrivappWhitelistEntry(perm, pkg)) {
                // Only report violations for apps on system image
                if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
                    // it's only a reportable violation if the permission isn't explicitly denied
                    ArraySet<String> deniedPermissions = null;
                    if (pkg.isVendor()) {
                        deniedPermissions = SystemConfig.getInstance()
                                .getVendorPrivAppDenyPermissions(pkg.packageName);
                    } else if (pkg.isProduct()) {
                        deniedPermissions = SystemConfig.getInstance()
                                .getProductPrivAppDenyPermissions(pkg.packageName);
                    } else {
                        deniedPermissions = SystemConfig.getInstance()
                                .getPrivAppDenyPermissions(pkg.packageName);
                    }
                    final boolean permissionViolation =
                            deniedPermissions == null || !deniedPermissions.contains(perm);
                    if (permissionViolation) {
                        Slog.w(TAG, "Privileged permission " + perm + " for package "
                                + pkg.packageName + " - not in privapp-permissions whitelist");

                        if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
                            if (mPrivappPermissionsViolations == null) {
                                mPrivappPermissionsViolations = new ArraySet<>();
                            }
                            mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm);
                        }
                    } else {
                        return false;
                    }
                }
                if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
                    return false;
                }
            }
        }
        final String systemPackageName = mPackageManagerInt.getKnownPackageName(
                PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
        final PackageParser.Package systemPackage =
                mPackageManagerInt.getPackage(systemPackageName);

        // check if the package is allow to use this signature permission.  A package is allowed to
        // use a signature permission if:
        //     - it has the same set of signing certificates as the source package
        //     - or its signing certificate was rotated from the source package's certificate
        //     - or its signing certificate is a previous signing certificate of the defining
        //       package, and the defining package still trusts the old certificate for permissions
        //     - or it shares the above relationships with the system package
        boolean allowed =
                pkg.mSigningDetails.hasAncestorOrSelf(
                        bp.getSourcePackageSetting().getSigningDetails())
                || bp.getSourcePackageSetting().getSigningDetails().checkCapability(
                        pkg.mSigningDetails,
                        PackageParser.SigningDetails.CertCapabilities.PERMISSION)
                || pkg.mSigningDetails.hasAncestorOrSelf(systemPackage.mSigningDetails)
                || systemPackage.mSigningDetails.checkCapability(
                        pkg.mSigningDetails,
                        PackageParser.SigningDetails.CertCapabilities.PERMISSION);
        if (!allowed && (privilegedPermission || oemPermission)) {
            if (pkg.isSystem()) {
                // For updated system applications, a privileged/oem permission
                // is granted only if it had been defined by the original application.
                if (pkg.isUpdatedSystemApp()) {
                    final PackageParser.Package disabledPkg =
                            mPackageManagerInt.getDisabledPackage(pkg.packageName);
                    final PackageSetting disabledPs =
                            (disabledPkg != null) ? (PackageSetting) disabledPkg.mExtras : null;
                    if (disabledPs != null
                            && disabledPs.getPermissionsState().hasInstallPermission(perm)) {
                        // If the original was granted this permission, we take
                        // that grant decision as read and propagate it to the
                        // update.
                        if ((privilegedPermission && disabledPs.isPrivileged())
                                || (oemPermission && disabledPs.isOem()
                                        && canGrantOemPermission(disabledPs, perm))) {
                            allowed = true;
                        }
                    } else {
                        // The system apk may have been updated with an older
                        // version of the one on the data partition, but which
                        // granted a new system permission that it didn't have
                        // before.  In this case we do want to allow the app to
                        // now get the new permission if the ancestral apk is
                        // privileged to get it.
                        if (disabledPs != null && disabledPkg != null
                                && isPackageRequestingPermission(disabledPkg, perm)
                                && ((privilegedPermission && disabledPs.isPrivileged())
                                        || (oemPermission && disabledPs.isOem()
                                                && canGrantOemPermission(disabledPs, perm)))) {
                            allowed = true;
                        }
                        // Also if a privileged parent package on the system image or any of
                        // its children requested a privileged/oem permission, the updated child
                        // packages can also get the permission.
                        if (pkg.parentPackage != null) {
                            final PackageParser.Package disabledParentPkg = mPackageManagerInt
                                    .getDisabledPackage(pkg.parentPackage.packageName);
                            final PackageSetting disabledParentPs = (disabledParentPkg != null)
                                    ? (PackageSetting) disabledParentPkg.mExtras : null;
                            if (disabledParentPkg != null
                                    && ((privilegedPermission && disabledParentPs.isPrivileged())
                                            || (oemPermission && disabledParentPs.isOem()))) {
                                if (isPackageRequestingPermission(disabledParentPkg, perm)
                                        && canGrantOemPermission(disabledParentPs, perm)) {
                                    allowed = true;
                                } else if (disabledParentPkg.childPackages != null) {
                                    for (PackageParser.Package disabledChildPkg
                                            : disabledParentPkg.childPackages) {
                                        final PackageSetting disabledChildPs =
                                                (disabledChildPkg != null)
                                                        ? (PackageSetting) disabledChildPkg.mExtras
                                                        : null;
                                        if (isPackageRequestingPermission(disabledChildPkg, perm)
                                                && canGrantOemPermission(
                                                        disabledChildPs, perm)) {
                                            allowed = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    final PackageSetting ps = (PackageSetting) pkg.mExtras;
                    allowed = (privilegedPermission && pkg.isPrivileged())
                            || (oemPermission && pkg.isOem()
                                    && canGrantOemPermission(ps, perm));
                }
                // 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 && privilegedPermission &&
                        !vendorPrivilegedPermission && pkg.isVendor()) {
                   Slog.w(TAG, "Permission " + perm + " cannot be granted to privileged vendor apk "
                           + pkg.packageName + " because it isn't a 'vendorPrivileged' permission.");
                   allowed = false;
                }
            }
        }
        if (!allowed) {
            if (!allowed
                    && bp.isPre23()
                    && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
                // If this was a previously normal/dangerous permission that got moved
                // to a system permission as part of the runtime permission redesign, then
                // we still want to blindly grant it to old apps.
                allowed = true;
            }
            if (!allowed && bp.isInstaller()
                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
                            PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM))) {
                // If this permission is to be granted to the system installer and
                // this app is an installer, then it gets the permission.
                allowed = true;
            }
            if (!allowed && bp.isVerifier()
                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
                            PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM))) {
                // If this permission is to be granted to the system verifier and
                // this app is a verifier, then it gets the permission.
                allowed = true;
            }
            if (!allowed && bp.isPreInstalled()
                    && pkg.isSystem()) {
                // Any pre-installed system app is allowed to get this permission.
                allowed = true;
            }
            if (!allowed && bp.isDevelopment()) {
                // For development permissions, a development permission
                // is granted only if it was already granted.
                allowed = origPermissions.hasInstallPermission(perm);
            }
            if (!allowed && bp.isSetup()
                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
                            PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM))) {
                // If this permission is to be granted to the system setup wizard and
                // this app is a setup wizard, then it gets the permission.
                allowed = true;
            }
            if (!allowed && bp.isSystemTextClassifier()
                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
                            PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER,
                            UserHandle.USER_SYSTEM))) {
                // Special permissions for the system default text classifier.
                allowed = true;
            }
        }
        return allowed;
    }