Merge "Revert "Revert "Fix privapp permission allowlisting.""" into sc-dev

This commit is contained in:
Hai Zhang
2021-02-12 04:16:43 +00:00
committed by Android (Google) Code Review
2 changed files with 115 additions and 97 deletions

View File

@@ -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.
*

View File

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