From 2a90f673f5819e05ea72f6aba3e75956e0f807dc Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 6 Jan 2016 12:26:11 -0700 Subject: [PATCH] Update logic for resolving verifiers. Verifiers or installers may not be encryption-aware, or the user may have disabled them, so we probe pretty deeply during system boot to resolve them. Use the new MATCH_SYSTEM_ONLY flag to limit results to packages on the system image. When there are multiple matches, pick the one with highest priority instead of crashing the system. Switch to updated MATCH_ constants in more places. Bug: 26250295 Change-Id: Ia7a3b1fb74da6c3b9d2c2edbf1deaa9fb52fc40a --- core/java/android/content/pm/ResolveInfo.java | 3 +- .../server/pm/PackageManagerService.java | 198 ++++++------------ .../java/com/android/server/pm/Settings.java | 85 ++++---- 3 files changed, 115 insertions(+), 171 deletions(-) diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index d5d300760c8a6..c9be6edab424c 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -172,7 +172,8 @@ public class ResolveInfo implements Parcelable { */ public boolean handleAllWebDataURI; - private ComponentInfo getComponentInfo() { + /** {@hide} */ + public ComponentInfo getComponentInfo() { if (activityInfo != null) return activityInfo; if (serviceInfo != null) return serviceInfo; if (providerInfo != null) return providerInfo; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7e186a0da0ee6..324eaccc813f4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -59,6 +59,10 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; import static android.content.pm.PackageManager.MATCH_ALL; +import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; +import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE; +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; +import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST; import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING; @@ -88,6 +92,8 @@ import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCES import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED; import android.Manifest; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AppGlobals; @@ -2426,113 +2432,60 @@ public class PackageManagerService extends IPackageManager.Stub { return mIsUpgrade; } - private String getRequiredVerifierLPr() { - final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); - // We only care about verifier that's installed under system user. - final List receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE, - PackageManager.GET_DISABLED_COMPONENTS, UserHandle.USER_SYSTEM); + private @NonNull String getRequiredVerifierLPr() { + final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); - String requiredVerifier = null; - - final int N = receivers.size(); - for (int i = 0; i < N; i++) { - final ResolveInfo info = receivers.get(i); - - if (info.activityInfo == null) { - continue; - } - - final String packageName = info.activityInfo.packageName; - - if (checkPermission(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, - packageName, UserHandle.USER_SYSTEM) != PackageManager.PERMISSION_GRANTED) { - continue; - } - - if (requiredVerifier != null) { - throw new RuntimeException("There can be only one required verifier"); - } - - requiredVerifier = packageName; + final List matches = queryIntentReceivers(intent, PACKAGE_MIME_TYPE, + MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM); + if (matches.size() == 1) { + return matches.get(0).getComponentInfo().packageName; + } else { + throw new RuntimeException("There must be exactly one verifier; found " + matches); } - - 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); + private @NonNull String getRequiredInstallerLPr() { + final Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); - final List installers = queryIntentActivities(installerIntent, - PACKAGE_MIME_TYPE, 0, UserHandle.USER_SYSTEM); - - 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; + final List matches = queryIntentActivities(intent, PACKAGE_MIME_TYPE, + MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM); + if (matches.size() == 1) { + return matches.get(0).getComponentInfo().packageName; + } else { + throw new RuntimeException("There must be exactly one installer; found " + matches); } - - 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 receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE, - PackageManager.GET_DISABLED_COMPONENTS, UserHandle.USER_SYSTEM); + private @NonNull ComponentName getIntentFilterVerifierComponentNameLPr() { + final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION); - ComponentName verifierComponentName = null; - - int priority = -1000; - final int N = receivers.size(); + final List matches = queryIntentReceivers(intent, PACKAGE_MIME_TYPE, + MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM); + ResolveInfo best = null; + final int N = matches.size(); for (int i = 0; i < N; i++) { - final ResolveInfo info = receivers.get(i); - - if (info.activityInfo == null) { - continue; - } - - final String packageName = info.activityInfo.packageName; - - final PackageSetting ps = mSettings.mPackages.get(packageName); - if (ps == null) { - continue; - } - + final ResolveInfo cur = matches.get(i); + final String packageName = cur.getComponentInfo().packageName; if (checkPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT, packageName, UserHandle.USER_SYSTEM) != PackageManager.PERMISSION_GRANTED) { continue; } - // Select the IntentFilterVerifier with the highest priority - if (priority < info.priority) { - priority = info.priority; - verifierComponentName = new ComponentName(packageName, info.activityInfo.name); - if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Selecting IntentFilterVerifier: " - + verifierComponentName + " with priority: " + info.priority); + if (best == null || cur.priority > best.priority) { + best = cur; } } - return verifierComponentName; + if (best != null) { + return best.getComponentInfo().getComponentName(); + } else { + throw new RuntimeException("There must be at least one intent filter verifier"); + } } - private ComponentName getEphemeralResolverLPr() { + private @Nullable ComponentName getEphemeralResolverLPr() { final String[] packageArray = mContext.getResources().getStringArray(R.array.config_ephemeralResolverPackage); if (packageArray.length == 0) { @@ -2542,9 +2495,9 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } - Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE); - final List resolvers = queryIntentServices(resolverIntent, - null /*resolvedType*/, 0 /*flags*/, UserHandle.USER_SYSTEM); + final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE); + final List resolvers = queryIntentServices(resolverIntent, null, + MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM); final int N = resolvers.size(); if (N == 0) { @@ -2583,36 +2536,21 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } - private ComponentName getEphemeralInstallerLPr() { - Intent installerIntent = new Intent(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE); - installerIntent.addCategory(Intent.CATEGORY_DEFAULT); - installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); - final List installers = queryIntentActivities(installerIntent, - PACKAGE_MIME_TYPE, 0 /*flags*/, 0 /*userId*/); + private @Nullable ComponentName getEphemeralInstallerLPr() { + final Intent intent = new Intent(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); - ComponentName ephemeralInstaller = 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()) { - if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Ephemeral installer is not system app;" - + " pkg: " + packageName + ", info:" + info); - } - continue; - } - - if (ephemeralInstaller != null) { - throw new RuntimeException("There must only be one ephemeral installer"); - } - - ephemeralInstaller = new ComponentName(packageName, info.activityInfo.name); + final List matches = queryIntentActivities(intent, PACKAGE_MIME_TYPE, + MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM); + if (matches.size() == 0) { + return null; + } else if (matches.size() == 1) { + return matches.get(0).getComponentInfo().getComponentName(); + } else { + throw new RuntimeException( + "There must be at most one ephemeral installer; found " + matches); } - - return ephemeralInstaller; } private void primeDomainVerificationsLPw(int userId) { @@ -2857,7 +2795,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (p != null) { return generatePackageInfo(p, flags, userId); } - if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { + if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) { return generatePackageInfoFromSettingsLPw(packageName, flags, userId); } } @@ -2907,7 +2845,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (p != null) { return UserHandle.getUid(userId, p.applicationInfo.uid); } - if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { + if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { return UserHandle.getUid(userId, ps.appId); @@ -2937,7 +2875,7 @@ public class PackageManagerService extends IPackageManager.Stub { PackageSetting ps = (PackageSetting) p.mExtras; return ps.getPermissionsState().computeGids(userId); } - if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { + if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { return ps.getPermissionsState().computeGids(userId); @@ -3045,7 +2983,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (ps != null) { PackageParser.Package pkg = ps.pkg; if (pkg == null) { - if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) { + if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0) { return null; } // Only data remains, so we aren't worried about code paths @@ -3084,7 +3022,7 @@ public class PackageManagerService extends IPackageManager.Stub { if ("android".equals(packageName)||"system".equals(packageName)) { return mAndroidApplication; } - if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { + if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) { return generateApplicationInfoFromSettingsLPw(packageName, flags, userId); } } @@ -4688,7 +4626,7 @@ public class PackageManagerService extends IPackageManager.Stub { ppa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); } final ActivityInfo ai = getActivityInfo(ppa.mComponent, - flags | PackageManager.GET_DISABLED_COMPONENTS, userId); + flags | MATCH_DISABLED_COMPONENTS, userId); if (DEBUG_PREFERRED || debug) { Slog.v(TAG, "Found persistent preferred activity:"); if (ai != null) { @@ -4797,7 +4735,7 @@ public class PackageManagerService extends IPackageManager.Stub { continue; } final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, - flags | PackageManager.GET_DISABLED_COMPONENTS, userId); + flags | MATCH_DISABLED_COMPONENTS, userId); if (DEBUG_PREFERRED || debug) { Slog.v(TAG, "Found preferred activity:"); if (ai != null) { @@ -5713,7 +5651,7 @@ public class PackageManagerService extends IPackageManager.Stub { public ParceledListSlice getInstalledPackages(int flags, int userId) { if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList(); flags = updateFlagsForPackage(flags, userId, null); - final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; + final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0; enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "get installed packages"); // writer @@ -5794,7 +5732,7 @@ public class PackageManagerService extends IPackageManager.Stub { String[] permissions, int flags, int userId) { if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList(); flags = updateFlagsForPackage(flags, userId, permissions); - final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; + final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0; // writer synchronized (mPackages) { @@ -5822,7 +5760,7 @@ public class PackageManagerService extends IPackageManager.Stub { public ParceledListSlice getInstalledApplications(int flags, int userId) { if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList(); flags = updateFlagsForApplication(flags, userId, null); - final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; + final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0; // writer synchronized (mPackages) { @@ -11263,9 +11201,9 @@ public class PackageManagerService extends IPackageManager.Stub { PACKAGE_MIME_TYPE); verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + // Query all live verifiers based on current user state final List receivers = queryIntentReceivers(verification, - PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS, - verifierUser.getIdentifier()); + PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier()); if (DEBUG_VERIFY) { Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent " diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index b33013995350e..0666d6bba4871 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -16,23 +16,42 @@ package com.android.server.pm; +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; -import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; -import static android.os.Process.SYSTEM_UID; +import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; +import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; +import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; +import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE; +import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE; +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.os.Process.PACKAGE_INFO_GID; +import static android.os.Process.SYSTEM_UID; + import static com.android.server.pm.PackageManagerService.DEBUG_DOMAIN_VERIFICATION; import android.annotation.NonNull; +import android.content.ComponentName; +import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ComponentInfo; import android.content.pm.IntentFilterVerificationInfo; +import android.content.pm.PackageCleanItem; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.PackageUserState; +import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; +import android.content.pm.Signature; +import android.content.pm.UserInfo; +import android.content.pm.VerifierDeviceIdentity; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -47,11 +66,18 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; -import android.util.AtomicFile; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.AtomicFile; +import android.util.Log; import android.util.LogPrinter; +import android.util.Slog; +import android.util.SparseArray; import android.util.SparseBooleanArray; +import android.util.SparseIntArray; import android.util.SparseLongArray; +import android.util.Xml; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BackgroundThread; @@ -65,58 +91,37 @@ import com.android.server.backup.PreferredActivityBackupHelper; import com.android.server.pm.PackageManagerService.DumpState; import com.android.server.pm.PermissionsState.PermissionState; -import java.io.BufferedInputStream; -import java.io.BufferedWriter; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.nio.charset.Charset; -import java.util.Collection; +import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; -import android.content.ComponentName; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.ComponentInfo; -import android.content.pm.PackageCleanItem; -import android.content.pm.PackageManager; -import android.content.pm.PackageParser; -import android.content.pm.PermissionInfo; -import android.content.pm.Signature; -import android.content.pm.UserInfo; -import android.content.pm.PackageUserState; -import android.content.pm.VerifierDeviceIdentity; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Log; -import android.util.Slog; -import android.util.SparseArray; -import android.util.SparseIntArray; -import android.util.Xml; - +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Set; -import java.util.Map.Entry; - -import libcore.io.IoUtils; /** * Holds information about dynamic settings. @@ -2857,7 +2862,7 @@ final class Settings { for (int i=0; i