Merge "Add sys config to handle apexes that are allowed to be updated" into sc-dev
This commit is contained in:
@@ -62,6 +62,8 @@ interface IPackageInstaller {
|
||||
|
||||
void bypassNextStagedInstallerCheck(boolean value);
|
||||
|
||||
void bypassNextAllowedApexUpdateCheck(boolean value);
|
||||
|
||||
void setAllowUnlimitedSilentUpdates(String installerPackageName);
|
||||
void setSilentUpdatesThrottleTime(long throttleTimeInSeconds);
|
||||
}
|
||||
|
||||
@@ -1278,6 +1278,13 @@ public abstract class PackageManager {
|
||||
*/
|
||||
public static final int INSTALL_STAGED = 0x00200000;
|
||||
|
||||
/**
|
||||
* Flag parameter for {@link #installPackage} to indicate that check whether given APEX can be
|
||||
* updated should be disabled for this install.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK = 0x00400000;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = true, value = {
|
||||
DONT_KILL_APP,
|
||||
|
||||
@@ -240,6 +240,7 @@ public class SystemConfig {
|
||||
|
||||
private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
|
||||
private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
|
||||
private final ArraySet<String> mAllowedPartnerApexes = new ArraySet<>();
|
||||
|
||||
/**
|
||||
* Map of system pre-defined, uniquely named actors; keys are namespace,
|
||||
@@ -410,6 +411,10 @@ public class SystemConfig {
|
||||
return mWhitelistedStagedInstallers;
|
||||
}
|
||||
|
||||
public Set<String> getAllowedPartnerApexes() {
|
||||
return mAllowedPartnerApexes;
|
||||
}
|
||||
|
||||
public ArraySet<String> getAppDataIsolationWhitelistedApps() {
|
||||
return mAppDataIsolationWhitelistedApps;
|
||||
}
|
||||
@@ -1212,6 +1217,21 @@ public class SystemConfig {
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
} break;
|
||||
case "allowed-partner-apex": {
|
||||
// TODO(b/189274479): should this be allowOemPermissions instead?
|
||||
if (allowAppConfigs) {
|
||||
String pkgName = parser.getAttributeValue(null, "package");
|
||||
if (pkgName == null) {
|
||||
Slog.w(TAG, "<" + name + "> without package in " + permFile
|
||||
+ " at " + parser.getPositionDescription());
|
||||
} else {
|
||||
mAllowedPartnerApexes.add(pkgName);
|
||||
}
|
||||
} else {
|
||||
logNotAllowedInPartition(name, permFile, parser);
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
} break;
|
||||
default: {
|
||||
Slog.w(TAG, "Tag " + name + " is unknown in "
|
||||
+ permFile + " at " + parser.getPositionDescription());
|
||||
|
||||
@@ -157,6 +157,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
|
||||
private volatile boolean mOkToSendBroadcasts = false;
|
||||
private volatile boolean mBypassNextStagedInstallerCheck = false;
|
||||
private volatile boolean mBypassNextAllowedApexUpdateCheck = false;
|
||||
|
||||
/**
|
||||
* File storing persisted {@link #mSessions} metadata.
|
||||
@@ -650,6 +651,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
throw new IllegalArgumentException(
|
||||
"Non-staged APEX session doesn't support INSTALL_ENABLE_ROLLBACK");
|
||||
}
|
||||
if (isCalledBySystemOrShell(callingUid) || mBypassNextAllowedApexUpdateCheck) {
|
||||
params.installFlags |= PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK;
|
||||
} else {
|
||||
// Only specific APEX updates (installed through ADB, or for CTS tests) can disable
|
||||
// allowed APEX update check.
|
||||
params.installFlags &= ~PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK;
|
||||
}
|
||||
}
|
||||
|
||||
if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0
|
||||
@@ -674,6 +682,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
}
|
||||
|
||||
mBypassNextStagedInstallerCheck = false;
|
||||
mBypassNextAllowedApexUpdateCheck = false;
|
||||
|
||||
if (!params.isMultiPackage) {
|
||||
// Only system components can circumvent runtime permissions when installing.
|
||||
if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
|
||||
@@ -1106,6 +1116,14 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
mBypassNextStagedInstallerCheck = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bypassNextAllowedApexUpdateCheck(boolean value) {
|
||||
if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
|
||||
throw new SecurityException("Caller not allowed to bypass allowed apex update check");
|
||||
}
|
||||
mBypassNextAllowedApexUpdateCheck = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an installer to allow for the unlimited silent updates.
|
||||
*/
|
||||
|
||||
@@ -147,6 +147,7 @@ import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemConfig;
|
||||
import com.android.server.pm.Installer.InstallerException;
|
||||
import com.android.server.pm.dex.DexManager;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
@@ -2238,6 +2239,26 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
.setAdmin(mInstallSource.installerPackageName)
|
||||
.write();
|
||||
}
|
||||
|
||||
// Check if APEX update is allowed. We do this check in handleInstall, since this is one of
|
||||
// the places that:
|
||||
// * Shared between staged and non-staged APEX update flows.
|
||||
// * Only is called after boot completes.
|
||||
// The later is important, since isApexUpdateAllowed check depends on the
|
||||
// ModuleInfoProvider, which is only populated after device has booted.
|
||||
if (isApexSession()) {
|
||||
boolean checkApexUpdateAllowed =
|
||||
(params.installFlags & PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK)
|
||||
== 0;
|
||||
synchronized (mLock) {
|
||||
if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName)) {
|
||||
onSessionValidationFailure(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
|
||||
"Update of APEX package " + mPackageName + " is not allowed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (params.isStaged) {
|
||||
mStagingManager.commitSession(mStagedSession);
|
||||
// TODO(b/136257624): CTS test fails if we don't send session finished broadcast, even
|
||||
@@ -2776,6 +2797,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
return sessionContains((s) -> !s.isApexSession());
|
||||
}
|
||||
|
||||
private boolean isApexUpdateAllowed(String apexPackageName) {
|
||||
return mPm.getModuleInfo(apexPackageName, 0) != null
|
||||
|| SystemConfig.getInstance().getAllowedPartnerApexes().contains(apexPackageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate apex install.
|
||||
* <p>
|
||||
|
||||
@@ -307,6 +307,8 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
return runLogVisibility();
|
||||
case "bypass-staged-installer-check":
|
||||
return runBypassStagedInstallerCheck();
|
||||
case "bypass-allowed-apex-update-check":
|
||||
return runBypassAllowedApexUpdateCheck();
|
||||
case "set-silent-updates-policy":
|
||||
return runSetSilentUpdatesPolicy();
|
||||
default: {
|
||||
@@ -424,6 +426,20 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private int runBypassAllowedApexUpdateCheck() {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
try {
|
||||
mInterface.getPackageInstaller()
|
||||
.bypassNextAllowedApexUpdateCheck(Boolean.parseBoolean(getNextArg()));
|
||||
return 0;
|
||||
} catch (RemoteException e) {
|
||||
pw.println("Failure ["
|
||||
+ e.getClass().getName() + " - "
|
||||
+ e.getMessage() + "]");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private int uninstallSystemUpdates(String packageName) {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
boolean failedUninstalls = false;
|
||||
|
||||
@@ -221,6 +221,64 @@ public class SystemConfigTest {
|
||||
assertThat(mSysConfig.getWhitelistedStagedInstallers()).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that readPermissions works correctly with {@link SystemConfig#ALLOW_APP_CONFIGS}
|
||||
* permission flag for the tag: {@code allowed-partner-apex}.
|
||||
*/
|
||||
@Test
|
||||
public void readPermissions_allowAppConfigs_parsesPartnerApexAllowList()
|
||||
throws IOException {
|
||||
final String contents =
|
||||
"<config>\n"
|
||||
+ " <allowed-partner-apex package=\"com.android.apex1\" />\n"
|
||||
+ "</config>";
|
||||
final File folder = createTempSubfolder("folder");
|
||||
createTempFile(folder, "partner-apex-allowlist.xml", contents);
|
||||
|
||||
mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
|
||||
|
||||
assertThat(mSysConfig.getAllowedPartnerApexes()).containsExactly("com.android.apex1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that readPermissions works correctly with {@link SystemConfig#ALLOW_APP_CONFIGS}
|
||||
* permission flag for the tag: {@code allowed-partner-apex}.
|
||||
*/
|
||||
@Test
|
||||
public void readPermissions_allowAppConfigs_parsesPartnerApexAllowList_noPackage()
|
||||
throws IOException {
|
||||
final String contents =
|
||||
"<config>\n"
|
||||
+ " <allowed-partner-apex/>\n"
|
||||
+ "</config>";
|
||||
final File folder = createTempSubfolder("folder");
|
||||
createTempFile(folder, "partner-apex-allowlist.xml", contents);
|
||||
|
||||
mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
|
||||
|
||||
assertThat(mSysConfig.getAllowedPartnerApexes()).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that readPermissions works correctly without {@link SystemConfig#ALLOW_APP_CONFIGS}
|
||||
* permission flag for the tag: {@code allowed-partner-apex}.
|
||||
*/
|
||||
@Test
|
||||
public void readPermissions_notAllowAppConfigs_doesNotParsePartnerApexAllowList()
|
||||
throws IOException {
|
||||
final String contents =
|
||||
"<config>\n"
|
||||
+ " <allowed-partner-apex package=\"com.android.apex1\" />\n"
|
||||
+ "</config>";
|
||||
final File folder = createTempSubfolder("folder");
|
||||
createTempFile(folder, "partner-apex-allowlist.xml", contents);
|
||||
|
||||
mSysConfig.readPermissions(folder, /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
|
||||
|
||||
assertThat(mSysConfig.getAllowedPartnerApexes()).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user