summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/permission/flags.aconfig8
-rw-r--r--services/core/java/com/android/server/SystemConfig.java49
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionAllowlist.java74
-rw-r--r--services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt80
4 files changed, 200 insertions, 11 deletions
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 60143cc79d2d..ecc0cdade45c 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -78,3 +78,11 @@ flag {
description: "This flag is used to enabled the Wallet Role for all users on the device"
bug: "283989236"
}
+
+flag {
+ name: "signature_permission_allowlist_enabled"
+ is_fixed_read_only: true
+ namespace: "permissions"
+ description: "Enable signature permission allowlist"
+ bug: "308573169"
+}
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 3483c1a1404a..a493d7a57500 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -95,6 +95,7 @@ public class SystemConfig {
private static final int ALLOW_OVERRIDE_APP_RESTRICTIONS = 0x100;
private static final int ALLOW_IMPLICIT_BROADCASTS = 0x200;
private static final int ALLOW_VENDOR_APEX = 0x400;
+ private static final int ALLOW_SIGNATURE_PERMISSIONS = 0x800;
private static final int ALLOW_ALL = ~0;
// property for runtime configuration differentiation
@@ -597,7 +598,7 @@ public class SystemConfig {
// Vendors are only allowed to customize these
int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
- | ALLOW_ASSOCIATIONS | ALLOW_VENDOR_APEX;
+ | ALLOW_SIGNATURE_PERMISSIONS | ALLOW_ASSOCIATIONS | ALLOW_VENDOR_APEX;
if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.O_MR1) {
// For backward compatibility
vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
@@ -649,9 +650,9 @@ public class SystemConfig {
// TODO(b/157203468): ALLOW_HIDDENAPI_WHITELISTING must be removed because we prohibited
// the use of hidden APIs from the product partition.
int productPermissionFlag = ALLOW_FEATURES | ALLOW_LIBS | ALLOW_PERMISSIONS
- | ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS | ALLOW_HIDDENAPI_WHITELISTING
- | ALLOW_ASSOCIATIONS | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS
- | ALLOW_VENDOR_APEX;
+ | ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS | ALLOW_SIGNATURE_PERMISSIONS
+ | ALLOW_HIDDENAPI_WHITELISTING | ALLOW_ASSOCIATIONS
+ | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS | ALLOW_VENDOR_APEX;
if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.R) {
// TODO(b/157393157): This must check product interface enforcement instead of
// DEVICE_INITIAL_SDK_INT for the devices without product interface enforcement.
@@ -772,6 +773,8 @@ public class SystemConfig {
final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS)
!= 0;
+ final boolean allowSignaturePermissions = (permissionFlag & ALLOW_SIGNATURE_PERMISSIONS)
+ != 0;
final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0;
final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING)
!= 0;
@@ -1246,6 +1249,38 @@ public class SystemConfig {
XmlUtils.skipCurrentTag(parser);
}
} break;
+ case "signature-permissions": {
+ if (allowSignaturePermissions) {
+ // signature permissions from system, apex, vendor, product and
+ // system_ext partitions are stored separately. This is to
+ // prevent xml files in the vendor partition from granting
+ // permissions to signature apps in the system partition and vice versa.
+ boolean vendor = permFile.toPath().startsWith(
+ Environment.getVendorDirectory().toPath() + "/")
+ || permFile.toPath().startsWith(
+ Environment.getOdmDirectory().toPath() + "/");
+ boolean product = permFile.toPath().startsWith(
+ Environment.getProductDirectory().toPath() + "/");
+ boolean systemExt = permFile.toPath().startsWith(
+ Environment.getSystemExtDirectory().toPath() + "/");
+ if (vendor) {
+ readSignatureAppPermissions(parser,
+ mPermissionAllowlist.getVendorSignatureAppAllowlist());
+ } else if (product) {
+ readSignatureAppPermissions(parser,
+ mPermissionAllowlist.getProductSignatureAppAllowlist());
+ } else if (systemExt) {
+ readSignatureAppPermissions(parser,
+ mPermissionAllowlist.getSystemExtSignatureAppAllowlist());
+ } else {
+ readSignatureAppPermissions(parser,
+ mPermissionAllowlist.getSignatureAppAllowlist());
+ }
+ } else {
+ logNotAllowedInPartition(name, permFile, parser);
+ XmlUtils.skipCurrentTag(parser);
+ }
+ } break;
case "oem-permissions": {
if (allowOemPermissions) {
readOemPermissions(parser);
@@ -1655,6 +1690,12 @@ public class SystemConfig {
readPermissionAllowlist(parser, allowlist, "privapp-permissions");
}
+ private void readSignatureAppPermissions(@NonNull XmlPullParser parser,
+ @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist)
+ throws IOException, XmlPullParserException {
+ readPermissionAllowlist(parser, allowlist, "signature-permissions");
+ }
+
private void readInstallInUserType(XmlPullParser parser,
Map<String, Set<String>> doInstallMap,
Map<String, Set<String>> nonInstallMap)
diff --git a/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java b/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java
index 3efac81d44e3..d138606369b9 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java
@@ -26,6 +26,7 @@ import android.util.ArrayMap;
public final class PermissionAllowlist {
@NonNull
private final ArrayMap<String, ArrayMap<String, Boolean>> mOemAppAllowlist = new ArrayMap<>();
+
@NonNull
private final ArrayMap<String, ArrayMap<String, Boolean>> mPrivilegedAppAllowlist =
new ArrayMap<>();
@@ -43,6 +44,19 @@ public final class PermissionAllowlist {
mApexPrivilegedAppAllowlists = new ArrayMap<>();
@NonNull
+ private final ArrayMap<String, ArrayMap<String, Boolean>> mSignatureAppAllowlist =
+ new ArrayMap<>();
+ @NonNull
+ private final ArrayMap<String, ArrayMap<String, Boolean>> mVendorSignatureAppAllowlist =
+ new ArrayMap<>();
+ @NonNull
+ private final ArrayMap<String, ArrayMap<String, Boolean>> mProductSignatureAppAllowlist =
+ new ArrayMap<>();
+ @NonNull
+ private final ArrayMap<String, ArrayMap<String, Boolean>> mSystemExtSignatureAppAllowlist =
+ new ArrayMap<>();
+
+ @NonNull
public ArrayMap<String, ArrayMap<String, Boolean>> getOemAppAllowlist() {
return mOemAppAllowlist;
}
@@ -73,6 +87,26 @@ public final class PermissionAllowlist {
return mApexPrivilegedAppAllowlists;
}
+ @NonNull
+ public ArrayMap<String, ArrayMap<String, Boolean>> getSignatureAppAllowlist() {
+ return mSignatureAppAllowlist;
+ }
+
+ @NonNull
+ public ArrayMap<String, ArrayMap<String, Boolean>> getVendorSignatureAppAllowlist() {
+ return mVendorSignatureAppAllowlist;
+ }
+
+ @NonNull
+ public ArrayMap<String, ArrayMap<String, Boolean>> getProductSignatureAppAllowlist() {
+ return mProductSignatureAppAllowlist;
+ }
+
+ @NonNull
+ public ArrayMap<String, ArrayMap<String, Boolean>> getSystemExtSignatureAppAllowlist() {
+ return mSystemExtSignatureAppAllowlist;
+ }
+
@Nullable
public Boolean getOemAppAllowlistState(@NonNull String packageName,
@NonNull String permissionName) {
@@ -137,4 +171,44 @@ public final class PermissionAllowlist {
}
return permissions.get(permissionName);
}
+
+ @Nullable
+ public Boolean getSignatureAppAllowlistState(@NonNull String packageName,
+ @NonNull String permissionName) {
+ ArrayMap<String, Boolean> permissions = mSignatureAppAllowlist.get(packageName);
+ if (permissions == null) {
+ return null;
+ }
+ return permissions.get(permissionName);
+ }
+
+ @Nullable
+ public Boolean getVendorSignatureAppAllowlistState(@NonNull String packageName,
+ @NonNull String permissionName) {
+ ArrayMap<String, Boolean> permissions = mVendorSignatureAppAllowlist.get(packageName);
+ if (permissions == null) {
+ return null;
+ }
+ return permissions.get(permissionName);
+ }
+
+ @Nullable
+ public Boolean getProductSignatureAppAllowlistState(@NonNull String packageName,
+ @NonNull String permissionName) {
+ ArrayMap<String, Boolean> permissions = mProductSignatureAppAllowlist.get(packageName);
+ if (permissions == null) {
+ return null;
+ }
+ return permissions.get(permissionName);
+ }
+
+ @Nullable
+ public Boolean getSystemExtSignatureAppAllowlistState(@NonNull String packageName,
+ @NonNull String permissionName) {
+ ArrayMap<String, Boolean> permissions = mSystemExtSignatureAppAllowlist.get(packageName);
+ if (permissions == null) {
+ return null;
+ }
+ return permissions.get(permissionName);
+ }
}
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 022268df4a63..823c8839c90e 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -22,6 +22,7 @@ import android.content.pm.PermissionGroupInfo
import android.content.pm.PermissionInfo
import android.content.pm.SigningDetails
import android.os.Build
+import android.permission.flags.Flags
import android.util.Slog
import com.android.internal.os.RoSystemProperties
import com.android.internal.pm.permission.CompatibilityPermissionInfo
@@ -1193,15 +1194,80 @@ class AppIdPermissionPolicy : SchemePolicy() {
newState.externalState.packageStates[PLATFORM_PACKAGE_NAME]!!
.androidPackage!!
.signingDetails
- return sourceSigningDetails?.hasCommonSignerWithCapability(
- packageSigningDetails,
- SigningDetails.CertCapabilities.PERMISSION
- ) == true ||
- packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) ||
- platformSigningDetails.checkCapability(
+ val hasCommonSigner =
+ sourceSigningDetails?.hasCommonSignerWithCapability(
packageSigningDetails,
SigningDetails.CertCapabilities.PERMISSION
- )
+ ) == true ||
+ packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) ||
+ platformSigningDetails.checkCapability(
+ packageSigningDetails,
+ SigningDetails.CertCapabilities.PERMISSION
+ )
+ if (!Flags.signaturePermissionAllowlistEnabled()) {
+ return hasCommonSigner;
+ }
+ if (!hasCommonSigner) {
+ return false
+ }
+ // A platform signature permission also needs to be allowlisted on non-debuggable builds.
+ if (permission.packageName == PLATFORM_PACKAGE_NAME) {
+ val isRequestedByFactoryApp =
+ if (packageState.isSystem) {
+ // For updated system applications, a signature permission still needs to be
+ // allowlisted if it wasn't requested by the original application.
+ if (packageState.isUpdatedSystemApp) {
+ val disabledSystemPackage =
+ newState.externalState.disabledSystemPackageStates[
+ packageState.packageName]
+ ?.androidPackage
+ disabledSystemPackage != null &&
+ permission.name in disabledSystemPackage.requestedPermissions
+ } else {
+ true
+ }
+ } else {
+ false
+ }
+ if (
+ !(isRequestedByFactoryApp ||
+ getSignaturePermissionAllowlistState(packageState, permission.name) == true)
+ ) {
+ Slog.w(
+ LOG_TAG,
+ "Signature permission ${permission.name} for package" +
+ " ${packageState.packageName} (${packageState.path}) not in" +
+ " signature permission allowlist"
+ )
+ if (!Build.isDebuggable()) {
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ private fun MutateStateScope.getSignaturePermissionAllowlistState(
+ packageState: PackageState,
+ permissionName: String
+ ): Boolean? {
+ val permissionAllowlist = newState.externalState.permissionAllowlist
+ val packageName = packageState.packageName
+ return when {
+ packageState.isVendor || packageState.isOdm ->
+ permissionAllowlist.getVendorSignatureAppAllowlistState(packageName, permissionName)
+ packageState.isProduct ->
+ permissionAllowlist.getProductSignatureAppAllowlistState(
+ packageName,
+ permissionName
+ )
+ packageState.isSystemExt ->
+ permissionAllowlist.getSystemExtSignatureAppAllowlistState(
+ packageName,
+ permissionName
+ )
+ else -> permissionAllowlist.getSignatureAppAllowlistState(packageName, permissionName)
+ }
}
private fun MutateStateScope.checkPrivilegedPermissionAllowlist(