diff options
| author | 2019-11-06 09:32:49 +0000 | |
|---|---|---|
| committer | 2019-11-12 09:03:07 +0000 | |
| commit | 5ed8537b6600fbcee82755f8bff4b80d8fea96cb (patch) | |
| tree | eed4266f20ed70ed727659145dcea4e7bd13706a | |
| parent | 6f7e2d5674c8fcd44e5421c7915349b5dc59ad7f (diff) | |
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
7 files changed, 76 insertions, 29 deletions
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto index d010c8ff8ad9..004b096496db 100644 --- a/core/proto/android/service/package.proto +++ b/core/proto/android/service/package.proto @@ -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". diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java index 990eba15234e..c7b502636d77 100644 --- a/services/core/java/com/android/server/pm/InstallSource.java +++ b/services/core/java/com/android/server/pm/InstallSource.java @@ -18,8 +18,6 @@ package com.android.server.pm; import android.annotation.Nullable; -import com.android.internal.util.IndentingPrintWriter; - import java.util.Objects; /** @@ -31,13 +29,22 @@ 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); } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index ed2bb3d53649..6564e71936eb 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -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, diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index feb1271d8c79..631df0ff9845 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -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, diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 4fca91a83724..12548918bfcc 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -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); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 66c77f583c57..5f3650c21b8e 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -2848,6 +2848,9 @@ public final class Settings { if (installSource.initiatingPackageName != null) { serializer.attribute(null, "installInitiator", installSource.initiatingPackageName); } + if (installSource.originatingPackageName != null) { + serializer.attribute(null, "installOriginator", installSource.originatingPackageName); + } if (pkg.volumeUuid != null) { serializer.attribute(null, "volumeUuid", pkg.volumeUuid); } @@ -3605,6 +3608,7 @@ public final class Settings { String systemStr = null; String installerPackageName = null; String isOrphaned = null; + String installOriginatingPackageName = null; String installInitiatingPackageName = null; String volumeUuid = null; String categoryHintString = null; @@ -3653,6 +3657,7 @@ public final class Settings { installerPackageName = parser.getAttributeValue(null, "installer"); isOrphaned = parser.getAttributeValue(null, "isOrphaned"); installInitiatingPackageName = parser.getAttributeValue(null, "installInitiator"); + installOriginatingPackageName = parser.getAttributeValue(null, "installOriginator"); volumeUuid = parser.getAttributeValue(null, "volumeUuid"); categoryHintString = parser.getAttributeValue(null, "categoryHint"); if (categoryHintString != null) { @@ -3808,7 +3813,8 @@ public final class Settings { if (packageSetting != null) { packageSetting.uidError = "true".equals(uidError); packageSetting.installSource = InstallSource.create( - installInitiatingPackageName, installerPackageName, "true".equals(isOrphaned)); + installInitiatingPackageName, installOriginatingPackageName, + installerPackageName, "true".equals(isOrphaned)); packageSetting.volumeUuid = volumeUuid; packageSetting.categoryHint = categoryHint; packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr; diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java index 3c1044728fcc..b751308a4bb4 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java @@ -156,6 +156,8 @@ public class PackageInstallerSessionTest { if (isMultiPackage) { params.isMultiPackage = true; } + InstallSource installSource = InstallSource.create("testInstaller", null, "testInstaller", + false); return new PackageInstallerSession( /* callback */ null, /* context */null, @@ -166,7 +168,7 @@ public class PackageInstallerSessionTest { /* sessionId */ sessionId, /* userId */ 456, /* installerUid */ -1, - /* installSource */ InstallSource.create("testInstaller", "testInstaller"), + /* installSource */ installSource, /* sessionParams */ params, /* createdMillis */ 0L, /* stageDir */ mTmpDir, |