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

Commit b0a72e22 authored by Eric Biggers's avatar Eric Biggers
Browse files

UserController: avoid misleading log messages about failed to find key

If a user's CE storage requires a credential token to unlock, then
there's no need to try to unlock it without one.

This avoids logging some misleading error messages on every boot, like:

    E vold    : Failed to read from /data/misc/vold/user_keys/ce/0/current/keymaster_key_blob: No such file or directory
    E vold    : Failed to find working ce key for user 0
    E vold    : Couldn't read key for 0

Bug: 146206679

Test: atest com.android.server.am.UserControllerTest
      atest com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testResetPasswordWithToken

      Also a manual test: booted device that has a PIN.  Verified that
      the misleading log messages are no longer present.  Unlocked
      device, then removed the PIN and rebooted.  Verified that the
      device was then automatically unlocked as expected.

Change-Id: I5652a417727553f10a39eb97fc04cc5116b81347
parent abe60b35
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -1635,6 +1635,13 @@ class UserController implements Handler.Callback {
     * PIN or pattern.
     */
    private boolean maybeUnlockUser(final @UserIdInt int userId) {
        if (mInjector.isFileEncryptedNativeOnly() && mLockPatternUtils.isSecure(userId)) {
            // A token is needed, so don't bother trying to unlock without one.
            // This keeps misleading error messages from being logged.
            Slog.d(TAG, "Not unlocking user " + userId
                    + "'s CE storage yet because a credential token is needed");
            return false;
        }
        // Try unlocking storage using empty token
        return unlockUserCleared(userId, null, null, null);
    }
@@ -3085,5 +3092,11 @@ class UserController implements Handler.Callback {
        protected IStorageManager getStorageManager() {
            return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
        }

        // This is needed because isFileEncryptedNativeOnly is a static method,
        // but it needs to be mocked out in tests.
        protected boolean isFileEncryptedNativeOnly() {
            return StorageManager.isFileEncryptedNativeOnly();
        }
    }
}
+23 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ import android.util.Log;

import androidx.test.filters.SmallTest;

import com.android.internal.widget.LockPatternUtils;
import com.android.server.FgThread;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.pm.UserManagerInternal;
@@ -123,6 +124,7 @@ public class UserControllerTest {
    private static final long HANDLER_WAIT_TIME_MS = 100;

    private UserController mUserController;
    private LockPatternUtils mLockPatternUtils;
    private TestInjector mInjector;
    private final HashMap<Integer, UserState> mUserStates = new HashMap<>();

@@ -161,6 +163,13 @@ public class UserControllerTest {
            doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
            doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
            doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());

            // Make it appear that calling unlockUserKey() is needed.
            doReturn(true).when(mInjector).isFileEncryptedNativeOnly();
            mLockPatternUtils = mock(LockPatternUtils.class);
            when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
            doReturn(mLockPatternUtils).when(mInjector).getLockPatternUtils();

            // All UserController params are set to default.
            mUserController = new UserController(mInjector);
            setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
@@ -552,6 +561,20 @@ public class UserControllerTest {
                /* keyEvictedCallback= */ mKeyEvictedCallback, /* expectLocking= */ true);
    }

    /**
     * Test that if a user has a lock screen credential set, then UserController
     * doesn't bother trying to unlock their storage key without a credential
     * token, as it will never work.
     */
    @Test
    public void testSecureUserUnlockNotAttempted() throws Exception {
        when(mLockPatternUtils.isSecure(eq(TEST_USER_ID1))).thenReturn(true);
        setUpUser(TEST_USER_ID1, 0);
        mUserController.startUser(TEST_USER_ID1, /* foreground= */ false);
        verify(mInjector.mStorageManagerMock, times(0))
                .unlockUserKey(eq(TEST_USER_ID1), anyInt(), any(), any());
    }

    @Test
    public void testStartProfile_fullUserFails() {
        setUpUser(TEST_USER_ID1, 0);