diff options
author | Svetoslav <svetoslavganov@google.com> | 2015-07-06 18:31:23 -0700 |
---|---|---|
committer | Svetoslav <svetoslavganov@google.com> | 2015-07-07 14:02:51 -0700 |
commit | 3e7d977ff7c743713f0ad6336a039d7760ba47d1 (patch) | |
tree | 78c832f2bf7fde55fd89dcfcebf19db74e7e6ac1 | |
parent | 79d9219c9f9734025837a01a6f8e490d1e0ab57e (diff) | |
download | frameworks_base-3e7d977ff7c743713f0ad6336a039d7760ba47d1.zip frameworks_base-3e7d977ff7c743713f0ad6336a039d7760ba47d1.tar.gz frameworks_base-3e7d977ff7c743713f0ad6336a039d7760ba47d1.tar.bz2 |
Grant installer and verifier install permissions robustly
bug:22248271
Change-Id: I3a47ae9a112ba7d88b421fcb5f9651d1168ba7a5
-rw-r--r-- | api/current.txt | 4 | ||||
-rw-r--r-- | api/system-current.txt | 4 | ||||
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 5 | ||||
-rw-r--r-- | core/java/android/content/pm/PermissionInfo.java | 16 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 10 | ||||
-rw-r--r-- | core/res/res/values/attrs_manifest.xml | 6 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java | 124 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 49 |
8 files changed, 100 insertions, 118 deletions
diff --git a/api/current.txt b/api/current.txt index bb1070d..00477cd 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9465,10 +9465,12 @@ package android.content.pm { field public static final int PROTECTION_DANGEROUS = 1; // 0x1 field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40 field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20 + field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100 field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80 field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10 + field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200 field public static final int PROTECTION_MASK_BASE = 15; // 0xf - field public static final int PROTECTION_MASK_FLAGS = 240; // 0xf0 + field public static final int PROTECTION_MASK_FLAGS = 4080; // 0xff0 field public static final int PROTECTION_NORMAL = 0; // 0x0 field public static final int PROTECTION_SIGNATURE = 2; // 0x2 field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3 diff --git a/api/system-current.txt b/api/system-current.txt index 5861560..f0253bf 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -9800,10 +9800,12 @@ package android.content.pm { field public static final int PROTECTION_DANGEROUS = 1; // 0x1 field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40 field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20 + field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100 field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80 field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10 + field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200 field public static final int PROTECTION_MASK_BASE = 15; // 0xf - field public static final int PROTECTION_MASK_FLAGS = 240; // 0xf0 + field public static final int PROTECTION_MASK_FLAGS = 4080; // 0xff0 field public static final int PROTECTION_NORMAL = 0; // 0x0 field public static final int PROTECTION_SIGNATURE = 2; // 0x2 field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3 diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index ca6c6ca..844900d 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -74,6 +74,8 @@ import java.util.List; public class Am extends BaseCommand { + private static final String SHELL_PACKAGE_NAME = "com.android.shell"; + private IActivityManager mAm; private int mStartFlags = 0; @@ -767,7 +769,8 @@ public class Am extends BaseCommand { return; } System.out.println("Starting service: " + intent); - ComponentName cn = mAm.startService(null, intent, intent.getType(), null, mUserId); + ComponentName cn = mAm.startService(null, intent, intent.getType(), + SHELL_PACKAGE_NAME, mUserId); if (cn == null) { System.err.println("Error: Not found; no service started."); } else if (cn.getPackageName().equals("!")) { diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index 0a1f148..1857ecf 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -83,6 +83,20 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { public static final int PROTECTION_FLAG_PRE23 = 0x80; /** + * Additional flag for {@link #protectionLevel}, corresponding + * to the <code>installer</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_FLAG_INSTALLER = 0x100; + + /** + * Additional flag for {@link #protectionLevel}, corresponding + * to the <code>verifier</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_FLAG_VERIFIER = 0x200; + + /** * Mask for {@link #protectionLevel}: the basic protection type. */ public static final int PROTECTION_MASK_BASE = 0xf; @@ -90,7 +104,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { /** * Mask for {@link #protectionLevel}: additional flag bits. */ - public static final int PROTECTION_MASK_FLAGS = 0xf0; + public static final int PROTECTION_MASK_FLAGS = 0xff0; /** * The level of access this permission is protecting, as per diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 8c868c9..e18e44c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1327,7 +1327,7 @@ that removes restrictions on where broadcasts can be sent and allows other types of interactions. --> <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" - android:protectionLevel="signature" /> + android:protectionLevel="signature|installer" /> <!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage users on the device. This permission is not available to @@ -1769,7 +1769,7 @@ <!-- @SystemApi Allows an application to update application operation statistics. Not for use by third party apps. @hide --> <permission android:name="android.permission.UPDATE_APP_OPS_STATS" - android:protectionLevel="signature|system" /> + android:protectionLevel="signature|system|installer" /> <!-- @SystemApi Allows an application to open windows that are for use by parts of the system user interface. @@ -2016,7 +2016,7 @@ @hide --> <permission android:name="android.permission.CLEAR_APP_USER_DATA" - android:protectionLevel="signature" /> + android:protectionLevel="signature|installer" /> <!-- @SystemApi Allows an application to delete cache files. <p>Not for use by third-party applications. --> @@ -2041,7 +2041,7 @@ <!-- @hide Allows an application to grant or revoke specific permissions. --> <permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS" - android:protectionLevel="signature" /> + android:protectionLevel="signature|installer" /> <!-- @hide Allows an application to observe permission changes. --> <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" @@ -2552,7 +2552,7 @@ <p>Not for use by third-party applications. @hide --> <permission android:name="android.permission.KILL_UID" - android:protectionLevel="signature" /> + android:protectionLevel="signature|installer" /> <!-- Allows applications to act as network scorers. @hide @SystemApi--> <permission android:name="android.permission.LOCAL_MAC_ADDRESS" diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 70f9db9..c501329 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -220,6 +220,12 @@ {@link android.os.Build.VERSION_CODES#MNC} (before runtime permissions were introduced). --> <flag name="pre23" value="0x80" /> + <!-- Additional flag from base permission type: this permission can be automatically + granted to system apps that install packages. --> + <flag name="installer" value="0x100" /> + <!-- Additional flag from base permission type: this permission can be automatically + granted to system apps that verify packages. --> + <flag name="verifier" value="0x200" /> </attr> <!-- Flags indicating more context for a permission group. --> diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index 453f123..b10894f 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -54,7 +54,6 @@ final class DefaultPermissionGrantPolicy { private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars private static final boolean DEBUG = false; - private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; private static final String AUDIO_MIME_TYPE = "audio/mpeg"; private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>(); @@ -127,19 +126,6 @@ final class DefaultPermissionGrantPolicy { SETTINGS_PERMISSIONS.add(Manifest.permission.WRITE_SETTINGS); } - private static final Set<String> INSTALLER_PERMISSIONS = new ArraySet<>(); - static { - INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS); - INSTALLER_PERMISSIONS.add(Manifest.permission.INTERACT_ACROSS_USERS_FULL); - INSTALLER_PERMISSIONS.add(Manifest.permission.CLEAR_APP_USER_DATA); - INSTALLER_PERMISSIONS.add(Manifest.permission.KILL_UID); - } - - private static final Set<String> VERIFIER_PERMISSIONS = new ArraySet<>(); - static { - INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS); - } - private final PackageManagerService mService; private PackagesProvider mImePackagesProvider; @@ -250,30 +236,20 @@ final class DefaultPermissionGrantPolicy { syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null; synchronized (mService.mPackages) { - // Installers - Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE); - installerIntent.addCategory(Intent.CATEGORY_DEFAULT); - installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), - PACKAGE_MIME_TYPE); - List<PackageParser.Package> installerPackages = - getPrivilegedHandlerActivityPackagesLPr(installerIntent, userId); - final int installerCount = installerPackages.size(); - for (int i = 0; i < installerCount; i++) { - PackageParser.Package installPackage = installerPackages.get(i); - grantInstallPermissionsLPw(installPackage, INSTALLER_PERMISSIONS, userId); - grantRuntimePermissionsLPw(installPackage, STORAGE_PERMISSIONS, true, userId); - } - - // Verifiers - Intent verifierIntent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); - verifierIntent.setType(PACKAGE_MIME_TYPE); - List<PackageParser.Package> verifierPackages = - getPrivilegedHandlerReceiverPackagesLPr(verifierIntent, userId); - final int verifierCount = verifierPackages.size(); - for (int i = 0; i < verifierCount; i++) { - PackageParser.Package verifierPackage = verifierPackages.get(i); - grantInstallPermissionsLPw(verifierPackage, VERIFIER_PERMISSIONS, userId); - grantRuntimePermissionsLPw(verifierPackage, STORAGE_PERMISSIONS, userId); + // Installer + PackageParser.Package installerPackage = getSystemPackageLPr( + mService.mRequiredInstallerPackage); + if (installerPackage != null + && doesPackageSupportRuntimePermissions(installerPackage)) { + grantRuntimePermissionsLPw(installerPackage, STORAGE_PERMISSIONS, true, userId); + } + + // Verifier + PackageParser.Package verifierPackage = getSystemPackageLPr( + mService.mRequiredVerifierPackage); + if (verifierPackage != null + && doesPackageSupportRuntimePermissions(verifierPackage)) { + grantRuntimePermissionsLPw(verifierPackage, STORAGE_PERMISSIONS, true, userId); } // SetupWizard @@ -636,39 +612,10 @@ final class DefaultPermissionGrantPolicy { } } - private List<PackageParser.Package> getPrivilegedHandlerReceiverPackagesLPr( - Intent intent, int userId) { - List<ResolveInfo> handlers = mService.queryIntentReceivers( - intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()), - 0, userId); - return getPrivilegedPackages(handlers); - } - - private List<PackageParser.Package> getPrivilegedHandlerActivityPackagesLPr( - Intent intent, int userId) { - List<ResolveInfo> handlers = mService.queryIntentActivities( - intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()), - 0, userId); - return getPrivilegedPackages(handlers); - } - - private List<PackageParser.Package> getPrivilegedPackages(List<ResolveInfo> resolveInfos) { - List<PackageParser.Package> handlerPackages = new ArrayList<>(); - final int handlerCount = resolveInfos.size(); - for (int i = 0; i < handlerCount; i++) { - ResolveInfo handler = resolveInfos.get(i); - PackageParser.Package handlerPackage = getPrivilegedPackageLPr( - handler.activityInfo.packageName); - if (handlerPackage != null) { - handlerPackages.add(handlerPackage); - } - } - return handlerPackages; - } - private PackageParser.Package getDefaultSystemHandlerActivityPackageLPr( Intent intent, int userId) { - List<ResolveInfo> handlers = mService.queryIntentActivities(intent, null, 0, userId); + List<ResolveInfo> handlers = mService.queryIntentActivities(intent, + intent.resolveType(mService.mContext.getContentResolver()), 0, userId); final int handlerCount = handlers.size(); for (int i = 0; i < handlerCount; i++) { ResolveInfo handler = handlers.get(i); @@ -728,18 +675,9 @@ final class DefaultPermissionGrantPolicy { return null; } - private PackageParser.Package getPrivilegedPackageLPr(String packageName) { - PackageParser.Package pkg = mService.mPackages.get(packageName); - if (pkg != null && pkg.applicationInfo.isPrivilegedApp()) { - return !isSysComponentOrPersistentPrivApp(pkg) ? pkg : null; - } - return null; - } - private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions, int userId) { grantRuntimePermissionsLPw(pkg, permissions, false, userId); - } private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions, @@ -781,36 +719,6 @@ final class DefaultPermissionGrantPolicy { } } - private void grantInstallPermissionsLPw(PackageParser.Package pkg, Set<String> permissions, - int userId) { - List<String> requestedPermissions = pkg.requestedPermissions; - - if (pkg.isUpdatedSystemApp()) { - PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName); - if (sysPs != null) { - requestedPermissions = sysPs.pkg.requestedPermissions; - } - } - - final int permissionCount = requestedPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - String permission = requestedPermissions.get(i); - if (permissions.contains(permission)) { - final int flags = mService.getPermissionFlags(permission, pkg.packageName, userId); - - // If any flags are set to the permission, then it is either set in - // its current state by the system or device/profile owner or the user. - // In all these cases we do not want to clobber the current state. - if (flags == 0) { - mService.grantInstallPermissionLPw(permission, pkg); - if (DEBUG) { - Log.i(TAG, "Granted install " + permission + " to " + pkg.packageName); - } - } - } - } - } - private static boolean isSysComponentOrPersistentPrivApp(PackageParser.Package pkg) { return UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID || ((pkg.applicationInfo.privateFlags diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0240dbb..5e0d3d8 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -928,7 +928,8 @@ public class PackageManagerService extends IPackageManager.Stub { private static final String TAG_DEFAULT_APPS = "da"; private static final String TAG_INTENT_FILTER_VERIFICATION = "iv"; - private final String mRequiredVerifierPackage; + final String mRequiredVerifierPackage; + final String mRequiredInstallerPackage; private final PackageUsage mPackageUsage = new PackageUsage(); @@ -2262,6 +2263,7 @@ public class PackageManagerService extends IPackageManager.Stub { SystemClock.uptimeMillis()); mRequiredVerifierPackage = getRequiredVerifierLPr(); + mRequiredInstallerPackage = getRequiredInstallerLPr(); mInstallerService = new PackageInstallerService(context, this); @@ -2328,6 +2330,39 @@ public class PackageManagerService extends IPackageManager.Stub { return requiredVerifier; } + private String getRequiredInstallerLPr() { + Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE); + installerIntent.addCategory(Intent.CATEGORY_DEFAULT); + installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); + + final List<ResolveInfo> installers = queryIntentActivities(installerIntent, + PACKAGE_MIME_TYPE, 0, 0); + + String requiredInstaller = null; + + final int N = installers.size(); + for (int i = 0; i < N; i++) { + final ResolveInfo info = installers.get(i); + final String packageName = info.activityInfo.packageName; + + if (!info.activityInfo.applicationInfo.isSystemApp()) { + continue; + } + + if (requiredInstaller != null) { + throw new RuntimeException("There must be one required installer"); + } + + requiredInstaller = packageName; + } + + if (requiredInstaller == null) { + throw new RuntimeException("There must be one required installer"); + } + + return requiredInstaller; + } + private ComponentName getIntentFilterVerifierComponentNameLPr() { final Intent verification = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION); final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE, @@ -8428,6 +8463,18 @@ public class PackageManagerService extends IPackageManager.Stub { // we still want to blindly grant it to old apps. allowed = true; } + if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0 + && pkg.packageName.equals(mRequiredInstallerPackage)) { + // 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.protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0 + && pkg.packageName.equals(mRequiredVerifierPackage)) { + // 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.protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) { // For development permissions, a development permission |