From 85e4e818d83dbc65b1e6e3ed9d39c656188acaec Mon Sep 17 00:00:00 2001 From: Paul Crowley Date: Tue, 19 May 2015 12:42:00 +0100 Subject: [PATCH] Delete the user key when deleting a user. BUG=19706593 Change-Id: I36ec1b987f5a07450c6a564c74f124ec8d3403ad --- .../android/os/storage/IMountService.java | 31 +++++++++++++++++++ .../android/os/storage/StorageManager.java | 9 ++++++ .../java/com/android/server/MountService.java | 29 +++++++++++++++++ .../android/server/pm/UserManagerService.java | 3 ++ 4 files changed, 72 insertions(+) diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 35e535d41d4a4..edae5d9410c1a 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -1193,6 +1193,21 @@ public interface IMountService extends IInterface { _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 @@ public interface IMountService extends IInterface { 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 @@ public interface IMountService extends IInterface { 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 interface IMountService extends IInterface { */ 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 0502397195081..6dfc3d315b34a 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -910,6 +910,15 @@ public class StorageManager { } } + /** {@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( diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 8c6c25b112b6c..7e6dd5b22ea9a 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2336,6 +2336,35 @@ class MountService extends IMountService.Stub } } + // 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 15d1535a2eb14..d8594424b09ec 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.RemoteException; 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 @@ public class UserManagerService extends IUserManager.Stub { } private void removeUserStateLocked(final int userHandle) { + mContext.getSystemService(StorageManager.class) + .deleteUserKey(userHandle); // Cleanup package manager settings mPm.cleanUpUserLILPw(this, userHandle);