Merge "Force garbage collection after credential verification" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-06-29 14:49:00 +00:00
committed by Android (Google) Code Review

View File

@@ -1616,6 +1616,7 @@ public class LockSettingsService extends ILockSettings.Stub {
synchronized (mSeparateChallengeLock) { synchronized (mSeparateChallengeLock) {
if (!setLockCredentialInternal(credential, savedCredential, if (!setLockCredentialInternal(credential, savedCredential,
userId, /* isLockTiedToParent= */ false)) { userId, /* isLockTiedToParent= */ false)) {
scheduleGc();
return false; return false;
} }
setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null); setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
@@ -1626,6 +1627,7 @@ public class LockSettingsService extends ILockSettings.Stub {
setDeviceUnlockedForUser(userId); setDeviceUnlockedForUser(userId);
} }
notifySeparateProfileChallengeChanged(userId); notifySeparateProfileChallengeChanged(userId);
scheduleGc();
return true; return true;
} }
@@ -1965,7 +1967,11 @@ public class LockSettingsService extends ILockSettings.Stub {
public VerifyCredentialResponse checkCredential(LockscreenCredential credential, int userId, public VerifyCredentialResponse checkCredential(LockscreenCredential credential, int userId,
ICheckCredentialProgressCallback progressCallback) { ICheckCredentialProgressCallback progressCallback) {
checkPasswordReadPermission(userId); checkPasswordReadPermission(userId);
return doVerifyCredential(credential, CHALLENGE_NONE, 0, userId, progressCallback); try {
return doVerifyCredential(credential, CHALLENGE_NONE, 0, userId, progressCallback);
} finally {
scheduleGc();
}
} }
@Override @Override
@@ -1978,8 +1984,12 @@ public class LockSettingsService extends ILockSettings.Stub {
challengeType = CHALLENGE_NONE; challengeType = CHALLENGE_NONE;
} }
return doVerifyCredential(credential, challengeType, challenge, userId, try {
null /* progressCallback */); return doVerifyCredential(credential, challengeType, challenge, userId,
null /* progressCallback */);
} finally {
scheduleGc();
}
} }
private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential, private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
@@ -2070,6 +2080,8 @@ public class LockSettingsService extends ILockSettings.Stub {
| BadPaddingException | CertificateException | IOException e) { | BadPaddingException | CertificateException | IOException e) {
Slog.e(TAG, "Failed to decrypt child profile key", e); Slog.e(TAG, "Failed to decrypt child profile key", e);
throw new IllegalStateException("Unable to get tied profile token"); throw new IllegalStateException("Unable to get tied profile token");
} finally {
scheduleGc();
} }
} }
@@ -2983,27 +2995,31 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override @Override
public byte[] getHashFactor(LockscreenCredential currentCredential, int userId) { public byte[] getHashFactor(LockscreenCredential currentCredential, int userId) {
checkPasswordReadPermission(userId); checkPasswordReadPermission(userId);
if (isManagedProfileWithUnifiedLock(userId)) { try {
try { if (isManagedProfileWithUnifiedLock(userId)) {
currentCredential = getDecryptedPasswordForTiedProfile(userId); try {
} catch (Exception e) { currentCredential = getDecryptedPasswordForTiedProfile(userId);
Slog.e(TAG, "Failed to get work profile credential", e); } catch (Exception e) {
return null; Slog.e(TAG, "Failed to get work profile credential", e);
return null;
}
} }
} synchronized (mSpManager) {
synchronized (mSpManager) { if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
if (!isSyntheticPasswordBasedCredentialLocked(userId)) { Slog.w(TAG, "Synthetic password not enabled");
Slog.w(TAG, "Synthetic password not enabled"); return null;
return null; }
long handle = getSyntheticPasswordHandleLocked(userId);
AuthenticationResult auth = mSpManager.unwrapPasswordBasedSyntheticPassword(
getGateKeeperService(), handle, currentCredential, userId, null);
if (auth.authToken == null) {
Slog.w(TAG, "Current credential is incorrect");
return null;
}
return auth.authToken.derivePasswordHashFactor();
} }
long handle = getSyntheticPasswordHandleLocked(userId); } finally {
AuthenticationResult auth = mSpManager.unwrapPasswordBasedSyntheticPassword( scheduleGc();
getGateKeeperService(), handle, currentCredential, userId, null);
if (auth.authToken == null) {
Slog.w(TAG, "Current credential is incorrect");
return null;
}
return auth.authToken.derivePasswordHashFactor();
} }
} }
@@ -3287,6 +3303,22 @@ public class LockSettingsService extends ILockSettings.Stub {
} }
} }
/**
* Schedules garbage collection to sanitize lockscreen credential remnants in memory.
*
* One source of leftover lockscreen credentials is the unmarshalled binder method arguments.
* Since this method will be called within the binder implementation method, a small delay is
* added before the GC operation to allow the enclosing binder proxy code to complete and
* release references to the argument.
*/
private void scheduleGc() {
mHandler.postDelayed(() -> {
System.gc();
System.runFinalization();
System.gc();
}, 2000);
}
private class DeviceProvisionedObserver extends ContentObserver { private class DeviceProvisionedObserver extends ContentObserver {
private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor( private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor(
Settings.Global.DEVICE_PROVISIONED); Settings.Global.DEVICE_PROVISIONED);