diff options
6 files changed, 81 insertions, 12 deletions
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 84a879c99562..c9f050d34a67 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -1192,6 +1192,22 @@ public interface IMountService extends IInterface { _data.recycle(); } } + + @Override + public void createNewUserDir(int userHandle, String path) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(userHandle); + _data.writeString(path); + mRemote.transact(Stub.TRANSACTION_createNewUserDir, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } } private static final String DESCRIPTOR = "IMountService"; @@ -1309,6 +1325,8 @@ public interface IMountService extends IInterface { static final int TRANSACTION_remountUid = IBinder.FIRST_CALL_TRANSACTION + 61; + static final int TRANSACTION_createNewUserDir = IBinder.FIRST_CALL_TRANSACTION + 62; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -1869,6 +1887,14 @@ public interface IMountService extends IInterface { reply.writeNoException(); return true; } + case TRANSACTION_createNewUserDir: { + data.enforceInterface(DESCRIPTOR); + int userHandle = data.readInt(); + String path = data.readString(); + createNewUserDir(userHandle, path); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -2180,4 +2206,12 @@ public interface IMountService extends IInterface { throws RemoteException; public void remountUid(int uid) throws RemoteException; + + /** + * Creates the user data directory, possibly encrypted + * @param userHandle Handle of the user whose directory we are creating + * @param path Path at which to create the directory. + */ + public void createNewUserDir(int userHandle, String path) + throws RemoteException; } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index f03e04e50112..5088159f7423 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -946,6 +946,15 @@ public class StorageManager { } /** {@hide} */ + public void createNewUserDir(int userHandle, File path) { + try { + mMountService.createNewUserDir(userHandle, path.getAbsolutePath()); + } 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 894f513ed1a9..721866680f4c 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2527,6 +2527,34 @@ class MountService extends IMountService.Stub } @Override + public void createNewUserDir(int userHandle, String path) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Only SYSTEM_UID can create user directories"); + } + + waitForReady(); + + if (DEBUG_EVENTS) { + Slog.i(TAG, "Creating new user dir"); + } + + try { + NativeDaemonEvent event = mCryptConnector.execute( + "cryptfs", "createnewuserdir", userHandle, path); + if (!"0".equals(event.getMessage())) { + String error = "createnewuserdir 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, "createnewuserdir threw exception", e); + throw new RuntimeException("createnewuserdir threw exception", e); + } + } + + @Override public int mkdirs(String callingPkg, String appPath) { final int userId = UserHandle.getUserId(Binder.getCallingUid()); final UserEnvironment userEnv = new UserEnvironment(userId); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 124214c84b5f..8ebf316d499e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15398,7 +15398,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (userDir.exists()) continue; try { - UserManagerService.prepareUserDirectory(userDir); + UserManagerService.prepareUserDirectory(mContext, volumeUuid, user.id); UserManagerService.enforceSerialNumber(userDir, user.serialNumber); } catch (IOException e) { Log.wtf(TAG, "Failed to create user directory on " + volumeUuid, e); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 4e85e3925863..7f7417eb5542 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -38,13 +38,17 @@ import android.os.Binder; import android.os.Build; import android.os.Environment; import android.os.FileUtils; +import android.os.IBinder; import android.os.Handler; import android.os.Message; import android.os.PatternMatcher; import android.os.Process; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.util.AtomicFile; import android.text.TextUtils; diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 1a79b4eff6ed..f22f3138e00f 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1262,7 +1262,7 @@ public class UserManagerService extends IUserManager.Stub { try { final File userDir = Environment.getDataUserDirectory(volumeUuid, userId); - prepareUserDirectory(userDir); + prepareUserDirectory(mContext, volumeUuid, userId); enforceSerialNumber(userDir, userInfo.serialNumber); } catch (IOException e) { Log.wtf(LOG_TAG, "Failed to create user directory on " + volumeUuid, e); @@ -1876,16 +1876,10 @@ public class UserManagerService extends IUserManager.Stub { * Create new {@code /data/user/[id]} directory and sets default * permissions. */ - public static void prepareUserDirectory(File file) throws IOException { - if (!file.exists()) { - if (!file.mkdir()) { - throw new IOException("Failed to create " + file); - } - } - if (FileUtils.setPermissions(file.getAbsolutePath(), 0771, Process.SYSTEM_UID, - Process.SYSTEM_UID) != 0) { - throw new IOException("Failed to prepare " + file); - } + public static void prepareUserDirectory(Context context, String volumeUuid, int userId) { + final StorageManager storage = context.getSystemService(StorageManager.class); + final File userDir = Environment.getDataUserDirectory(volumeUuid, userId); + storage.createNewUserDir(userId, userDir); } /** |