Merge changes from topic "unencrypted-dirs-r" into rvc-dev
* changes: [RESTRICT AUTOMERGE] Log to EventLog on prepareUserStorage failure [RESTRICT AUTOMERGE] Ignore errors preparing user storage for existing users [RESTRICT AUTOMERGE] UserDataPreparer: reboot to recovery for system user only [RESTRICT AUTOMERGE] UserDataPreparer: reboot to recovery if preparing user storage fails [RESTRICT AUTOMERGE] StorageManagerService: don't ignore failures to prepare user storage
This commit is contained in:
@@ -271,4 +271,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);
|
||||
}
|
||||
|
||||
@@ -131,6 +131,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;
|
||||
@@ -3381,7 +3382,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +197,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";
|
||||
@@ -297,6 +299,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;
|
||||
}
|
||||
@@ -305,6 +315,14 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return mLastRequestQuietModeEnabledMillis;
|
||||
}
|
||||
|
||||
boolean getIgnorePrepareStorageErrors() {
|
||||
return mIgnorePrepareStorageErrors;
|
||||
}
|
||||
|
||||
void setIgnorePrepareStorageErrors() {
|
||||
mIgnorePrepareStorageErrors = true;
|
||||
}
|
||||
|
||||
void clearSeedAccountData() {
|
||||
seedAccountName = null;
|
||||
seedAccountType = null;
|
||||
@@ -2928,6 +2946,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();
|
||||
@@ -3039,6 +3061,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());
|
||||
@@ -3126,6 +3149,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3152,6 +3180,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) {
|
||||
@@ -4771,6 +4802,9 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
|
||||
pw.println(" Ignore errors preparing storage: "
|
||||
+ userData.getIgnorePrepareStorageErrors());
|
||||
}
|
||||
}
|
||||
pw.println();
|
||||
@@ -5183,6 +5217,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user