Loading services/core/java/com/android/server/pm/PackageManagerService.java +2 −21 Original line number Diff line number Diff line Loading @@ -14346,27 +14346,8 @@ public class PackageManagerService extends IPackageManager.Stub } if (dataOwnerPkg != null) { // If installed, the package will get access to data left on the device by its // predecessor. As a security measure, this is permited only if this is not a // version downgrade or if the predecessor package is marked as debuggable and // a downgrade is explicitly requested. // // On debuggable platform builds, downgrades are permitted even for // non-debuggable packages to make testing easier. Debuggable platform builds do // not offer security guarantees and thus it's OK to disable some security // mechanisms to make debugging/testing easier on those builds. However, even on // debuggable builds downgrades of packages are permitted only if requested via // installFlags. This is because we aim to keep the behavior of debuggable // platform builds as close as possible to the behavior of non-debuggable // platform builds. final boolean downgradeRequested = (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0; final boolean packageDebuggable = (dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; final boolean downgradePermitted = (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable)); if (!downgradePermitted) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, dataOwnerPkg.applicationInfo.flags)) { try { checkDowngrade(dataOwnerPkg, pkgLite); } catch (PackageManagerException e) { services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +31 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.annotation.Nullable; import android.app.AppGlobals; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageParser; Loading Loading @@ -795,6 +796,36 @@ public class PackageManagerServiceUtils { } } /** * Checks whenever downgrade of an app is permitted. * * @param installFlags flags of the current install. * @param applicationFlags flags of the currently installed version of the app. * @return {@code true} if downgrade is permitted according to the {@code installFlags} and * {@code applicationFlags}. */ public static boolean isDowngradePermitted(int installFlags, int applicationFlags) { // If installed, the package will get access to data left on the device by its // predecessor. As a security measure, this is permited only if this is not a // version downgrade or if the predecessor package is marked as debuggable and // a downgrade is explicitly requested. // // On debuggable platform builds, downgrades are permitted even for // non-debuggable packages to make testing easier. Debuggable platform builds do // not offer security guarantees and thus it's OK to disable some security // mechanisms to make debugging/testing easier on those builds. However, even on // debuggable builds downgrades of packages are permitted only if requested via // installFlags. This is because we aim to keep the behavior of debuggable // platform builds as close as possible to the behavior of non-debuggable // platform builds. final boolean downgradeRequested = (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0; final boolean packageDebuggable = (applicationFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; return (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable)); } /** * Copy package to the target location. * Loading services/core/java/com/android/server/pm/StagingManager.java +30 −4 Original line number Diff line number Diff line Loading @@ -144,12 +144,40 @@ public class StagingManager { private boolean submitSessionToApexService(@NonNull PackageInstallerSession session, List<PackageInstallerSession> childSessions, ApexInfoList apexInfoList) { return mApexManager.submitStagedSession( boolean submittedToApexd = mApexManager.submitStagedSession( session.sessionId, childSessions != null ? childSessions.stream().mapToInt(s -> s.sessionId).toArray() : new int[]{}, apexInfoList); if (!submittedToApexd) { session.setStagedSessionFailed( SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "APEX staging failed, check logcat messages from apexd for more details."); return false; } for (ApexInfo newPackage : apexInfoList.apexInfos) { PackageInfo activePackage = mApexManager.getActivePackage(newPackage.packageName); if (activePackage == null) { continue; } long activeVersion = activePackage.applicationInfo.longVersionCode; boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted( session.params.installFlags, activePackage.applicationInfo.flags); if (activeVersion > newPackage.versionCode && !allowsDowngrade) { session.setStagedSessionFailed( SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "Downgrade of APEX package " + newPackage.packageName + " is not allowed. Active version: " + activeVersion + " attempted: " + newPackage.versionCode); if (!mApexManager.abortActiveSession()) { Slog.e(TAG, "Failed to abort apex session " + session.sessionId); } return false; } } return true; } private static boolean isApexSession(@NonNull PackageInstallerSession session) { Loading Loading @@ -184,9 +212,7 @@ public class StagingManager { } if (!success) { session.setStagedSessionFailed( SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "APEX staging failed, check logcat messages from apexd for more details."); // submitSessionToApexService will populate error. return; } Loading Loading
services/core/java/com/android/server/pm/PackageManagerService.java +2 −21 Original line number Diff line number Diff line Loading @@ -14346,27 +14346,8 @@ public class PackageManagerService extends IPackageManager.Stub } if (dataOwnerPkg != null) { // If installed, the package will get access to data left on the device by its // predecessor. As a security measure, this is permited only if this is not a // version downgrade or if the predecessor package is marked as debuggable and // a downgrade is explicitly requested. // // On debuggable platform builds, downgrades are permitted even for // non-debuggable packages to make testing easier. Debuggable platform builds do // not offer security guarantees and thus it's OK to disable some security // mechanisms to make debugging/testing easier on those builds. However, even on // debuggable builds downgrades of packages are permitted only if requested via // installFlags. This is because we aim to keep the behavior of debuggable // platform builds as close as possible to the behavior of non-debuggable // platform builds. final boolean downgradeRequested = (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0; final boolean packageDebuggable = (dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; final boolean downgradePermitted = (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable)); if (!downgradePermitted) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, dataOwnerPkg.applicationInfo.flags)) { try { checkDowngrade(dataOwnerPkg, pkgLite); } catch (PackageManagerException e) {
services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +31 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.annotation.Nullable; import android.app.AppGlobals; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageParser; Loading Loading @@ -795,6 +796,36 @@ public class PackageManagerServiceUtils { } } /** * Checks whenever downgrade of an app is permitted. * * @param installFlags flags of the current install. * @param applicationFlags flags of the currently installed version of the app. * @return {@code true} if downgrade is permitted according to the {@code installFlags} and * {@code applicationFlags}. */ public static boolean isDowngradePermitted(int installFlags, int applicationFlags) { // If installed, the package will get access to data left on the device by its // predecessor. As a security measure, this is permited only if this is not a // version downgrade or if the predecessor package is marked as debuggable and // a downgrade is explicitly requested. // // On debuggable platform builds, downgrades are permitted even for // non-debuggable packages to make testing easier. Debuggable platform builds do // not offer security guarantees and thus it's OK to disable some security // mechanisms to make debugging/testing easier on those builds. However, even on // debuggable builds downgrades of packages are permitted only if requested via // installFlags. This is because we aim to keep the behavior of debuggable // platform builds as close as possible to the behavior of non-debuggable // platform builds. final boolean downgradeRequested = (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0; final boolean packageDebuggable = (applicationFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; return (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable)); } /** * Copy package to the target location. * Loading
services/core/java/com/android/server/pm/StagingManager.java +30 −4 Original line number Diff line number Diff line Loading @@ -144,12 +144,40 @@ public class StagingManager { private boolean submitSessionToApexService(@NonNull PackageInstallerSession session, List<PackageInstallerSession> childSessions, ApexInfoList apexInfoList) { return mApexManager.submitStagedSession( boolean submittedToApexd = mApexManager.submitStagedSession( session.sessionId, childSessions != null ? childSessions.stream().mapToInt(s -> s.sessionId).toArray() : new int[]{}, apexInfoList); if (!submittedToApexd) { session.setStagedSessionFailed( SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "APEX staging failed, check logcat messages from apexd for more details."); return false; } for (ApexInfo newPackage : apexInfoList.apexInfos) { PackageInfo activePackage = mApexManager.getActivePackage(newPackage.packageName); if (activePackage == null) { continue; } long activeVersion = activePackage.applicationInfo.longVersionCode; boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted( session.params.installFlags, activePackage.applicationInfo.flags); if (activeVersion > newPackage.versionCode && !allowsDowngrade) { session.setStagedSessionFailed( SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "Downgrade of APEX package " + newPackage.packageName + " is not allowed. Active version: " + activeVersion + " attempted: " + newPackage.versionCode); if (!mApexManager.abortActiveSession()) { Slog.e(TAG, "Failed to abort apex session " + session.sessionId); } return false; } } return true; } private static boolean isApexSession(@NonNull PackageInstallerSession session) { Loading Loading @@ -184,9 +212,7 @@ public class StagingManager { } if (!success) { session.setStagedSessionFailed( SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "APEX staging failed, check logcat messages from apexd for more details."); // submitSessionToApexService will populate error. return; } Loading