Loading services/core/java/android/os/UserManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -279,4 +279,12 @@ public abstract class UserManagerInternal { * Gets all {@link UserInfo UserInfos}. */ public abstract @NonNull UserInfo[] getUserInfos(); /** * Returns {@code true} if the system should ignore errors when preparing * the storage directories for the user with ID {@code userId}. This will * return {@code false} for all new users; it will only return {@code true} * for users that already existed on-disk from an older version of Android. */ public abstract boolean shouldIgnorePrepareStorageErrors(int userId); } services/core/java/com/android/server/StorageManagerService.java +15 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.DataUnit; import android.util.EventLog; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.Pair; Loading Loading @@ -3407,7 +3408,21 @@ class StorageManagerService extends IStorageManager.Stub } } } catch (Exception e) { EventLog.writeEvent(0x534e4554, "224585613", -1, ""); Slog.wtf(TAG, e); // Make sure to re-throw this exception; we must not ignore failure // to prepare the user storage as it could indicate that encryption // wasn't successfully set up. // // Very unfortunately, these errors need to be ignored for broken // users that already existed on-disk from older Android versions. UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); if (umInternal.shouldIgnorePrepareStorageErrors(userId)) { Slog.wtf(TAG, "ignoring error preparing storage for existing user " + userId + "; device may be insecure!"); return; } throw new RuntimeException(e); } } Loading services/core/java/com/android/server/notification/NotificationManagerService.java +3 −1 Original line number Diff line number Diff line Loading @@ -5811,8 +5811,10 @@ public class NotificationManagerService extends SystemService { // Fix the notification as best we can. try { fixNotification(notification, pkg, tag, id, userId); } catch (Exception e) { if (notification.isForegroundService()) { throw new SecurityException("Invalid FGS notification", e); } Slog.e(TAG, "Cannot fix notification", e); return; } Loading services/core/java/com/android/server/pm/UserDataPreparer.java +11 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.pm.UserInfo; import android.os.Environment; import android.os.FileUtils; import android.os.RecoverySystem; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.os.SystemProperties; Loading Loading @@ -115,6 +116,16 @@ class UserDataPreparer { // Try one last time; if we fail again we're really in trouble prepareUserDataLI(volumeUuid, userId, userSerial, flags | StorageManager.FLAG_STORAGE_DE, false); } else { try { Log.wtf(TAG, "prepareUserData failed for user " + userId, e); if (userId == UserHandle.USER_SYSTEM) { RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed for system user"); } } catch (IOException e2) { throw new RuntimeException("error rebooting into recovery", e2); } } } } Loading services/core/java/com/android/server/pm/UserManagerService.java +42 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,8 @@ public class UserManagerService extends IUserManager.Stub { private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions"; private static final String TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL = "lastRequestQuietModeEnabledCall"; private static final String TAG_IGNORE_PREPARE_STORAGE_ERRORS = "ignorePrepareStorageErrors"; private static final String ATTR_KEY = "key"; private static final String ATTR_VALUE_TYPE = "type"; private static final String ATTR_MULTIPLE = "m"; Loading Loading @@ -298,6 +300,14 @@ public class UserManagerService extends IUserManager.Stub { private long mLastRequestQuietModeEnabledMillis; /** * {@code true} if the system should ignore errors when preparing the * storage directories for this user. This is {@code false} for all new * users; it will only be {@code true} for users that already existed * on-disk from an older version of Android. */ private boolean mIgnorePrepareStorageErrors; void setLastRequestQuietModeEnabledMillis(long millis) { mLastRequestQuietModeEnabledMillis = millis; } Loading @@ -306,6 +316,14 @@ public class UserManagerService extends IUserManager.Stub { return mLastRequestQuietModeEnabledMillis; } boolean getIgnorePrepareStorageErrors() { return mIgnorePrepareStorageErrors; } void setIgnorePrepareStorageErrors() { mIgnorePrepareStorageErrors = true; } void clearSeedAccountData() { seedAccountName = null; seedAccountType = null; Loading Loading @@ -2955,6 +2973,10 @@ public class UserManagerService extends IUserManager.Stub { serializer.endTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL); } serializer.startTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS); serializer.text(String.valueOf(userData.getIgnorePrepareStorageErrors())); serializer.endTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS); serializer.endTag(null, TAG_USER); serializer.endDocument(); Loading Loading @@ -3067,6 +3089,7 @@ public class UserManagerService extends IUserManager.Stub { Bundle legacyLocalRestrictions = null; RestrictionsSet localRestrictions = null; Bundle globalRestrictions = null; boolean ignorePrepareStorageErrors = true; // default is true for old users XmlPullParser parser = Xml.newPullParser(); parser.setInput(is, StandardCharsets.UTF_8.name()); Loading Loading @@ -3158,6 +3181,11 @@ public class UserManagerService extends IUserManager.Stub { if (type == XmlPullParser.TEXT) { lastRequestQuietModeEnabledTimestamp = Long.parseLong(parser.getText()); } } else if (TAG_IGNORE_PREPARE_STORAGE_ERRORS.equals(tag)) { type = parser.next(); if (type == XmlPullParser.TEXT) { ignorePrepareStorageErrors = Boolean.parseBoolean(parser.getText()); } } } } Loading Loading @@ -3185,6 +3213,9 @@ public class UserManagerService extends IUserManager.Stub { userData.persistSeedData = persistSeedData; userData.seedAccountOptions = seedAccountOptions; userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp); if (ignorePrepareStorageErrors) { userData.setIgnorePrepareStorageErrors(); } synchronized (mRestrictionsLock) { if (baseRestrictions != null) { Loading Loading @@ -4829,6 +4860,9 @@ public class UserManagerService extends IUserManager.Stub { pw.println(); } } pw.println(" Ignore errors preparing storage: " + userData.getIgnorePrepareStorageErrors()); } } pw.println(); Loading Loading @@ -5254,6 +5288,14 @@ public class UserManagerService extends IUserManager.Stub { return allInfos; } } @Override public boolean shouldIgnorePrepareStorageErrors(int userId) { synchronized (mUsersLock) { UserData userData = mUsers.get(userId); return userData != null && userData.getIgnorePrepareStorageErrors(); } } } /** Loading Loading
services/core/java/android/os/UserManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -279,4 +279,12 @@ public abstract class UserManagerInternal { * Gets all {@link UserInfo UserInfos}. */ public abstract @NonNull UserInfo[] getUserInfos(); /** * Returns {@code true} if the system should ignore errors when preparing * the storage directories for the user with ID {@code userId}. This will * return {@code false} for all new users; it will only return {@code true} * for users that already existed on-disk from an older version of Android. */ public abstract boolean shouldIgnorePrepareStorageErrors(int userId); }
services/core/java/com/android/server/StorageManagerService.java +15 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.DataUnit; import android.util.EventLog; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.Pair; Loading Loading @@ -3407,7 +3408,21 @@ class StorageManagerService extends IStorageManager.Stub } } } catch (Exception e) { EventLog.writeEvent(0x534e4554, "224585613", -1, ""); Slog.wtf(TAG, e); // Make sure to re-throw this exception; we must not ignore failure // to prepare the user storage as it could indicate that encryption // wasn't successfully set up. // // Very unfortunately, these errors need to be ignored for broken // users that already existed on-disk from older Android versions. UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); if (umInternal.shouldIgnorePrepareStorageErrors(userId)) { Slog.wtf(TAG, "ignoring error preparing storage for existing user " + userId + "; device may be insecure!"); return; } throw new RuntimeException(e); } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +3 −1 Original line number Diff line number Diff line Loading @@ -5811,8 +5811,10 @@ public class NotificationManagerService extends SystemService { // Fix the notification as best we can. try { fixNotification(notification, pkg, tag, id, userId); } catch (Exception e) { if (notification.isForegroundService()) { throw new SecurityException("Invalid FGS notification", e); } Slog.e(TAG, "Cannot fix notification", e); return; } Loading
services/core/java/com/android/server/pm/UserDataPreparer.java +11 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.pm.UserInfo; import android.os.Environment; import android.os.FileUtils; import android.os.RecoverySystem; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.os.SystemProperties; Loading Loading @@ -115,6 +116,16 @@ class UserDataPreparer { // Try one last time; if we fail again we're really in trouble prepareUserDataLI(volumeUuid, userId, userSerial, flags | StorageManager.FLAG_STORAGE_DE, false); } else { try { Log.wtf(TAG, "prepareUserData failed for user " + userId, e); if (userId == UserHandle.USER_SYSTEM) { RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed for system user"); } } catch (IOException e2) { throw new RuntimeException("error rebooting into recovery", e2); } } } } Loading
services/core/java/com/android/server/pm/UserManagerService.java +42 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,8 @@ public class UserManagerService extends IUserManager.Stub { private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions"; private static final String TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL = "lastRequestQuietModeEnabledCall"; private static final String TAG_IGNORE_PREPARE_STORAGE_ERRORS = "ignorePrepareStorageErrors"; private static final String ATTR_KEY = "key"; private static final String ATTR_VALUE_TYPE = "type"; private static final String ATTR_MULTIPLE = "m"; Loading Loading @@ -298,6 +300,14 @@ public class UserManagerService extends IUserManager.Stub { private long mLastRequestQuietModeEnabledMillis; /** * {@code true} if the system should ignore errors when preparing the * storage directories for this user. This is {@code false} for all new * users; it will only be {@code true} for users that already existed * on-disk from an older version of Android. */ private boolean mIgnorePrepareStorageErrors; void setLastRequestQuietModeEnabledMillis(long millis) { mLastRequestQuietModeEnabledMillis = millis; } Loading @@ -306,6 +316,14 @@ public class UserManagerService extends IUserManager.Stub { return mLastRequestQuietModeEnabledMillis; } boolean getIgnorePrepareStorageErrors() { return mIgnorePrepareStorageErrors; } void setIgnorePrepareStorageErrors() { mIgnorePrepareStorageErrors = true; } void clearSeedAccountData() { seedAccountName = null; seedAccountType = null; Loading Loading @@ -2955,6 +2973,10 @@ public class UserManagerService extends IUserManager.Stub { serializer.endTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL); } serializer.startTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS); serializer.text(String.valueOf(userData.getIgnorePrepareStorageErrors())); serializer.endTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS); serializer.endTag(null, TAG_USER); serializer.endDocument(); Loading Loading @@ -3067,6 +3089,7 @@ public class UserManagerService extends IUserManager.Stub { Bundle legacyLocalRestrictions = null; RestrictionsSet localRestrictions = null; Bundle globalRestrictions = null; boolean ignorePrepareStorageErrors = true; // default is true for old users XmlPullParser parser = Xml.newPullParser(); parser.setInput(is, StandardCharsets.UTF_8.name()); Loading Loading @@ -3158,6 +3181,11 @@ public class UserManagerService extends IUserManager.Stub { if (type == XmlPullParser.TEXT) { lastRequestQuietModeEnabledTimestamp = Long.parseLong(parser.getText()); } } else if (TAG_IGNORE_PREPARE_STORAGE_ERRORS.equals(tag)) { type = parser.next(); if (type == XmlPullParser.TEXT) { ignorePrepareStorageErrors = Boolean.parseBoolean(parser.getText()); } } } } Loading Loading @@ -3185,6 +3213,9 @@ public class UserManagerService extends IUserManager.Stub { userData.persistSeedData = persistSeedData; userData.seedAccountOptions = seedAccountOptions; userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp); if (ignorePrepareStorageErrors) { userData.setIgnorePrepareStorageErrors(); } synchronized (mRestrictionsLock) { if (baseRestrictions != null) { Loading Loading @@ -4829,6 +4860,9 @@ public class UserManagerService extends IUserManager.Stub { pw.println(); } } pw.println(" Ignore errors preparing storage: " + userData.getIgnorePrepareStorageErrors()); } } pw.println(); Loading Loading @@ -5254,6 +5288,14 @@ public class UserManagerService extends IUserManager.Stub { return allInfos; } } @Override public boolean shouldIgnorePrepareStorageErrors(int userId) { synchronized (mUsersLock) { UserData userData = mUsers.get(userId); return userData != null && userData.getIgnorePrepareStorageErrors(); } } } /** Loading