Delete the user key when deleting a user.
BUG=19706593
Change-Id: I36ec1b987f5a07450c6a564c74f124ec8d3403ad
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 35e535d..edae5d9 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -1193,6 +1193,21 @@
_data.recycle();
}
}
+
+ @Override
+ public void deleteUserKey(int userHandle) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(userHandle);
+ mRemote.transact(Stub.TRANSACTION_deleteUserKey, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
}
private static final String DESCRIPTOR = "IMountService";
@@ -1310,6 +1325,8 @@
static final int TRANSACTION_createNewUserDir = IBinder.FIRST_CALL_TRANSACTION + 61;
+ static final int TRANSACTION_deleteUserKey = IBinder.FIRST_CALL_TRANSACTION + 62;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1871,6 +1888,13 @@
reply.writeNoException();
return true;
}
+ case TRANSACTION_deleteUserKey: {
+ data.enforceInterface(DESCRIPTOR);
+ int userHandle = data.readInt();
+ deleteUserKey(userHandle);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
}
@@ -2188,4 +2212,11 @@
*/
public void createNewUserDir(int userHandle, String path)
throws RemoteException;
+
+ /**
+ * Securely delete the user's encryption key
+ * @param userHandle Handle of the user whose key we are deleting
+ */
+ public void deleteUserKey(int userHandle)
+ throws RemoteException;
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 0502397..6dfc3d3 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -911,6 +911,15 @@
}
/** {@hide} */
+ public void deleteUserKey(int userHandle) {
+ try {
+ mMountService.deleteUserKey(userHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** {@hide} */
public static File maybeTranslateEmulatedPathToInternal(File path) {
final IMountService mountService = IMountService.Stub.asInterface(
ServiceManager.getService("mount"));
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 8c6c25b..7e6dd5b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2336,6 +2336,35 @@
}
}
+ // ext4enc:TODO duplication between this and createNewUserDir is nasty
+ @Override
+ public void deleteUserKey(int userHandle) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Only SYSTEM_UID can delete user keys");
+ }
+
+ waitForReady();
+
+ if (DEBUG_EVENTS) {
+ Slog.i(TAG, "Deleting user key");
+ }
+
+ try {
+ NativeDaemonEvent event = mConnector.execute(
+ "cryptfs", "deleteuserkey", userHandle);
+ if (!"0".equals(event.getMessage())) {
+ String error = "deleteuserkey sent unexpected message: "
+ + event.getMessage();
+ Slog.e(TAG, error);
+ // ext4enc:TODO is this the right exception?
+ throw new RuntimeException(error);
+ }
+ } catch (NativeDaemonConnectorException e) {
+ Slog.e(TAG, "deleteuserkey threw exception", e);
+ throw new RuntimeException("deleteuserkey threw exception", e);
+ }
+ }
+
@Override
public int mkdirs(String callingPkg, String appPath) {
final int userId = UserHandle.getUserId(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 15d1535a..d859442 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -42,6 +42,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
@@ -1444,6 +1445,8 @@
}
private void removeUserStateLocked(final int userHandle) {
+ mContext.getSystemService(StorageManager.class)
+ .deleteUserKey(userHandle);
// Cleanup package manager settings
mPm.cleanUpUserLILPw(this, userHandle);