Make AccountManagerService more resilient to database corruption.

Currently, if a user accounts database is corrupted, the system will crash and
boot loop.

This CL mitigates the issue by removing the user instead.

Bug: 145710595
Test: adb shell chmod 000 /data/system_de/10/accounts_de.db && adb reboot

Change-Id: I47916fde4577709a2555586b8dc94090605595bd
(cherry picked from commit 8472b904ecef69ee12818fa1f69458875a58c8df)
This commit is contained in:
Felipe Leme
2019-12-05 15:23:16 -08:00
parent 297a84231f
commit bc215de992

View File

@@ -1289,6 +1289,33 @@ public class AccountManagerService
}
protected UserAccounts getUserAccounts(int userId) {
try {
return getUserAccountsNotChecked(userId);
} catch (RuntimeException e) {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
// Let it go...
throw e;
}
// User accounts database is corrupted, we must wipe out the whole user, otherwise the
// system will crash indefinitely
Slog.wtf(TAG, "Removing user " + userId + " due to exception (" + e + ") reading its "
+ "account database");
if (userId == ActivityManager.getCurrentUser() && userId != UserHandle.USER_SYSTEM) {
Slog.i(TAG, "Switching to system user first");
try {
ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
} catch (RemoteException re) {
Slog.e(TAG, "Could not switch to " + UserHandle.USER_SYSTEM + ": " + re);
}
}
if (!getUserManager().removeUserEvenWhenDisallowed(userId)) {
Slog.e(TAG, "could not remove user " + userId);
}
throw e;
}
}
private UserAccounts getUserAccountsNotChecked(int userId) {
synchronized (mUsers) {
UserAccounts accounts = mUsers.get(userId);
boolean validateAccounts = false;