Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcf1e558 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Consistent creation/destruction of user data.

Preparing and destroying users currently needs to be split across
installd, system_server, and vold, since no single party has all the
required SELinux permissions.

When preparing user directories on a storage device, always enforce
the serial number and destroy data if we run into a mismatch.  When
deleting a user, write the updated user list first before we start
destroying data.  Also start reconciling users on internal storage
at boot, so we can recover from stale data left behind from partially
destroyed users.

Check both CE and DE user directories when reconciling user storage
on a newly mounted storage device.

Bug: 27896918
Change-Id: I4536c82b0196e2720628c4f73fccb742c233350b
parent f2abc9d2
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -437,6 +437,14 @@ public class FileUtils {
        return filePath.startsWith(dirPath);
    }

    public static boolean deleteContentsAndDir(File dir) {
        if (deleteContents(dir)) {
            return dir.delete();
        } else {
            return false;
        }
    }

    public static boolean deleteContents(File dir) {
        File[] files = dir.listFiles();
        boolean success = true;
+29 −0
Original line number Diff line number Diff line
@@ -1324,6 +1324,24 @@ public interface IMountService extends IInterface {
                }
            }

            @Override
            public void destroyUserStorage(String volumeUuid, int userId, int flags)
                    throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(volumeUuid);
                    _data.writeInt(userId);
                    _data.writeInt(flags);
                    mRemote.transact(Stub.TRANSACTION_destroyUserStorage, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public ParcelFileDescriptor mountAppFuse(String name) throws RemoteException {
                Parcel _data = Parcel.obtain();
@@ -1465,6 +1483,7 @@ public interface IMountService extends IInterface {
        static final int TRANSACTION_isUserKeyUnlocked = IBinder.FIRST_CALL_TRANSACTION + 65;

        static final int TRANSACTION_prepareUserStorage = IBinder.FIRST_CALL_TRANSACTION + 66;
        static final int TRANSACTION_destroyUserStorage = IBinder.FIRST_CALL_TRANSACTION + 67;

        static final int TRANSACTION_isConvertibleToFBE = IBinder.FIRST_CALL_TRANSACTION + 68;

@@ -2096,6 +2115,15 @@ public interface IMountService extends IInterface {
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_destroyUserStorage: {
                    data.enforceInterface(DESCRIPTOR);
                    String volumeUuid = data.readString();
                    int userId = data.readInt();
                    int _flags = data.readInt();
                    destroyUserStorage(volumeUuid, userId, _flags);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_mountAppFuse: {
                    data.enforceInterface(DESCRIPTOR);
                    String name = data.readString();
@@ -2434,6 +2462,7 @@ public interface IMountService extends IInterface {

    public void prepareUserStorage(String volumeUuid, int userId, int serialNumber,
            int flags) throws RemoteException;
    public void destroyUserStorage(String volumeUuid, int userId, int flags) throws RemoteException;

    public ParcelFileDescriptor mountAppFuse(String name) throws RemoteException;
}
+9 −0
Original line number Diff line number Diff line
@@ -1052,6 +1052,15 @@ public class StorageManager {
        }
    }

    /** {@hide} */
    public void destroyUserStorage(String volumeUuid, int userId, int flags) {
        try {
            mMountService.destroyUserStorage(volumeUuid, userId, flags);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** {@hide} */
    public boolean isUserKeyUnlocked(int userId) {
        try {
+13 −0
Original line number Diff line number Diff line
@@ -2874,6 +2874,19 @@ class MountService extends IMountService.Stub
        }
    }

    @Override
    public void destroyUserStorage(String volumeUuid, int userId, int flags) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
        waitForReady();

        try {
            mCryptConnector.execute("cryptfs", "destroy_user_storage", escapeNull(volumeUuid),
                    userId, flags);
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
        }
    }

    @Override
    public ParcelFileDescriptor mountAppFuse(final String name) throws RemoteException {
        try {
+5 −4
Original line number Diff line number Diff line
@@ -174,12 +174,13 @@ public final class Installer extends SystemService {
        mInstaller.execute("destroy_app_profiles", pkgName);
    }

    public void createUserConfig(int userid) throws InstallerException {
        mInstaller.execute("mkuserconfig", userid);
    public void createUserData(String uuid, int userId, int userSerial, int flags)
            throws InstallerException {
        mInstaller.execute("create_user_data", uuid, userId, userSerial, flags);
    }

    public void removeUserDataDirs(String uuid, int userid) throws InstallerException {
        mInstaller.execute("rmuser", uuid, userid);
    public void destroyUserData(String uuid, int userId, int flags) throws InstallerException {
        mInstaller.execute("destroy_user_data", uuid, userId, flags);
    }

    public void markBootComplete(String instructionSet) throws InstallerException {
Loading