Remove the resolved path of session's APK from user confirmation intent
Intent sent to the user for install confirmation includes the resolved path of the session's base apk. A malicious app can modify this path, resulting in the installer activity to show a different app icon and label in the confirmation dialog. To fix this, expose a SystemApi for getting the resolved path and permission protect it with a privileged permission. Bug: 269728874 Test: atest CtsPackageInstallTestCases:SessionTest Change-Id: Ibe7fe3ab5e74e3e910d9f7bd5b6f3f2e3c0ca658
This commit is contained in:
@@ -272,6 +272,7 @@ package android {
|
||||
field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
|
||||
field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
|
||||
field public static final String READ_GLOBAL_APP_SEARCH_DATA = "android.permission.READ_GLOBAL_APP_SEARCH_DATA";
|
||||
field public static final String READ_INSTALLED_SESSION_PATHS = "android.permission.READ_INSTALLED_SESSION_PATHS";
|
||||
field public static final String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
|
||||
field public static final String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
|
||||
field public static final String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
|
||||
@@ -3802,7 +3803,6 @@ package android.content.pm {
|
||||
field public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK";
|
||||
field public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
|
||||
field public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS";
|
||||
field public static final String EXTRA_RESOLVED_BASE_PATH = "android.content.pm.extra.RESOLVED_BASE_PATH";
|
||||
field public static final int LOCATION_DATA_APP = 0; // 0x0
|
||||
field public static final int LOCATION_MEDIA_DATA = 2; // 0x2
|
||||
field public static final int LOCATION_MEDIA_OBB = 1; // 0x1
|
||||
@@ -3839,6 +3839,7 @@ package android.content.pm {
|
||||
method public boolean getInstallAsVirtualPreload();
|
||||
method public int getPendingUserActionReason();
|
||||
method public boolean getRequestDowngrade();
|
||||
method @Nullable @RequiresPermission(android.Manifest.permission.READ_INSTALLED_SESSION_PATHS) public String getResolvedBaseApkPath();
|
||||
method public int getRollbackDataPolicy();
|
||||
method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
|
||||
}
|
||||
|
||||
@@ -333,17 +333,6 @@ public class PackageInstaller {
|
||||
@SystemApi
|
||||
public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE";
|
||||
|
||||
/**
|
||||
* Path to the validated base APK for this session, which may point at an
|
||||
* APK inside the session (when the session defines the base), or it may
|
||||
* point at the existing base APK (when adding splits to an existing app).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final String EXTRA_RESOLVED_BASE_PATH =
|
||||
"android.content.pm.extra.RESOLVED_BASE_PATH";
|
||||
|
||||
/**
|
||||
* Streaming installation pending.
|
||||
* Caller should make sure DataLoader is able to prepare image and reinitiate the operation.
|
||||
@@ -3549,6 +3538,19 @@ public class PackageInstaller {
|
||||
return referrerUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the path to the validated base APK for this session, which may point at an
|
||||
* APK inside the session (when the session defines the base), or it may
|
||||
* point at the existing base APK (when adding splits to an existing app).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.READ_INSTALLED_SESSION_PATHS)
|
||||
public @Nullable String getResolvedBaseApkPath() {
|
||||
return resolvedBaseCodePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
|
||||
*
|
||||
|
||||
@@ -5421,6 +5421,15 @@
|
||||
<permission android:name="android.permission.INSTALL_DPC_PACKAGES"
|
||||
android:protectionLevel="signature|role" />
|
||||
|
||||
<!-- @SystemApi Allows an application to read resolved paths to the APKs (Base and any splits)
|
||||
of a session based install.
|
||||
<p>Not for use by third-party applications.
|
||||
@hide
|
||||
-->
|
||||
<permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS"
|
||||
android:protectionLevel="signature|installer" />
|
||||
<uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
|
||||
|
||||
<!-- Allows an application to use System Data Loaders.
|
||||
<p>Not for use by third-party applications.
|
||||
@hide
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.READ_INSTALL_SESSIONS" />
|
||||
<uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" />
|
||||
<uses-permission android:name="android.permission.USE_RESERVED_DISK" />
|
||||
|
||||
@@ -374,16 +374,15 @@ public class PackageInstallerActivity extends AlertActivity {
|
||||
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
|
||||
-1 /* defaultValue */);
|
||||
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
|
||||
final String resolvedBaseCodePath = intent.getStringExtra(
|
||||
PackageInstaller.EXTRA_RESOLVED_BASE_PATH);
|
||||
if (info == null || !info.isSealed() || resolvedBaseCodePath == null) {
|
||||
String resolvedPath = info.getResolvedBaseApkPath();
|
||||
if (info == null || !info.isSealed() || resolvedPath == null) {
|
||||
Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mSessionId = sessionId;
|
||||
packageSource = Uri.fromFile(new File(resolvedBaseCodePath));
|
||||
packageSource = Uri.fromFile(new File(resolvedPath));
|
||||
mOriginatingURI = null;
|
||||
mReferrerURI = null;
|
||||
mPendingUserActionReason = info.getPendingUserActionReason();
|
||||
|
||||
@@ -830,6 +830,9 @@
|
||||
|
||||
<uses-permission android:name="android.permission.LOG_FOREGROUND_RESOURCE_USE"/>
|
||||
|
||||
<!-- Permission required for CTS test - CtsPackageInstallTestCases -->
|
||||
<uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
|
||||
|
||||
<application android:label="@string/app_label"
|
||||
android:theme="@android:style/Theme.DeviceDefault.DayNight"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
|
||||
@@ -1135,8 +1135,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
info.userId = userId;
|
||||
info.installerPackageName = mInstallSource.mInstallerPackageName;
|
||||
info.installerAttributionTag = mInstallSource.mInstallerAttributionTag;
|
||||
info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
|
||||
mResolvedBaseFile.getAbsolutePath() : null;
|
||||
if (mContext.checkCallingOrSelfPermission(
|
||||
Manifest.permission.READ_INSTALLED_SESSION_PATHS)
|
||||
== PackageManager.PERMISSION_GRANTED && mResolvedBaseFile != null) {
|
||||
info.resolvedBaseCodePath = mResolvedBaseFile.getAbsolutePath();
|
||||
} else {
|
||||
info.resolvedBaseCodePath = null;
|
||||
}
|
||||
info.progress = progress;
|
||||
info.sealed = mSealed;
|
||||
info.isCommitted = isCommitted();
|
||||
@@ -2763,11 +2768,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
: PackageInstaller.ACTION_CONFIRM_INSTALL);
|
||||
intent.setPackage(mPm.getPackageInstallerPackageName());
|
||||
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
|
||||
synchronized (mLock) {
|
||||
intent.putExtra(PackageInstaller.EXTRA_RESOLVED_BASE_PATH,
|
||||
mResolvedBaseFile != null ? mResolvedBaseFile.getAbsolutePath() : null);
|
||||
}
|
||||
|
||||
sendOnUserActionRequired(mContext, target, sessionId, intent);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user