UserSystemPackageInstaller: Implicit System Mode

Previously, to ease local development, the SYSTEM user was always
implicitly whitelisted (meaning that, if the system package whitelist
didn't have an entry for a particular system package, it would *always*
be implicitly whitelisted on user 0). Here, we turn this into a
optional mode (implicitWhitelistSystemMode) set in config.xml.

Test: atest UserSystemPackageInstallerTest
Bug: 134605778
Fixes: 145611545
Change-Id: I5cf8eaa31969bafc4c3bbe15ecd7bd36f3a87384
This commit is contained in:
Bookatz
2019-12-17 12:30:20 -08:00
parent da587dc1ac
commit eac923e30c
3 changed files with 76 additions and 65 deletions

View File

@@ -2357,15 +2357,22 @@
<!-- Whether to only install system packages on a user if they're whitelisted for that user
type. These are flags and can be freely combined.
0 (0b000) - disable whitelist (install all system packages; no logging)
1 (0b001) - enforce (only install system packages if they are whitelisted)
2 (0b010) - log (log when a non-whitelisted package is run)
4 (0b100) - treat any package not mentioned in the whitelist file as implicitly whitelisted
8 (0b1000) - ignore OTAs (don't install system packages during OTAs)
0 - disable whitelist (install all system packages; no logging)
1 - enforce (only install system packages if they are whitelisted)
2 - log (log when a non-whitelisted package is run)
4 - any package not mentioned in the whitelist file is implicitly whitelisted on all users
8 - same as 4, but just for the SYSTEM user
16 - ignore OTAs (don't install system packages during OTAs)
Common scenarios:
- to enable feature (fully enforced) for a complete whitelist: 1
- to enable feature for an incomplete whitelist (so use implicit whitelist mode): 5
- to enable feature but implicitly whitelist for SYSTEM user to ease local development: 9
- to disable feature completely if it had never been enabled: 16
- to henceforth disable feature and try to undo its previous effects: 0
Note: This list must be kept current with PACKAGE_WHITELIST_MODE_PROP in
frameworks/base/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java -->
<integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 0b1101 -->
<!-- TODO(b/143200798): Change to value 5, i.e. 0b0101, when b/143200798 is resolved. -->
<integer name="config_userTypePackageWhitelistMode">29</integer> <!-- 1+4+8+16 -->
<!-- TODO(b/143200798): Change to value 13, i.e. 1+4+8, when b/143200798 is resolved. -->
<!-- Whether UI for multi user should be shown -->
<bool name="config_enableMultiUserUI">false</bool>

View File

@@ -67,10 +67,11 @@ import java.util.Set;
* then:
* <ul>
* <li>If {@link #isImplicitWhitelistMode()}, the package is implicitly treated as whitelisted
* for all users</li>
* <li>Otherwise, the package is implicitly treated as blacklisted for all non-SYSTEM users</li>
* <li>Either way, for {@link UserHandle#USER_SYSTEM}, the package will be implicitly
* whitelisted so that it can be used for local development purposes.</li>
* for <b>all</b> users</li>
* <li>Otherwise, if {@link #isImplicitWhitelistSystemMode()}, the package is implicitly treated
* as whitelisted for the <b>{@link UserHandle#USER_SYSTEM}</b> user (not other users),
* which is useful for local development purposes</li>
* <li>Otherwise, the package is implicitly treated as blacklisted for all users</li>
* </ul>
*
* <p><b>NOTE:</b> the {@code SystemConfig} state is only updated on first boot or after a system
@@ -86,22 +87,24 @@ class UserSystemPackageInstaller {
* System Property whether to only install system packages on a user if they're whitelisted for
* that user type. These are flags and can be freely combined.
* <ul>
* <li> 0 (0b0000) - disable whitelist (install all system packages; no logging)</li>
* <li> 1 (0b0001) - enforce (only install system packages if they are whitelisted)</li>
* <li> 2 (0b0010) - log (log when a non-whitelisted package is run)</li>
* <li> 4 (0b0100) - implicitly whitelist any package not mentioned in the whitelist</li>
* <li> 8 (0b1000) - ignore OTAs (don't install system packages during OTAs)</li>
* <li>-1 - use device default (as defined in res/res/values/config.xml)</li>
* <li> 0 - disable whitelist (install all system packages; no logging)</li>
* <li> 1 - enforce (only install system packages if they are whitelisted)</li>
* <li> 2 - log (log when a non-whitelisted package is run)</li>
* <li> 4 - for all users: implicitly whitelist any package not mentioned in the whitelist</li>
* <li> 8 - for SYSTEM: implicitly whitelist any package not mentioned in the whitelist</li>
* <li> 16 - ignore OTAs (don't install system packages during OTAs)</li>
* <li>-1 - use device default (as defined in res/res/values/config.xml)</li>
* </ul>
* Note: This list must be kept current with config_userTypePackageWhitelistMode in
* frameworks/base/core/res/res/values/config.xml
*/
static final String PACKAGE_WHITELIST_MODE_PROP = "persist.debug.user.package_whitelist_mode";
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0b0001;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0b0010;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0b0100;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0b1000;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DISABLE = 0x00;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE = 0x01;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_LOG = 0x02;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST = 0x04;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM = 0x08;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA = 0x10;
static final int USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT = -1;
@IntDef(flag = true, prefix = "USER_TYPE_PACKAGE_WHITELIST_MODE_", value = {
@@ -281,6 +284,14 @@ class UserSystemPackageInstaller {
return isImplicitWhitelistMode(getWhitelistMode());
}
/**
* Whether to treat all packages that are not mentioned at all in the whitelist to be implicitly
* whitelisted for the SYSTEM user.
*/
boolean isImplicitWhitelistSystemMode() {
return isImplicitWhitelistSystemMode(getWhitelistMode());
}
/** See {@link #isEnforceMode()}. */
private static boolean isEnforceMode(int whitelistMode) {
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE) != 0;
@@ -301,6 +312,11 @@ class UserSystemPackageInstaller {
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST) != 0;
}
/** See {@link #isImplicitWhitelistSystemMode()}. */
private static boolean isImplicitWhitelistSystemMode(int whitelistMode) {
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM) != 0;
}
/** Gets the PackageWhitelistMode for use of {@link #mWhitelistedPackagesForUserTypes}. */
private @PackageWhitelistMode int getWhitelistMode() {
final int runtimeMode = SystemProperties.getInt(
@@ -332,8 +348,8 @@ class UserSystemPackageInstaller {
if (!isEnforceMode(mode)) {
return null;
}
final boolean isSystemUser = mUm.isUserTypeSubtypeOfSystem(userType);
final boolean isImplicitWhitelistMode = isImplicitWhitelistMode(mode);
final boolean implicitlyWhitelist = isImplicitWhitelistMode(mode)
|| (isImplicitWhitelistSystemMode(mode) && mUm.isUserTypeSubtypeOfSystem(userType));
final Set<String> whitelistedPackages = getWhitelistedPackagesForUserType(userType);
final Set<String> installPackages = new ArraySet<>();
@@ -343,7 +359,7 @@ class UserSystemPackageInstaller {
return;
}
if (shouldInstallPackage(pkg, mWhitelistedPackagesForUserTypes,
whitelistedPackages, isImplicitWhitelistMode, isSystemUser)) {
whitelistedPackages, implicitlyWhitelist)) {
// Although the whitelist uses manifest names, this function returns packageNames.
installPackages.add(pkg.getPackageName());
}
@@ -360,31 +376,18 @@ class UserSystemPackageInstaller {
* installed. This is only used for overriding the userWhitelist in
* certain situations (based on its keyset).
* @param userWhitelist set of package manifest names that should be installed on this
* particular user. This must be consistent with userTypeWhitelist, but is
* passed in separately to avoid repeatedly calculating it from
* <b>particular</b> user. This must be consistent with userTypeWhitelist,
* but is passed in separately to avoid repeatedly calculating it from
* userTypeWhitelist.
* @param isImplicitWhitelistMode whether non-mentioned packages are implicitly whitelisted.
* @param isSystemUser whether the user is USER_SYSTEM (which gets special treatment).
* @param implicitlyWhitelist whether non-mentioned packages are implicitly whitelisted.
*/
@VisibleForTesting
static boolean shouldInstallPackage(AndroidPackage sysPkg,
@NonNull ArrayMap<String, Long> userTypeWhitelist,
@NonNull Set<String> userWhitelist, boolean isImplicitWhitelistMode,
boolean isSystemUser) {
@NonNull Set<String> userWhitelist, boolean implicitlyWhitelist) {
final String pkgName = sysPkg.getManifestPackageName();
boolean install = (isImplicitWhitelistMode && !userTypeWhitelist.containsKey(pkgName))
return (implicitlyWhitelist && !userTypeWhitelist.containsKey(pkgName))
|| userWhitelist.contains(pkgName);
// For the purposes of local development, any package that isn't even mentioned in the
// whitelist at all is implicitly treated as whitelisted for the SYSTEM user.
if (!install && isSystemUser && !userTypeWhitelist.containsKey(pkgName)) {
install = true;
Slog.e(TAG, "System package " + pkgName + " is not mentioned "
+ "in SystemConfig's 'install-in-user-type' but we are "
+ "implicitly treating it as whitelisted for the SYSTEM user.");
}
return install;
}
/**

View File

@@ -26,6 +26,7 @@ import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE;
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA;
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST;
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM;
import static com.android.server.pm.UserSystemPackageInstaller.USER_TYPE_PACKAGE_WHITELIST_MODE_LOG;
import static org.junit.Assert.assertEquals;
@@ -262,39 +263,25 @@ public class UserSystemPackageInstallerTest {
// No implicit whitelist, so only install pkg1.
boolean implicit = false;
boolean isSysUser = false;
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
pkg1, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg1, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
pkg2, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg2, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
pkg3, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg3, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
pkg4, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg4, pkgBitSetMap, userWhitelist, implicit));
// Use implicit whitelist, so install pkg1 and pkg4
implicit = true;
isSysUser = false;
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
pkg1, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg1, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
pkg2, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg2, pkgBitSetMap, userWhitelist, implicit));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
pkg3, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg3, pkgBitSetMap, userWhitelist, implicit));
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
pkg4, pkgBitSetMap, userWhitelist, implicit, isSysUser));
// For user 0 specifically, we always implicitly whitelist.
implicit = false;
isSysUser = true;
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
pkg1, pkgBitSetMap, userWhitelist, implicit, isSysUser));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
pkg2, pkgBitSetMap, userWhitelist, implicit, isSysUser));
assertFalse(UserSystemPackageInstaller.shouldInstallPackage(
pkg3, pkgBitSetMap, userWhitelist, implicit, isSysUser));
assertTrue(UserSystemPackageInstaller.shouldInstallPackage(
pkg4, pkgBitSetMap, userWhitelist, implicit, isSysUser));
pkg4, pkgBitSetMap, userWhitelist, implicit));
}
/**
@@ -400,30 +387,42 @@ public class UserSystemPackageInstallerTest {
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_LOG);
assertTrue(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE);
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertTrue(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST);
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertTrue(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST_SYSTEM);
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertTrue(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IGNORE_OTA);
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertFalse(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertTrue(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(
@@ -431,6 +430,7 @@ public class UserSystemPackageInstallerTest {
assertTrue(mUserSystemPackageInstaller.isLogMode());
assertTrue(mUserSystemPackageInstaller.isEnforceMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST
@@ -438,6 +438,7 @@ public class UserSystemPackageInstallerTest {
assertFalse(mUserSystemPackageInstaller.isLogMode());
assertTrue(mUserSystemPackageInstaller.isEnforceMode());
assertTrue(mUserSystemPackageInstaller.isImplicitWhitelistMode());
assertFalse(mUserSystemPackageInstaller.isImplicitWhitelistSystemMode());
assertFalse(mUserSystemPackageInstaller.isIgnoreOtaMode());
}