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

Commit 270db90c authored by Eric Biggers's avatar Eric Biggers
Browse files

Get list of unlocked users from vold

When StorageManagerService is started, initialize mLocalUnlockedUsers to
the list of users that vold knows is unlocked rather than an empty list.

This fixes StorageManagerService.isUserKeyUnlocked() to return true
instead of false for already-unlocked users after a userspace reboot.

So far this bug hadn't been causing real problems, since UserController
will always try to unlock users without providing a secret, and that
happened to succeed with a vold warning for users that vold already
knows are unlocked -- even if a secret would normally be required.

However, in order to eliminate misleading error messages from the log,
system_server needs to stop asking vold to unlock users that require a
secret without providing one.  To keep that from breaking userspace
reboot, we need to fix mLocalUnlockedUsers to properly reflect the
initial state and not have to be fixed up "by accident" later.

Bug: 146206679
Test: see I482ed8017f7bbc8f7d4fd5a2c0f58629317ce4ed
Change-Id: Ife12ba9fbb2e65822b8d54de8f7a050b6ebe10a9
parent 006b746b
Loading
Loading
Loading
Loading
+38 −2
Original line number Diff line number Diff line
@@ -363,6 +363,12 @@ class StorageManagerService extends IStorageManager.Stub
            users = ArrayUtils.appendInt(users, userId);
            invalidateIsUserUnlockedCache();
        }
        public void appendAll(int[] userIds) {
            for (int userId : userIds) {
                users = ArrayUtils.appendInt(users, userId);
            }
            invalidateIsUserUnlockedCache();
        }
        public void remove(int userId) {
            users = ArrayUtils.removeInt(users, userId);
            invalidateIsUserUnlockedCache();
@@ -1099,6 +1105,10 @@ class StorageManagerService extends IStorageManager.Stub
            }

            try {
                // Reset vold to tear down existing disks/volumes and start from
                // a clean state.  Exception: already-unlocked user storage will
                // remain unlocked and is not affected by the reset.
                //
                // TODO(b/135341433): Remove cautious logging when FUSE is stable
                Slog.i(TAG, "Resetting vold...");
                mVold.reset();
@@ -1113,7 +1123,7 @@ class StorageManagerService extends IStorageManager.Stub
                    mStoraged.onUserStarted(userId);
                }
                if (mIsAutomotive) {
                    restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
                    restoreSystemUnlockedUsers(userManager, users, systemUnlockedUsers);
                }
                mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
                mStorageManagerInternal.onReset(mVold);
@@ -1123,7 +1133,7 @@ class StorageManagerService extends IStorageManager.Stub
        }
    }

    private void restoreAllUnlockedUsers(UserManager userManager, List<UserInfo> allUsers,
    private void restoreSystemUnlockedUsers(UserManager userManager, List<UserInfo> allUsers,
            int[] systemUnlockedUsers) throws Exception {
        Arrays.sort(systemUnlockedUsers);
        UserManager.invalidateIsUserUnlockedCache();
@@ -1146,6 +1156,31 @@ class StorageManagerService extends IStorageManager.Stub
        }
    }

    // If vold knows that some users have their storage unlocked already (which
    // can happen after a "userspace reboot"), then add those users to
    // mLocalUnlockedUsers.  Do this right away and don't wait until
    // PHASE_BOOT_COMPLETED, since the system may unlock users before then.
    private void restoreLocalUnlockedUsers() {
        final int[] userIds;
        try {
            userIds = mVold.getUnlockedUsers();
        } catch (Exception e) {
            Slog.e(TAG, "Failed to get unlocked users from vold", e);
            return;
        }
        if (!ArrayUtils.isEmpty(userIds)) {
            Slog.d(TAG, "CE storage for users " + Arrays.toString(userIds)
                    + " is already unlocked");
            synchronized (mLock) {
                // Append rather than replace, just in case we're actually
                // reconnecting to vold after it crashed and was restarted, in
                // which case things will be the other way around --- we'll know
                // about the unlocked users but vold won't.
                mLocalUnlockedUsers.appendAll(userIds);
            }
        }
    }

    private void onUnlockUser(int userId) {
        Slog.d(TAG, "onUnlockUser " + userId);

@@ -1947,6 +1982,7 @@ class StorageManagerService extends IStorageManager.Stub
                connectVold();
            }, DateUtils.SECOND_IN_MILLIS);
        } else {
            restoreLocalUnlockedUsers();
            onDaemonConnected();
        }
    }