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

Commit da965adc authored by Eric Biggers's avatar Eric Biggers Committed by Android (Google) Code Review
Browse files

Merge changes from topics "presubmit-am-049eb38c3a6f461fb6edd46cfd39b59c",...

Merge changes from topics "presubmit-am-049eb38c3a6f461fb6edd46cfd39b59c", "presubmit-am-1488ce33ef094047acc7ba0f5b28a7bd" into tm-dev

* changes:
  Ignore errors preparing user storage for existing users
  UserDataPreparer: reboot to recovery for system user only
parents 54d7eb44 c785063d
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -3670,11 +3670,20 @@ class StorageManagerService extends IStorageManager.Stub
                    mInstaller.tryMountDataMirror(volumeUuid);
                }
            }
        } catch (RemoteException | Installer.InstallerException e) {
        } catch (Exception e) {
            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);
        }
    }
+5 −2
Original line number Diff line number Diff line
@@ -118,8 +118,11 @@ class UserDataPreparer {
                    flags | StorageManager.FLAG_STORAGE_DE, false);
            } else {
                try {
                    Log.e(TAG, "prepareUserData failed", e);
                    RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed");
                    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);
                }
+8 −0
Original line number Diff line number Diff line
@@ -312,4 +312,12 @@ public abstract class UserManagerInternal {
     */
    public abstract void setDefaultCrossProfileIntentFilters(
            @UserIdInt int parentUserId, @UserIdInt int profileUserId);

    /**
     * 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);
}
+53 −0
Original line number Diff line number Diff line
@@ -211,6 +211,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";
@@ -320,6 +322,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;
        }
@@ -328,6 +338,25 @@ public class UserManagerService extends IUserManager.Stub {
            return mLastRequestQuietModeEnabledMillis;
        }

        boolean getIgnorePrepareStorageErrors() {
            return mIgnorePrepareStorageErrors;
        }

        @SuppressWarnings("AndroidFrameworkCompatChange")  // This is not an app-visible API.
        void setIgnorePrepareStorageErrors() {
            // This method won't be called for new users.  But to fully rule out
            // the possibility of mIgnorePrepareStorageErrors ever being true
            // for any user on any device that launched with T or later, we also
            // explicitly check that DEVICE_INITIAL_SDK_INT is below T before
            // honoring the request to set mIgnorePrepareStorageErrors to true.
            if (Build.VERSION.DEVICE_INITIAL_SDK_INT < Build.VERSION_CODES.TIRAMISU) {
                mIgnorePrepareStorageErrors = true;
                return;
            }
            Slog.w(LOG_TAG, "Not setting mIgnorePrepareStorageErrors to true"
                    + " since this is a new device");
        }

        void clearSeedAccountData() {
            seedAccountName = null;
            seedAccountType = null;
@@ -3408,6 +3437,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();
@@ -3517,6 +3550,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

        final TypedXmlPullParser parser = Xml.resolvePullParser(is);
        int type;
@@ -3595,6 +3629,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());
                    }
                }
            }
        }
@@ -3622,6 +3661,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) {
@@ -5732,6 +5774,9 @@ public class UserManagerService extends IUserManager.Stub {
                pw.println();
            }
        }

        pw.println("    Ignore errors preparing storage: "
                + userData.getIgnorePrepareStorageErrors());
    }

    private static void dumpTimeAgo(PrintWriter pw, StringBuilder sb, long nowTime, long time) {
@@ -6135,6 +6180,14 @@ public class UserManagerService extends IUserManager.Stub {
            UserManagerService.this.setDefaultCrossProfileIntentFilters(
                    profileUserId, userTypeDetails, restrictions, parentUserId);
        }

        @Override
        public boolean shouldIgnorePrepareStorageErrors(int userId) {
            synchronized (mUsersLock) {
                UserData userData = mUsers.get(userId);
                return userData != null && userData.getIgnorePrepareStorageErrors();
            }
        }
    }

    /**