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

Commit ede482d4 authored by Andrew Scull's avatar Andrew Scull
Browse files

LSS: check whether to cache SP in handler

LockSettingsService should not call DevicePolicyManagerService while
holding a lock this will likely lead to a deadlock. That was the case
here so post to a handler to drop the LSS locks.

Fix: 72538198
Test: runtest frameworks-services -p com.android.server.locksettings
Test: cts-tradefed run cts-dev -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy
Test: cts-tradefed run cts-dev -m CtsDevicePolicyManagerTestCases \
          -t com.android.cts.devicepolicy.ManagedProfileTest#testResetPasswordTokenUsableAfterClearingLock
Change-Id: I74bdb2a556ff97f6ae76881ca0e13d9a6e0c706f
parent 9d3986bd
Loading
Loading
Loading
Loading
+23 −24
Original line number Diff line number Diff line
@@ -1887,7 +1887,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        mSpManager.removeUser(userId);
        mStorage.removeUser(userId);
        mStrongAuth.removeUser(userId);
        cleanSpCache();
        tryRemoveUserFromSpCacheLater(userId);

        final KeyStore ks = KeyStore.getInstance();
        ks.onUserRemoved(userId);
@@ -2141,6 +2141,13 @@ public class LockSettingsService extends ILockSettings.Stub {
    private SparseArray<AuthenticationToken> mSpCache = new SparseArray();

    private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
        // Preemptively cache the SP and then try to remove it in a handler.
        Slog.i(TAG, "Caching SP for user " + userId);
        synchronized (mSpManager) {
            mSpCache.put(userId, auth);
        }
        tryRemoveUserFromSpCacheLater(userId);

        // Pass the primary user's auth secret to the HAL
        if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) {
            try {
@@ -2154,33 +2161,25 @@ public class LockSettingsService extends ILockSettings.Stub {
                Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e);
            }
        }

        // Update the SP cache, removing the entry when allowed
        synchronized (mSpManager) {
            if (shouldCacheSpForUser(userId)) {
                Slog.i(TAG, "Caching SP for user " + userId);
                mSpCache.put(userId, auth);
            } else {
                Slog.i(TAG, "Not caching SP for user " + userId);
                mSpCache.delete(userId);
            }
        }
    }

    /** Clean up the SP cache by removing unneeded entries. */
    private void cleanSpCache() {
        synchronized (mSpManager) {
            // Preserve indicies after removal by iterating backwards
            for (int i = mSpCache.size() - 1; i >= 0; --i) {
                final int userId = mSpCache.keyAt(i);
    private void tryRemoveUserFromSpCacheLater(@UserIdInt int userId) {
        mHandler.post(() -> {
            if (!shouldCacheSpForUser(userId)) {
                    Slog.i(TAG, "Uncaching SP for user " + userId);
                    mSpCache.removeAt(i);
                }
                // The transition from 'should not cache' to 'should cache' can only happen if
                // certain admin apps are installed after provisioning e.g. via adb. This is not
                // a common case and we do not seamlessly support; it may result in the SP not
                // being cached when it is needed. The cache can be re-populated by verifying
                // the credential again.
                Slog.i(TAG, "Removing SP from cache for user " + userId);
                synchronized (mSpManager) {
                    mSpCache.remove(userId);
                }
            }
        });
    }

    /** Do not hold any of the locks from this service when calling. */
    private boolean shouldCacheSpForUser(@UserIdInt int userId) {
        // Before the user setup has completed, an admin could be installed that requires the SP to
        // be cached (see below).
@@ -2731,7 +2730,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
        public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
            if (mDeviceProvisionedUri.equals(uri)) {
                updateRegistration();

@@ -2741,7 +2740,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                    clearFrpCredentialIfOwnerNotSecure();
                }
            } else if (mUserSetupCompleteUri.equals(uri)) {
                cleanSpCache();
                tryRemoveUserFromSpCacheLater(userId);
            }
        }