Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 894d001c authored by Jiakai Zhang's avatar Jiakai Zhang
Browse files

Verify `loadingPackageName` on `notifyDexLoad`.

notifyDexLoad is a PM API callable from an app's process. The arguments
are provided by the app and shouldn't be blindly trusted. This change
verifies `loadingPackageName` against calling UID.

Bug: 253570365
Test: Disable AppZygote preloading, start Chrome, and see dex load
  report from both isolated process and non-isolated process being
  accepted (no "Invalid dex load report" warning).
Change-Id: I5d2390ed643f5202b3cdb088795d026dc8fa51df
parent eecb5c7f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -203,6 +203,12 @@ public interface Computer extends PackageDataSnapshot {
    boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid, int userId,
            long flags);
    boolean isCallerSameApp(String packageName, int uid);
    /**
     * Returns true if the package name and the uid represent the same app.
     *
     * @param resolveIsolatedUid if true, resolves an isolated uid into the real uid.
     */
    boolean isCallerSameApp(String packageName, int uid, boolean resolveIsolatedUid);
    boolean isComponentVisibleToInstantApp(@Nullable ComponentName component);
    boolean isComponentVisibleToInstantApp(@Nullable ComponentName component,
            @PackageManager.ComponentType int type);
+8 −0
Original line number Diff line number Diff line
@@ -2209,11 +2209,19 @@ public class ComputerEngine implements Computer {
    }

    public final boolean isCallerSameApp(String packageName, int uid) {
        return isCallerSameApp(packageName, uid, false /* resolveIsolatedUid */);
    }

    @Override
    public final boolean isCallerSameApp(String packageName, int uid, boolean resolveIsolatedUid) {
        if (Process.isSdkSandboxUid(uid)) {
            return (packageName != null
                    && packageName.equals(mService.getSdkSandboxPackageName()));
        }
        AndroidPackage pkg = mPackages.get(packageName);
        if (resolveIsolatedUid && Process.isIsolated(uid)) {
            uid = getIsolatedOwner(uid);
        }
        return pkg != null
                && UserHandle.getAppId(uid) == pkg.getUid();
    }
+19 −14
Original line number Diff line number Diff line
@@ -5242,25 +5242,30 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                Map<String, String> classLoaderContextMap,
                String loaderIsa) {
            int callingUid = Binder.getCallingUid();
            if (PackageManagerService.PLATFORM_PACKAGE_NAME.equals(loadingPackageName)
                    && callingUid != Process.SYSTEM_UID) {

            // TODO(b/254043366): System server should not report its own dex load because there's
            // nothing ART can do with it.

            Computer snapshot = snapshot();

            // System server should be able to report dex load on behalf of other apps. E.g., it
            // could potentially resend the notifications in order to migrate the existing dex load
            // info to ART Service.
            if (!PackageManagerServiceUtils.isSystemOrRoot()
                    && !snapshot.isCallerSameApp(
                            loadingPackageName, callingUid, true /* resolveIsolatedUid */)) {
                Slog.w(PackageManagerService.TAG,
                        "Non System Server process reporting dex loads as system server. uid="
                                + callingUid);
                // Do not record dex loads from processes pretending to be system server.
                // Only the system server should be assigned the package "android", so reject calls
                // that don't satisfy the constraint.
                //
                // notifyDexLoad is a PM API callable from the app process. So in theory, apps could
                // craft calls to this API and pretend to be system server. Doing so poses no
                // particular danger for dex load reporting or later dexopt, however it is a
                // sensible check to do in order to verify the expectations.
                        TextUtils.formatSimple(
                                "Invalid dex load report. loadingPackageName=%s, uid=%d",
                                loadingPackageName, callingUid));
                return;
            }

            // TODO(b/254043366): Call `ArtManagerLocal.notifyDexLoad`.

            int userId = UserHandle.getCallingUserId();
            ApplicationInfo ai = snapshot().getApplicationInfo(loadingPackageName, /*flags*/ 0,
                    userId);
            ApplicationInfo ai =
                    snapshot.getApplicationInfo(loadingPackageName, /*flags*/ 0, userId);
            if (ai == null) {
                Slog.w(PackageManagerService.TAG, "Loading a package that does not exist for the calling user. package="
                        + loadingPackageName + ", user=" + userId);