Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a65e6491 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Progress towards FBE and adoptable storage.

Offer to adopt storage devices on FBE devices, but keep it guarded
behind a system property for now, since we still need to work out key
storage details.

Verify that all users are unlocked before moving apps or shared
storage.  We only need them to be unlocked; we don't need them to
be actually running.

Have PackageManager dump the set of volumes that it's finished
scanning and loading, since otherwise CTS can get excited and race
too far ahead of it.  Add a specific error code to communicate
that users are locked.

Test: cts-tradefed run commandAndExit cts-dev --abi armeabi-v7a -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AdoptableHostTest
Bug: 37436961, 29923055, 25861755, 30230655
Change-Id: I749dc3d8148e1a95d8bc4be56665253ef826d3fe
parent 6a869a9c
Loading
Loading
Loading
Loading
+3 −10
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.system.ErrnoException;
@@ -370,13 +371,6 @@ class ContextImpl extends Context {
        return getSharedPreferences(file, mode);
    }

    private boolean isBuggy() {
        // STOPSHIP: fix buggy apps
        if (SystemProperties.getBoolean("fw.ignore_buggy", false)) return false;
        if ("com.google.android.tts".equals(getApplicationInfo().packageName)) return true;
        return false;
    }

    @Override
    public SharedPreferences getSharedPreferences(File file, int mode) {
        SharedPreferencesImpl sp;
@@ -387,9 +381,8 @@ class ContextImpl extends Context {
                checkMode(mode);
                if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) {
                    if (isCredentialProtectedStorage()
                            && !getSystemService(StorageManager.class).isUserKeyUnlocked(
                            UserHandle.myUserId())
                            && !isBuggy()) {
                            && !getSystemService(UserManager.class)
                                    .isUserUnlockingOrUnlocked(UserHandle.myUserId())) {
                        throw new IllegalStateException("SharedPreferences in credential encrypted "
                                + "storage are not available until after user is unlocked");
                    }
+3 −0
Original line number Diff line number Diff line
@@ -1490,6 +1490,9 @@ public abstract class PackageManager {
     */
    public static final int MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL = -9;

    /** @hide */
    public static final int MOVE_FAILED_LOCKED_USER = -10;

    /**
     * Flag parameter for {@link #movePackage} to indicate that
     * the package should be moved to internal storage if its
+2 −0
Original line number Diff line number Diff line
@@ -118,6 +118,8 @@ public class StorageManager {
    public static final String PROP_SDCARDFS = "persist.sys.sdcardfs";
    /** {@hide} */
    public static final String PROP_VIRTUAL_DISK = "persist.sys.virtual_disk";
    /** {@hide} */
    public static final String PROP_ADOPTABLE_FBE = "persist.sys.adoptable_fbe";

    /** {@hide} */
    public static final String UUID_PRIVATE_INTERNAL = null;
+16 −2
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.NativeDaemonConnector.Command;
import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.pm.PackageManagerException;
import com.android.server.pm.PackageManagerService;
import com.android.server.storage.AppFuseBridge;

@@ -1078,7 +1079,8 @@ class StorageManagerService extends IStorageManager.Stub
                    flags |= DiskInfo.FLAG_ADOPTABLE;
                }
                // Adoptable storage isn't currently supported on FBE devices
                if (StorageManager.isFileEncryptedNativeOnly()) {
                if (StorageManager.isFileEncryptedNativeOnly()
                        && !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
                    flags &= ~DiskInfo.FLAG_ADOPTABLE;
                }
                mDisks.put(id, new DiskInfo(id, flags));
@@ -2045,7 +2047,8 @@ class StorageManagerService extends IStorageManager.Stub
        }

        if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
            if (StorageManager.isFileEncryptedNativeOnly()) {
            if (StorageManager.isFileEncryptedNativeOnly()
                    && !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
                throw new IllegalStateException(
                        "Adoptable storage not available on device with native FBE");
            }
@@ -2121,6 +2124,17 @@ class StorageManagerService extends IStorageManager.Stub
            mMoveCallback = callback;
            mMoveTargetUuid = volumeUuid;

            // We need all the users unlocked to move their primary storage
            final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
            for (UserInfo user : users) {
                if (StorageManager.isFileEncryptedNativeOrEmulated()
                        && !isUserKeyUnlocked(user.id)) {
                    Slog.w(TAG, "Failing move due to locked user " + user.id);
                    onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
                    return;
                }
            }

            // When moving to/from primary physical volume, we probably just nuked
            // the current storage location, so we have nothing to move.
            if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
+41 −3
Original line number Diff line number Diff line
@@ -58,7 +58,6 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE
import static android.content.pm.PackageManager.INSTALL_FORWARD_LOCK;
import static android.content.pm.PackageManager.INSTALL_INTERNAL;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
@@ -78,6 +77,7 @@ import static android.content.pm.PackageManager.MOVE_FAILED_3RD_PARTY_NOT_ALLOWE
import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.MOVE_FAILED_LOCKED_USER;
import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
@@ -87,6 +87,7 @@ import static android.content.pm.PackageParser.isApkFile;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDWR;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
@@ -102,6 +103,7 @@ import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefa
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
import static dalvik.system.DexFile.getNonProfileGuidedCompilerFilter;
import android.Manifest;
@@ -130,6 +132,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.AppsQueryHelper;
import android.content.pm.AuxiliaryResolveInfo;
import android.content.pm.ChangedPackages;
import android.content.pm.ComponentInfo;
import android.content.pm.FallbackCategoryProvider;
import android.content.pm.FeatureInfo;
import android.content.pm.IDexModuleRegisterCallback;
@@ -724,6 +727,9 @@ public class PackageManagerService extends IPackageManager.Stub
    final ProtectedPackages mProtectedPackages;
    @GuardedBy("mLoadedVolumes")
    final ArraySet<String> mLoadedVolumes = new ArraySet<>();
    boolean mFirstBoot;
    PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy;
@@ -21675,6 +21681,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
        public static final int DUMP_DEXOPT = 1 << 20;
        public static final int DUMP_COMPILER_STATS = 1 << 21;
        public static final int DUMP_CHANGES = 1 << 22;
        public static final int DUMP_VOLUMES = 1 << 23;
        public static final int OPTION_SHOW_FILTERS = 1 << 0;
@@ -21914,6 +21921,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                dumpState.setDump(DumpState.DUMP_INSTALLS);
            } else if ("frozen".equals(cmd)) {
                dumpState.setDump(DumpState.DUMP_FROZEN);
            } else if ("volumes".equals(cmd)) {
                dumpState.setDump(DumpState.DUMP_VOLUMES);
            } else if ("dexopt".equals(cmd)) {
                dumpState.setDump(DumpState.DUMP_DEXOPT);
            } else if ("compiler-stats".equals(cmd)) {
@@ -22298,6 +22307,23 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                ipw.decreaseIndent();
            }
            if (!checkin && dumpState.isDumping(DumpState.DUMP_VOLUMES) && packageName == null) {
                if (dumpState.onTitlePrinted()) pw.println();
                final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
                ipw.println();
                ipw.println("Loaded volumes:");
                ipw.increaseIndent();
                if (mLoadedVolumes.size() == 0) {
                    ipw.println("(none)");
                } else {
                    for (int i = 0; i < mLoadedVolumes.size(); i++) {
                        ipw.println(mLoadedVolumes.valueAt(i));
                    }
                }
                ipw.decreaseIndent();
            }
            if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) {
                if (dumpState.onTitlePrinted()) pw.println();
                dumpDexoptStateLPr(pw, packageName);
@@ -23014,6 +23040,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
        if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
        sendResourcesChangedBroadcast(true, false, loaded, null);
        mLoadedVolumes.add(vol.getId());
    }
    private void unloadPrivatePackages(final VolumeInfo vol) {
@@ -23065,6 +23092,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
        if (DEBUG_INSTALL) Slog.d(TAG, "Unloaded packages " + unloaded);
        sendResourcesChangedBroadcast(false, false, unloaded, null);
        mLoadedVolumes.remove(vol.getId());
        // Try very hard to release any references to this path so we don't risk
        // the system server being killed due to open FDs
@@ -23608,8 +23636,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                    movePackageInternal(packageName, volumeUuid, moveId, callingUid, user);
                } catch (PackageManagerException e) {
                    Slog.w(TAG, "Failed to move " + packageName, e);
                    mMoveCallbacks.notifyStatusChanged(moveId,
                            PackageManager.MOVE_FAILED_INTERNAL_ERROR);
                    mMoveCallbacks.notifyStatusChanged(moveId, e.error);
                }
            }
        });
@@ -23732,6 +23759,17 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
            measurePath = Environment.getDataAppDirectory(volumeUuid);
        }
        // If we're moving app data around, we need all the users unlocked
        if (moveCompleteApp) {
            for (int userId : installedUserIds) {
                if (StorageManager.isFileEncryptedNativeOrEmulated()
                        && !StorageManager.isUserKeyUnlocked(userId)) {
                    throw new PackageManagerException(MOVE_FAILED_LOCKED_USER,
                            "User " + userId + " must be unlocked");
                }
            }
        }
        final PackageStats stats = new PackageStats(null, -1);
        synchronized (mInstaller) {
            for (int userId : installedUserIds) {
Loading