From 15707b3f4df8f44881643adfc369b3cd50bc5598 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 10 Dec 2018 12:08:41 -0700 Subject: [PATCH] Define protection level for document manager. Similar to what we've done for services like the installer, verifier, and text classifier, we're creating a new permission protection level for the "document manager" on the device, called the "documenter" in this change. There should be exactly one "documenter" on the device, since it handles the sensitive MANAGE_DOCUMENTS permission. Bug: 117745631 Test: atest CtsPermission2TestCases Test: atest android.permission.cts.ProviderPermissionTest Change-Id: I92c9fcfee24feae8dc3a7516cde093e8f3bf0e56 --- api/system-current.txt | 2 ++ api/test-current.txt | 3 +++ .../content/pm/PackageManagerInternal.java | 2 ++ .../android/content/pm/PermissionInfo.java | 15 ++++++++++++++ core/res/AndroidManifest.xml | 9 ++++----- core/res/res/values/attrs_manifest.xml | 3 +++ .../server/pm/PackageManagerService.java | 20 +++++++++++++++++++ .../server/pm/permission/BasePermission.java | 3 +++ .../permission/PermissionManagerService.java | 7 +++++++ 9 files changed, 59 insertions(+), 5 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 29089b3e908a0..e8b56a9fd6180 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -172,6 +172,7 @@ package android { field public static final java.lang.String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER"; field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION"; field public static final java.lang.String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES"; + field public static final java.lang.String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; field public static final java.lang.String RESET_PASSWORD = "android.permission.RESET_PASSWORD"; field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS"; field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT"; @@ -1354,6 +1355,7 @@ package android.content.pm { public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { field public static final int FLAG_REMOVED = 2; // 0x2 + field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 diff --git a/api/test-current.txt b/api/test-current.txt index 5bedc72444300..d89350b57134e 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -10,6 +10,8 @@ package android { field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS"; field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; + field public static final java.lang.String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; + field public static final java.lang.String WRITE_OBB = "android.permission.WRITE_OBB"; } } @@ -372,6 +374,7 @@ package android.content.pm { } public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000 field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000 diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 43c02228499ec..5db9f506e6e44 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -54,6 +54,7 @@ public abstract class PackageManagerInternal { public static final int PACKAGE_SYSTEM_TEXT_CLASSIFIER = 5; public static final int PACKAGE_PERMISSION_CONTROLLER = 6; public static final int PACKAGE_WELLBEING = 7; + public static final int PACKAGE_DOCUMENTER = 8; @IntDef(value = { PACKAGE_SYSTEM, PACKAGE_SETUP_WIZARD, @@ -63,6 +64,7 @@ public abstract class PackageManagerInternal { PACKAGE_SYSTEM_TEXT_CLASSIFIER, PACKAGE_PERMISSION_CONTROLLER, PACKAGE_WELLBEING, + PACKAGE_DOCUMENTER, }) @Retention(RetentionPolicy.SOURCE) public @interface KnownPackage {} diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index 20997d6c0d119..bb8c92dba71aa 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -192,6 +192,17 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @TestApi public static final int PROTECTION_FLAG_WELLBEING = 0x20000; + /** + * Additional flag for {@link #protectionLevel}, corresponding to the + * {@code documenter} value of {@link android.R.attr#protectionLevel}. + * + * @hide + */ + @SystemApi + @TestApi + public static final int PROTECTION_FLAG_DOCUMENTER = 0x40000; + + /** @hide */ @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { PROTECTION_FLAG_PRIVILEGED, @@ -209,6 +220,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { PROTECTION_FLAG_VENDOR_PRIVILEGED, PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER, PROTECTION_FLAG_WELLBEING, + PROTECTION_FLAG_DOCUMENTER, }) @Retention(RetentionPolicy.SOURCE) public @interface ProtectionFlags {} @@ -401,6 +413,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0) { protLevel += "|wellbeing"; } + if ((level & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0) { + protLevel += "|documenter"; + } return protLevel; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4dedd492fdb3c..cabdd808af663 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -897,7 +897,7 @@ android:protectionLevel="dangerous" android:usageInfoRequired="true" /> - @@ -2087,10 +2087,9 @@

This permission should only be requested by the platform document management app. This permission cannot be granted to third-party apps. -

Protection level: signature --> + android:protectionLevel="signature|documenter" /> + + android:protectionLevel="signature|documenter" /> + + diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 888675c117e1f..0cff0783fb9c4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1302,6 +1302,7 @@ public class PackageManagerService extends IPackageManager.Stub final @Nullable String mStorageManagerPackage; final @Nullable String mSystemTextClassifierPackage; final @Nullable String mWellbeingPackage; + final @Nullable String mDocumenterPackage; final @NonNull String mServicesSystemSharedLibraryPackageName; final @NonNull String mSharedSystemSharedLibraryPackageName; @@ -2792,6 +2793,7 @@ public class PackageManagerService extends IPackageManager.Stub mSystemTextClassifierPackage = getSystemTextClassifierPackageName(); mWellbeingPackage = getWellbeingPackageName(); + mDocumenterPackage = getDocumenterPackageName(); // Now that we know all of the shared libraries, update all clients to have // the correct library paths. @@ -19570,6 +19572,22 @@ public class PackageManagerService extends IPackageManager.Stub return mContext.getString(R.string.config_defaultTextClassifierPackage); } + private @Nullable String getDocumenterPackageName() { + final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + + final List matches = queryIntentActivitiesInternal(intent, null, + MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE + | MATCH_DISABLED_COMPONENTS, + UserHandle.myUserId()); + if (matches.size() == 1) { + return matches.get(0).getComponentInfo().packageName; + } else { + Slog.e(TAG, "There should probably be exactly one documenter; found " + + matches.size() + ": matches=" + matches); + return null; + } + } + @Override public String getWellbeingPackageName() { return mContext.getString(R.string.config_defaultWellbeingPackage); @@ -22733,6 +22751,8 @@ public class PackageManagerService extends IPackageManager.Stub return mRequiredPermissionControllerPackage; case PackageManagerInternal.PACKAGE_WELLBEING: return mWellbeingPackage; + case PackageManagerInternal.PACKAGE_DOCUMENTER: + return mDocumenterPackage; } return null; } diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 996f42b646644..7390d1ef67e74 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -243,6 +243,9 @@ public final class BasePermission { public boolean isWellbeing() { return (protectionLevel & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0; } + public boolean isDocumenter() { + return (protectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0; + } public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) { if (!origPackageName.equals(sourcePackageName)) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index bc3c18d9d49c7..31f5ce47abd96 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1647,6 +1647,13 @@ public class PermissionManagerService { // Special permission granted only to the OEM specified wellbeing app allowed = true; } + if (!allowed && bp.isDocumenter() + && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM))) { + // If this permission is to be granted to the documenter and + // this app is the documenter, then it gets the permission. + allowed = true; + } } return allowed; }