diff options
| author | 2015-12-07 15:35:42 -0700 | |
|---|---|---|
| committer | 2015-12-07 18:02:10 -0700 | |
| commit | ce14cd01411c384b3b979a9f662bf3cd5f9e7183 (patch) | |
| tree | ac0e10bf97769a9cd4e08cfe325d0798be79cc7a | |
| parent | 39a275b3980b5ea75e060da540229b95a47333f7 (diff) | |
Mount storage after unlock, fix leaving emulation.
Delay mounting of storage devices until after the user is unlocked,
which means any emulated storage areas will be ready for use. Track
separate per-user unlocked states for local versus system lifecycle
state.
Switch to explicitly lock or unlock user keys during boot of a
device without native FBE support. This allows us to recover when
the user has disabled emulated FBE.
Force reboot when changing FBE emulation state.
Bug: 26010607, 26027473
Change-Id: Idaf8b63e69f886ddbd848a9fab6d143a5fd10500
| -rw-r--r-- | core/java/android/os/storage/StorageManager.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/MountService.java | 76 |
2 files changed, 61 insertions, 28 deletions
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index db1256409cb7..7f36a9866eb7 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1021,8 +1021,17 @@ public class StorageManager { /** {@hide} */ public static boolean isFileBasedEncryptionEnabled() { - return "file".equals(SystemProperties.get("ro.crypto.type", "none")) - || SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false); + return isNativeFileBasedEncryptionEnabled() || isEmulatedFileBasedEncryptionEnabled(); + } + + /** {@hide} */ + public static boolean isNativeFileBasedEncryptionEnabled() { + return "file".equals(SystemProperties.get("ro.crypto.type", "none")); + } + + /** {@hide} */ + public static boolean isEmulatedFileBasedEncryptionEnabled() { + return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false); } /** {@hide} */ diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 807c0d6be178..473eff654eac 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -57,6 +57,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -175,8 +176,8 @@ class MountService extends IMountService.Stub } @Override - public void onStartUser(int userHandle) { - mMountService.onStartUser(userHandle); + public void onUnlockUser(int userHandle) { + mMountService.onUnlockUser(userHandle); } @Override @@ -286,10 +287,12 @@ class MountService extends IMountService.Stub */ private final Object mLock = new Object(); + /** Set of users that we know are unlocked. */ @GuardedBy("mLock") - private int[] mStartedUsers = EmptyArray.INT; + private int[] mLocalUnlockedUsers = EmptyArray.INT; + /** Set of users that system knows are unlocked. */ @GuardedBy("mLock") - private int[] mUnlockedUsers = EmptyArray.INT; + private int[] mSystemUnlockedUsers = EmptyArray.INT; /** Map from disk ID to disk */ @GuardedBy("mLock") @@ -834,12 +837,21 @@ class MountService extends IMountService.Stub private void initIfReadyAndConnected() { Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady + ", mDaemonConnected=" + mDaemonConnected); - if (mSystemReady && mDaemonConnected && StorageManager.isFileBasedEncryptionEnabled()) { - final List<UserInfo> users = mContext.getSystemService(UserManager.class) - .getUsers(); + if (mSystemReady && mDaemonConnected + && !StorageManager.isNativeFileBasedEncryptionEnabled()) { + // When booting a device without native support, make sure that our + // user directories are locked or unlocked based on the current + // emulation status. + final boolean initLocked = StorageManager.isEmulatedFileBasedEncryptionEnabled(); + final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); for (UserInfo user : users) { try { - mCryptConnector.execute("cryptfs", "lock_user_key", user.id); + if (initLocked) { + mCryptConnector.execute("cryptfs", "lock_user_key", user.id); + } else { + mCryptConnector.execute("cryptfs", "unlock_user_key", user.id, + user.serialNumber, "!"); + } } catch (NativeDaemonConnectorException e) { Slog.w(TAG, "Failed to init vold", e); } @@ -854,9 +866,9 @@ class MountService extends IMountService.Stub final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); killMediaProvider(users); - final int[] startedUsers; + final int[] systemUnlockedUsers; synchronized (mLock) { - startedUsers = mStartedUsers; + systemUnlockedUsers = mSystemUnlockedUsers; mDisks.clear(); mVolumes.clear(); @@ -871,7 +883,7 @@ class MountService extends IMountService.Stub for (UserInfo user : users) { mConnector.execute("volume", "user_added", user.id, user.serialNumber); } - for (int userId : startedUsers) { + for (int userId : systemUnlockedUsers) { mConnector.execute("volume", "user_started", userId); } } catch (NativeDaemonConnectorException e) { @@ -880,8 +892,8 @@ class MountService extends IMountService.Stub } } - private void onStartUser(int userId) { - Slog.d(TAG, "onStartUser " + userId); + private void onUnlockUser(int userId) { + Slog.d(TAG, "onUnlockUser " + userId); // We purposefully block here to make sure that user-specific // staging area is ready so it's ready for zygote-forked apps to @@ -904,7 +916,7 @@ class MountService extends IMountService.Stub mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState); } } - mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userId); + mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId); } } @@ -917,7 +929,7 @@ class MountService extends IMountService.Stub } synchronized (mVolumes) { - mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userId); + mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId); } } @@ -1337,7 +1349,7 @@ class MountService extends IMountService.Stub // Kick state changed event towards all started users. Any users // started after this point will trigger additional // user-specific broadcasts. - for (int userId : mStartedUsers) { + for (int userId : mSystemUnlockedUsers) { if (vol.isVisibleForRead(userId)) { final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); @@ -1926,8 +1938,16 @@ class MountService extends IMountService.Stub waitForReady(); if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) { + if (StorageManager.isNativeFileBasedEncryptionEnabled()) { + throw new IllegalStateException( + "Emulation not available on device with native FBE"); + } + final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0; SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe)); + + // Perform hard reboot to kick policy into place + mContext.getSystemService(PowerManager.class).reboot(null); } if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) { @@ -2745,7 +2765,7 @@ class MountService extends IMountService.Stub } synchronized (mLock) { - mUnlockedUsers = ArrayUtils.appendInt(mUnlockedUsers, userId); + mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId); } } @@ -2761,7 +2781,7 @@ class MountService extends IMountService.Stub } synchronized (mLock) { - mUnlockedUsers = ArrayUtils.removeInt(mUnlockedUsers, userId); + mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId); } } @@ -2769,7 +2789,7 @@ class MountService extends IMountService.Stub public boolean isUserKeyUnlocked(int userId) { if (StorageManager.isFileBasedEncryptionEnabled()) { synchronized (mLock) { - return ArrayUtils.contains(mUnlockedUsers, userId); + return ArrayUtils.contains(mLocalUnlockedUsers, userId); } } else { return true; @@ -2836,21 +2856,25 @@ class MountService extends IMountService.Stub @Override public StorageVolume[] getVolumeList(int uid, String packageName, int flags) { + final int userId = UserHandle.getUserId(uid); final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0; - final ArrayList<StorageVolume> res = new ArrayList<>(); + boolean reportUnmounted = false; boolean foundPrimary = false; - final int userId = UserHandle.getUserId(uid); - final boolean reportUnmounted; final long identity = Binder.clearCallingIdentity(); try { - reportUnmounted = !mMountServiceInternal.hasExternalStorage( - uid, packageName); + if (!mMountServiceInternal.hasExternalStorage(uid, packageName)) { + reportUnmounted = true; + } + if (!isUserKeyUnlocked(userId)) { + reportUnmounted = true; + } } finally { Binder.restoreCallingIdentity(identity); } + final ArrayList<StorageVolume> res = new ArrayList<>(); synchronized (mLock) { for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); @@ -3530,8 +3554,8 @@ class MountService extends IMountService.Stub pw.println("Primary storage UUID: " + mPrimaryStorageUuid); pw.println("Force adoptable: " + mForceAdoptable); pw.println(); - pw.println("Started users: " + Arrays.toString(mStartedUsers)); - pw.println("Unlocked users: " + Arrays.toString(mUnlockedUsers)); + pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers)); + pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers)); } synchronized (mObbMounts) { |