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

Commit 5ed8537b authored by Alan Stokes's avatar Alan Stokes
Browse files

Add originatingPackageName to InstallSource.

This is mostly useful in cases where an install is done via
PackageInstaller UI so we can tell the real source of the install. We
already pass the originating UID to the verifier, but now we persist
it so it is available to malware scanners etc.

Bug: 134746019
Test: atest CtsPackageInstallTestCases PackageManagerTests
Test: Manual install via PackageInstaller + inspect outputs
Change-Id: I40340ddbc8a2e23a047508e717d48b4b4b686e1f
parent 6f7e2d56
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -119,6 +119,9 @@ message PackageProto {

        // The package that requested the installation of this one.
        optional string initiating_package_name = 1;

        // The package on behalf of which the initiiating package requested the install.
        optional string originating_package_name = 2;
    }

    // Name of package. e.g. "com.android.providers.telephony".
+39 −23
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ package com.android.server.pm;

import android.annotation.Nullable;

import com.android.internal.util.IndentingPrintWriter;

import java.util.Objects;

/**
@@ -31,12 +29,21 @@ final class InstallSource {
     * An instance of InstallSource representing an absence of knowledge of the source of
     * a package. Used in preference to null.
     */
    static final InstallSource EMPTY = new InstallSource(null, null, false);
    static final InstallSource EMPTY = new InstallSource(null, null, null, false);

    /** The package that requested the installation, if known. */
    @Nullable
    final String initiatingPackageName;

    /**
     * The package on behalf of which the initiating package requested the installation, if any.
     * For example if a downloaded APK is installed via the Package Installer this could be the
     * app that performed the download. This value is provided by the initiating package and not
     * verified by the framework.
     */
    @Nullable
    final String originatingPackageName;

    /**
     * Package name of the app that installed this package (the installer of record). Note that
     * this may be modified.
@@ -48,47 +55,49 @@ final class InstallSource {
    final boolean isOrphaned;

    static InstallSource create(@Nullable String initiatingPackageName,
            @Nullable String installerPackageName) {
        return create(initiatingPackageName, installerPackageName, false);
    }
            @Nullable String originatingPackageName, @Nullable String installerPackageName,
            boolean isOrphaned) {

    static InstallSource create(@Nullable String initiatingPackageName,
            @Nullable String installerPackageName, boolean isOrphaned) {
        if (initiatingPackageName == null && installerPackageName == null && !isOrphaned) {
        if (initiatingPackageName == null && originatingPackageName == null
                && installerPackageName == null && !isOrphaned) {
            return EMPTY;
        }
        return new InstallSource(
                initiatingPackageName == null ? null : initiatingPackageName.intern(),
                originatingPackageName == null ? null : originatingPackageName.intern(),
                installerPackageName == null ? null : installerPackageName.intern(),
                isOrphaned);
    }

    private InstallSource(@Nullable String initiatingPackageName,
            @Nullable String installerPackageName, boolean isOrphaned) {
            @Nullable String originatingPackageName, @Nullable String installerPackageName,
            boolean isOrphaned) {
        this.initiatingPackageName = initiatingPackageName;
        this.isOrphaned = isOrphaned;
        this.originatingPackageName = originatingPackageName;
        this.installerPackageName = installerPackageName;
    }

    void dump(IndentingPrintWriter pw) {
        pw.printPair("installerPackageName", installerPackageName);
        pw.printPair("installInitiatingPackageName", initiatingPackageName);
        this.isOrphaned = isOrphaned;
    }

    /**
     * Return an InstallSource the same as this one except with the specified installerPackageName.
     */
    InstallSource setInstallerPackage(String installerPackageName) {
        return Objects.equals(installerPackageName, this.installerPackageName) ? this
                : create(initiatingPackageName, installerPackageName, isOrphaned);
        if (Objects.equals(installerPackageName, this.installerPackageName)) {
            return this;
        }
        return create(initiatingPackageName, originatingPackageName, installerPackageName,
                isOrphaned);
    }

    /**
     * Return an InstallSource the same as this one except with the specified value for isOrphaned.
     */
    InstallSource setIsOrphaned(boolean isOrphaned) {
        return isOrphaned == this.isOrphaned ? this
                : create(initiatingPackageName, installerPackageName, isOrphaned);
        if (isOrphaned == this.isOrphaned) {
            return this;
        }
        return create(initiatingPackageName, originatingPackageName, installerPackageName,
                isOrphaned);
    }

    /**
@@ -102,6 +111,7 @@ final class InstallSource {

        boolean modified = false;
        String initiatingPackageName = this.initiatingPackageName;
        String originatingPackageName = this.originatingPackageName;
        String installerPackageName = this.installerPackageName;
        boolean isOrphaned = this.isOrphaned;

@@ -109,14 +119,20 @@ final class InstallSource {
            initiatingPackageName = null;
            modified = true;
        }
        if (packageName.equals(originatingPackageName)) {
            originatingPackageName = null;
            modified = true;
        }
        if (packageName.equals(installerPackageName)) {
            installerPackageName = null;
            isOrphaned = true;
            modified = true;
        }

        return modified
                ? create(initiatingPackageName, installerPackageName, isOrphaned)
                : this;
        if (!modified) {
            return this;
        }
        return create(initiatingPackageName, originatingPackageName, installerPackageName,
                isOrphaned);
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -512,6 +512,16 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
            }
        }

        String originatingPackageName = null;
        if (params.originatingUid != SessionParams.UID_UNKNOWN
                && params.originatingUid != callingUid) {
            String[] packages = mPm.getPackagesForUid(params.originatingUid);
            if (packages != null && packages.length > 0) {
                // Choose an arbitrary representative package in the case of a shared UID.
                originatingPackageName = packages[0];
            }
        }

        if (Build.IS_DEBUGGABLE || isDowngradeAllowedForCaller(callingUid)) {
            params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
        } else {
@@ -624,7 +634,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
            }
        }
        InstallSource installSource = InstallSource.create(installerPackageName,
                requestedInstallerPackageName);
                originatingPackageName, requestedInstallerPackageName, false);
        session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
                installSource, params, createdMillis,
+11 −3
Original line number Diff line number Diff line
@@ -148,6 +148,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private static final String ATTR_INSTALLER_UID = "installerUid";
    private static final String ATTR_INITIATING_PACKAGE_NAME =
            "installInitiatingPackageName";
    private static final String ATTR_ORIGINATING_PACKAGE_NAME =
            "installOriginatingPackageName";
    private static final String ATTR_CREATED_MILLIS = "createdMillis";
    private static final String ATTR_UPDATED_MILLIS = "updatedMillis";
    private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
@@ -1227,7 +1229,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            }

            mInstallerUid = newOwnerAppInfo.uid;
            mInstallSource = InstallSource.create(packageName, packageName);
            mInstallSource = InstallSource.create(packageName, null, packageName, false);
        }

        // Persist the fact that we've sealed ourselves to prevent
@@ -2336,7 +2338,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

        pw.printPair("userId", userId);
        pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid);
        mInstallSource.dump(pw);
        pw.printPair("installerPackageName", mInstallSource.installerPackageName);
        pw.printPair("installInitiatingPackageName", mInstallSource.initiatingPackageName);
        pw.printPair("installOriginatingPackageName", mInstallSource.originatingPackageName);
        pw.printPair("mInstallerUid", mInstallerUid);
        pw.printPair("createdMillis", createdMillis);
        pw.printPair("updatedMillis", updatedMillis);
@@ -2420,6 +2424,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid);
            writeStringAttribute(out, ATTR_INITIATING_PACKAGE_NAME,
                    mInstallSource.initiatingPackageName);
            writeStringAttribute(out, ATTR_ORIGINATING_PACKAGE_NAME,
                    mInstallSource.originatingPackageName);
            writeLongAttribute(out, ATTR_CREATED_MILLIS, createdMillis);
            writeLongAttribute(out, ATTR_UPDATED_MILLIS, updatedMillis);
            if (stageDir != null) {
@@ -2527,6 +2533,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId));
        final String installInitiatingPackageName =
                readStringAttribute(in, ATTR_INITIATING_PACKAGE_NAME);
        final String installOriginatingPackageName =
                readStringAttribute(in, ATTR_ORIGINATING_PACKAGE_NAME);
        final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
        long updatedMillis = readLongAttribute(in, ATTR_UPDATED_MILLIS);
        final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
@@ -2619,7 +2627,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }

        InstallSource installSource = InstallSource.create(installInitiatingPackageName,
                installerPackageName);
                installOriginatingPackageName, installerPackageName, false);
        return new PackageInstallerSession(callback, context, pm, sessionProvider,
                installerThread, stagingManager, sessionId, userId, installerUid,
                installSource, params, createdMillis, stageDir, stageCid,
+2 −0
Original line number Diff line number Diff line
@@ -209,6 +209,8 @@ public final class PackageSetting extends PackageSettingBase {
            long sourceToken = proto.start(PackageProto.INSTALL_SOURCE);
            proto.write(PackageProto.InstallSourceProto.INITIATING_PACKAGE_NAME,
                    installSource.initiatingPackageName);
            proto.write(PackageProto.InstallSourceProto.ORIGINATING_PACKAGE_NAME,
                    installSource.originatingPackageName);
            proto.end(sourceToken);
        }
        writeUsersInfoToProto(proto, PackageProto.USERS);
Loading