Merge "Revert "Revert "Fix privapp permission allowlisting.""" into sc-dev
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user