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;
}