summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@android.com> 2015-12-07 15:35:42 -0700
committer Jeff Sharkey <jsharkey@android.com> 2015-12-07 18:02:10 -0700
commitce14cd01411c384b3b979a9f662bf3cd5f9e7183 (patch)
treeac0e10bf97769a9cd4e08cfe325d0798be79cc7a
parent39a275b3980b5ea75e060da540229b95a47333f7 (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.java13
-rw-r--r--services/core/java/com/android/server/MountService.java76
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) {