From 18211fd8f6ff4a70a4b8b16fab642783d536102b Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Tue, 6 Jun 2017 09:15:46 -0700 Subject: [PATCH] Passing callingUid to internal methods Sometimes callers want to clear the calling identity [to avoid permission calls]. In this case, allow passing the original calling identity to internal methods. Test: Manual; create profile account and observe launcher still works cross profile Test: bit FrameworksServicesTests:com.android.server.pm.ShortcutManagerTest{1..10} Change-Id: I73f8ad4b2dc1895227c3fcb14f3f1f18f600562f Fixes: 38349978 --- .../content/pm/PackageManagerInternal.java | 46 ++++++-- .../server/am/ActivityManagerService.java | 14 +-- .../server/pm/LauncherAppsService.java | 62 ++++++---- .../server/pm/PackageManagerService.java | 111 +++++++++++++----- 4 files changed, 164 insertions(+), 69 deletions(-) diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 4cee2dfb66cbc..99700df2b990a 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -18,7 +18,11 @@ package android.content.pm; import android.content.ComponentName; import android.content.Intent; +import android.content.pm.PackageManager.ApplicationInfoFlags; +import android.content.pm.PackageManager.ComponentInfoFlags; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.PackageManager.PackageInfoFlags; +import android.content.pm.PackageManager.ResolveInfoFlags; import android.os.Bundle; import android.util.SparseArray; @@ -133,16 +137,40 @@ public abstract class PackageManagerInternal { public abstract boolean isPermissionsReviewRequired(String packageName, int userId); /** - * Gets all of the information we know about a particular package. - * - * @param packageName The package name to find. - * @param userId The user under which to check. - * - * @return An {@link ApplicationInfo} containing information about the - * package, or {@code null} if no application exists with that - * package name. + * Retrieve all of the information we know about a particular package/application. + * @param filterCallingUid The results will be filtered in the context of this UID instead + * of the calling UID. + * @see PackageManager#getPackageInfo(String, int) */ - public abstract ApplicationInfo getApplicationInfo(String packageName, int userId); + public abstract PackageInfo getPackageInfo(String packageName, + @PackageInfoFlags int flags, int filterCallingUid, int userId); + + /** + * Retrieve all of the information we know about a particular package/application. + * @param filterCallingUid The results will be filtered in the context of this UID instead + * of the calling UID. + * @see PackageManager#getApplicationInfo(String, int) + */ + public abstract ApplicationInfo getApplicationInfo(String packageName, + @ApplicationInfoFlags int flags, int filterCallingUid, int userId); + + /** + * Retrieve all of the information we know about a particular activity class. + * @param filterCallingUid The results will be filtered in the context of this UID instead + * of the calling UID. + * @see PackageManager#getActivityInfo(ComponentName, int) + */ + public abstract ActivityInfo getActivityInfo(ComponentName component, + @ComponentInfoFlags int flags, int filterCallingUid, int userId); + + /** + * Retrieve all activities that can be performed for the given intent. + * @param filterCallingUid The results will be filtered in the context of this UID instead + * of the calling UID. + * @see PackageManager#queryIntentActivities(Intent, int) + */ + public abstract List queryIntentActivities(Intent intent, + @ResolveInfoFlags int flags, int filterCallingUid, int userId); /** * Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f3ecfeb404985..c958313c13060 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -19158,10 +19158,11 @@ public class ActivityManagerService extends IActivityManager.Stub final Uri data = intent.getData(); final String ssp; if (data != null && (ssp = data.getSchemeSpecificPart()) != null) { - final ApplicationInfo aInfo = - getPackageManagerInternalLocked().getApplicationInfo( - ssp, - userId); + ApplicationInfo aInfo = null; + try { + aInfo = AppGlobals.getPackageManager() + .getApplicationInfo(ssp, 0 /*flags*/, userId); + } catch (RemoteException ignore) {} if (aInfo == null) { Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:" + " ssp=" + ssp + " data=" + data); @@ -24281,7 +24282,6 @@ public class ActivityManagerService extends IActivityManager.Stub } void updateApplicationInfoLocked(@NonNull List packagesToUpdate, int userId) { - final PackageManagerInternal packageManager = getPackageManagerInternalLocked(); final boolean updateFrameworkRes = packagesToUpdate.contains("android"); for (int i = mLruProcesses.size() - 1; i >= 0; i--) { final ProcessRecord app = mLruProcesses.get(i); @@ -24298,8 +24298,8 @@ public class ActivityManagerService extends IActivityManager.Stub final String packageName = app.pkgList.keyAt(j); if (updateFrameworkRes || packagesToUpdate.contains(packageName)) { try { - final ApplicationInfo ai = packageManager.getApplicationInfo( - packageName, app.userId); + final ApplicationInfo ai = AppGlobals.getPackageManager() + .getApplicationInfo(packageName, 0 /*flags*/, app.userId); if (ai != null) { app.thread.scheduleApplicationInfoChanged(ai); } diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 29f9f7c709bbc..4a5ce1203f152 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -34,6 +34,7 @@ import android.content.pm.IPackageManager; import android.content.pm.LauncherApps.ShortcutQuery; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; @@ -100,7 +101,6 @@ public class LauncherAppsService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "LauncherAppsService"; private final Context mContext; - private final PackageManager mPm; private final UserManager mUm; private final ActivityManagerInternal mActivityManagerInternal; private final ShortcutServiceInternal mShortcutServiceInternal; @@ -113,7 +113,6 @@ public class LauncherAppsService extends SystemService { public LauncherAppsImpl(Context context) { mContext = context; - mPm = mContext.getPackageManager(); mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mActivityManagerInternal = Preconditions.checkNotNull( LocalServices.getService(ActivityManagerInternal.class)); @@ -263,15 +262,17 @@ public class LauncherAppsService extends SystemService { void verifyCallingPackage(String callingPackage) { int packageUid = -1; try { - packageUid = mPm.getPackageUidAsUser(callingPackage, + packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_UNINSTALLED_PACKAGES, UserHandle.getUserId(getCallingUid())); - } catch (NameNotFoundException e) { + } catch (RemoteException ignore) { + } + if (packageUid < 0) { Log.e(TAG, "Package not found: " + callingPackage); } - if (packageUid != Binder.getCallingUid()) { + if (packageUid != injectBinderCallingUid()) { throw new SecurityException("Calling package name mismatch"); } } @@ -315,13 +316,15 @@ public class LauncherAppsService extends SystemService { return null; } + final int callingUid = injectBinderCallingUid(); long ident = Binder.clearCallingIdentity(); try { - IPackageManager pm = AppGlobals.getPackageManager(); - return pm.getActivityInfo(component, + final PackageManagerInternal pmInt = + LocalServices.getService(PackageManagerInternal.class); + return pmInt.getActivityInfo(component, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - user.getIdentifier()); + callingUid, user.getIdentifier()); } finally { Binder.restoreCallingIdentity(ident); } @@ -344,12 +347,15 @@ public class LauncherAppsService extends SystemService { return null; } + final int callingUid = injectBinderCallingUid(); long ident = injectClearCallingIdentity(); try { - List apps = mPm.queryIntentActivitiesAsUser(intent, + final PackageManagerInternal pmInt = + LocalServices.getService(PackageManagerInternal.class); + List apps = pmInt.queryIntentActivities(intent, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - user.getIdentifier()); + callingUid, user.getIdentifier()); return new ParceledListSlice<>(apps); } finally { injectRestoreCallingIdentity(ident); @@ -390,13 +396,15 @@ public class LauncherAppsService extends SystemService { return false; } + final int callingUid = injectBinderCallingUid(); long ident = Binder.clearCallingIdentity(); try { - IPackageManager pm = AppGlobals.getPackageManager(); - PackageInfo info = pm.getPackageInfo(packageName, + final PackageManagerInternal pmInt = + LocalServices.getService(PackageManagerInternal.class); + PackageInfo info = pmInt.getPackageInfo(packageName, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - user.getIdentifier()); + callingUid, user.getIdentifier()); return info != null && info.applicationInfo.enabled; } finally { Binder.restoreCallingIdentity(ident); @@ -414,11 +422,13 @@ public class LauncherAppsService extends SystemService { return null; } + final int callingUid = injectBinderCallingUid(); long ident = Binder.clearCallingIdentity(); try { - IPackageManager pm = AppGlobals.getPackageManager(); - ApplicationInfo info = pm.getApplicationInfo(packageName, flags, - user.getIdentifier()); + final PackageManagerInternal pmInt = + LocalServices.getService(PackageManagerInternal.class); + ApplicationInfo info = pmInt.getApplicationInfo(packageName, flags, + callingUid, user.getIdentifier()); return info; } finally { Binder.restoreCallingIdentity(ident); @@ -573,13 +583,15 @@ public class LauncherAppsService extends SystemService { return false; } + final int callingUid = injectBinderCallingUid(); long ident = Binder.clearCallingIdentity(); try { - IPackageManager pm = AppGlobals.getPackageManager(); - ActivityInfo info = pm.getActivityInfo(component, + final PackageManagerInternal pmInt = + LocalServices.getService(PackageManagerInternal.class); + ActivityInfo info = pmInt.getActivityInfo(component, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - user.getIdentifier()); + callingUid, user.getIdentifier()); return info != null; } finally { Binder.restoreCallingIdentity(ident); @@ -604,13 +616,15 @@ public class LauncherAppsService extends SystemService { | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); launchIntent.setPackage(component.getPackageName()); + final int callingUid = injectBinderCallingUid(); long ident = Binder.clearCallingIdentity(); try { - IPackageManager pm = AppGlobals.getPackageManager(); - ActivityInfo info = pm.getActivityInfo(component, + final PackageManagerInternal pmInt = + LocalServices.getService(PackageManagerInternal.class); + ActivityInfo info = pmInt.getActivityInfo(component, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - user.getIdentifier()); + callingUid, user.getIdentifier()); if (!info.exported) { throw new SecurityException("Cannot launch non-exported components " + component); @@ -619,10 +633,10 @@ public class LauncherAppsService extends SystemService { // Check that the component actually has Intent.CATEGORY_LAUCNCHER // as calling startActivityAsUser ignores the category and just // resolves based on the component if present. - List apps = mPm.queryIntentActivitiesAsUser(launchIntent, + List apps = pmInt.queryIntentActivities(launchIntent, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - user.getIdentifier()); + callingUid, user.getIdentifier()); final int size = apps.size(); for (int i = 0; i < size; ++i) { ActivityInfo activityInfo = apps.get(i).activityInfo; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 47431d45c9637..d19b238fe0719 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3651,22 +3651,27 @@ public class PackageManagerService extends IPackageManager.Stub @Override public PackageInfo getPackageInfo(String packageName, int flags, int userId) { return getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST, - flags, userId); + flags, Binder.getCallingUid(), userId); } @Override public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage, int flags, int userId) { return getPackageInfoInternal(versionedPackage.getPackageName(), - versionedPackage.getVersionCode(), flags, userId); + versionedPackage.getVersionCode(), flags, Binder.getCallingUid(), userId); } + /** + * Important: The provided filterCallingUid is used exclusively to filter out packages + * that can be seen based on user state. It's typically the original caller uid prior + * to clearing. Because it can only be provided by trusted code, it's value can be + * trusted and will be used as-is; unlike userId which will be validated by this method. + */ private PackageInfo getPackageInfoInternal(String packageName, int versionCode, - int flags, int userId) { + int flags, int filterCallingUid, int userId) { if (!sUserManager.exists(userId)) return null; - final int callingUid = Binder.getCallingUid(); flags = updateFlagsForPackage(flags, userId, packageName); - enforceCrossUserPermission(callingUid, userId, + enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission */, false /* checkShell */, "get package info"); // reader @@ -3678,10 +3683,10 @@ public class PackageManagerService extends IPackageManager.Stub if (matchFactoryOnly) { final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName); if (ps != null) { - if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) { + if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) { return null; } - if (filterAppAccessLPr(ps, callingUid, userId)) { + if (filterAppAccessLPr(ps, filterCallingUid, userId)) { return null; } return generatePackageInfo(ps, flags, userId); @@ -3696,10 +3701,10 @@ public class PackageManagerService extends IPackageManager.Stub Log.v(TAG, "getPackageInfo " + packageName + ": " + p); if (p != null) { final PackageSetting ps = (PackageSetting) p.mExtras; - if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) { + if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) { return null; } - if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) { + if (ps != null && filterAppAccessLPr(ps, filterCallingUid, userId)) { return null; } return generatePackageInfo((PackageSetting)p.mExtras, flags, userId); @@ -3707,10 +3712,10 @@ public class PackageManagerService extends IPackageManager.Stub if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null) return null; - if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) { + if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) { return null; } - if (filterAppAccessLPr(ps, callingUid, userId)) { + if (filterAppAccessLPr(ps, filterCallingUid, userId)) { return null; } return generatePackageInfo(ps, flags, userId); @@ -4071,14 +4076,14 @@ public class PackageManagerService extends IPackageManager.Stub } private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags, - int uid, int userId) { + int filterCallingUid, int userId) { if (!sUserManager.exists(userId)) return null; PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { - if (filterSharedLibPackageLPr(ps, uid, userId, flags)) { + if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) { return null; } - if (filterAppAccessLPr(ps, uid, userId)) { + if (filterAppAccessLPr(ps, filterCallingUid, userId)) { return null; } if (ps.pkg == null) { @@ -4101,6 +4106,17 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) { + return getApplicationInfoInternal(packageName, flags, Binder.getCallingUid(), userId); + } + + /** + * Important: The provided filterCallingUid is used exclusively to filter out applications + * that can be seen based on user state. It's typically the original caller uid prior + * to clearing. Because it can only be provided by trusted code, it's value can be + * trusted and will be used as-is; unlike userId which will be validated by this method. + */ + private ApplicationInfo getApplicationInfoInternal(String packageName, int flags, + int filterCallingUid, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForApplication(flags, userId, packageName); enforceCrossUserPermission(Binder.getCallingUid(), userId, @@ -4119,10 +4135,10 @@ public class PackageManagerService extends IPackageManager.Stub if (p != null) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null) return null; - if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) { + if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) { return null; } - if (filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) { + if (filterAppAccessLPr(ps, filterCallingUid, userId)) { return null; } // Note: isEnabledLP() does not apply here - always return info @@ -4140,7 +4156,7 @@ public class PackageManagerService extends IPackageManager.Stub if ((flags & MATCH_KNOWN_PACKAGES) != 0) { // Already generates the external package name return generateApplicationInfoFromSettingsLPw(packageName, - Binder.getCallingUid(), flags, userId); + flags, filterCallingUid, userId); } } return null; @@ -4570,10 +4586,20 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) { + return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId); + } + + /** + * Important: The provided filterCallingUid is used exclusively to filter out activities + * that can be seen based on user state. It's typically the original caller uid prior + * to clearing. Because it can only be provided by trusted code, it's value can be + * trusted and will be used as-is; unlike userId which will be validated by this method. + */ + private ActivityInfo getActivityInfoInternal(ComponentName component, int flags, + int filterCallingUid, int userId) { if (!sUserManager.exists(userId)) return null; - final int callingUid = Binder.getCallingUid(); flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(callingUid, userId, + enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission */, false /* checkShell */, "get activity info"); synchronized (mPackages) { PackageParser.Activity a = mActivities.mActivities.get(component); @@ -4582,7 +4608,7 @@ public class PackageManagerService extends IPackageManager.Stub if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; - if (filterAppAccessLPr(ps, callingUid, component, TYPE_ACTIVITY, userId)) { + if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) { return null; } return generateActivityInfo(a, flags, ps.readUserState(userId), userId); @@ -6303,7 +6329,7 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities"); final List query = queryIntentActivitiesInternal(intent, resolvedType, - flags, userId, resolveForStart); + flags, callingUid, userId, resolveForStart); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); final ResolveInfo bestChoice = @@ -6847,15 +6873,16 @@ public class PackageManagerService extends IPackageManager.Stub private @NonNull List queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, int userId) { - return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false); + return queryIntentActivitiesInternal( + intent, resolvedType, flags, Binder.getCallingUid(), userId, false); } private @NonNull List queryIntentActivitiesInternal(Intent intent, - String resolvedType, int flags, int userId, boolean resolveForStart) { + String resolvedType, int flags, int filterCallingUid, int userId, + boolean resolveForStart) { if (!sUserManager.exists(userId)) return Collections.emptyList(); - final int callingUid = Binder.getCallingUid(); - final String instantAppPkgName = getInstantAppPackageName(callingUid); - enforceCrossUserPermission(callingUid, userId, + final String instantAppPkgName = getInstantAppPackageName(filterCallingUid); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission */, false /* checkShell */, "query intent activities"); final String pkgName = intent.getPackage(); @@ -6867,7 +6894,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart, + flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart, comp != null || pkgName != null /*onlyExposedExplicitly*/); if (comp != null) { final List list = new ArrayList(1); @@ -24409,8 +24436,34 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } @Override - public ApplicationInfo getApplicationInfo(String packageName, int userId) { - return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId); + public PackageInfo getPackageInfo( + String packageName, int flags, int filterCallingUid, int userId) { + return PackageManagerService.this + .getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST, + flags, filterCallingUid, userId); + } + + @Override + public ApplicationInfo getApplicationInfo( + String packageName, int flags, int filterCallingUid, int userId) { + return PackageManagerService.this + .getApplicationInfoInternal(packageName, flags, filterCallingUid, userId); + } + + @Override + public ActivityInfo getActivityInfo( + ComponentName component, int flags, int filterCallingUid, int userId) { + return PackageManagerService.this + .getActivityInfoInternal(component, flags, filterCallingUid, userId); + } + + @Override + public List queryIntentActivities( + Intent intent, int flags, int filterCallingUid, int userId) { + final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver()); + return PackageManagerService.this + .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid, + userId, false /*resolveForStart*/); } @Override