From 2cffc7dafd390f6fe24a9fbb3ef3bc8226f5b385 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 14 Nov 2014 13:57:53 -0800 Subject: [PATCH 1/2] Warn user when build fingerprints differ. We're now shipping devices with several partitions which may end up mismatched, causing subtle runtime issues. To help manufacturers and users catch this case, show wanring when we detected mismatched fingerprints. Bug: 18357469 Change-Id: I897d7ee8cbf3b8042d3d7d282afab277d242ed3f --- core/java/android/os/Build.java | 29 ++++++++++ core/res/res/values/strings.xml | 6 ++ core/res/res/values/symbols.xml | 5 ++ .../server/am/ActivityManagerService.java | 55 ++++++++++++------- 4 files changed, 74 insertions(+), 21 deletions(-) diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index f361695b2fbd7..4b0cef6e5a120 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -20,8 +20,11 @@ import android.text.TextUtils; import android.util.Slog; import com.android.internal.telephony.TelephonyProperties; + import dalvik.system.VMRuntime; +import java.util.Objects; + /** * Information about the current build, extracted from system properties. */ @@ -640,6 +643,32 @@ public class Build { } } + /** + * Check that device fingerprint is defined and that it matches across + * various partitions. + * + * @hide + */ + public static boolean isFingerprintConsistent() { + final String system = SystemProperties.get("ro.build.fingerprint"); + final String vendor = SystemProperties.get("ro.vendor.build.fingerprint"); + + if (TextUtils.isEmpty(system)) { + Slog.e(TAG, "Required ro.build.fingerprint is empty!"); + return false; + } + + if (!TextUtils.isEmpty(vendor)) { + if (!Objects.equals(system, vendor)) { + Slog.e(TAG, "Mismatched fingerprints; system reported " + system + + " but vendor reported " + vendor); + return false; + } + } + + return true; + } + // The following properties only make sense for internal engineering builds. public static final long TIME = getLong("ro.build.date.utc") * 1000; public static final String USER = getString("ro.build.user"); diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 981c57652b4d9..c4b9c5f916c16 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5121,4 +5121,10 @@ Muted by %1$s + + + There\'s an internal problem with your device, and it may be unstable until you factory data reset. + + There\'s an internal problem with your device. Contact your manufacturer for details. + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c592f4962ac9a..f6d08363b2499 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2105,4 +2105,9 @@ + + + + + diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d0f5eeda2ee5a..86ca8cf7f4ffd 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1183,7 +1183,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int SERVICE_TIMEOUT_MSG = 12; static final int UPDATE_TIME_ZONE = 13; static final int SHOW_UID_ERROR_MSG = 14; - static final int IM_FEELING_LUCKY_MSG = 15; + static final int SHOW_FINGERPRINT_ERROR_MSG = 15; static final int PROC_START_TIMEOUT_MSG = 20; static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21; static final int KILL_APPLICATION_MSG = 22; @@ -1212,13 +1212,13 @@ public final class ActivityManagerService extends ActivityManagerNative static final int FINISH_BOOTING_MSG = 45; static final int START_USER_SWITCH_MSG = 46; static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47; + static final int DISMISS_DIALOG_MSG = 48; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; static final int FIRST_COMPAT_MODE_MSG = 300; static final int FIRST_SUPERVISOR_STACK_MSG = 100; - AlertDialog mUidAlert; CompatModeDialog mCompatModeDialog; long mLastMemUsageReportTime = 0; @@ -1447,27 +1447,27 @@ public final class ActivityManagerService extends ActivityManagerNative } } break; case SHOW_UID_ERROR_MSG: { - String title = "System UIDs Inconsistent"; - String text = "UIDs on the system are inconsistent, you need to wipe your" - + " data partition or your device will be unstable."; - Log.e(TAG, title + ": " + text); if (mShowDialogs) { - // XXX This is a temporary dialog, no need to localize. AlertDialog d = new BaseErrorDialog(mContext); d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); d.setCancelable(false); - d.setTitle(title); - d.setMessage(text); - d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky", - mHandler.obtainMessage(IM_FEELING_LUCKY_MSG)); - mUidAlert = d; + d.setTitle(mContext.getText(R.string.android_system_label)); + d.setMessage(mContext.getText(R.string.system_error_wipe_data)); + d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), + mHandler.obtainMessage(DISMISS_DIALOG_MSG, d)); d.show(); } } break; - case IM_FEELING_LUCKY_MSG: { - if (mUidAlert != null) { - mUidAlert.dismiss(); - mUidAlert = null; + case SHOW_FINGERPRINT_ERROR_MSG: { + if (mShowDialogs) { + AlertDialog d = new BaseErrorDialog(mContext); + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + d.setCancelable(false); + d.setTitle(mContext.getText(R.string.android_system_label)); + d.setMessage(mContext.getText(R.string.system_error_manufacturer)); + d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), + mHandler.obtainMessage(DISMISS_DIALOG_MSG, d)); + d.show(); } } break; case PROC_START_TIMEOUT_MSG: { @@ -1727,6 +1727,11 @@ public final class ActivityManagerService extends ActivityManagerNative } break; } + case DISMISS_DIALOG_MSG: { + final Dialog d = (Dialog) msg.obj; + d.dismiss(); + break; + } } } }; @@ -1776,7 +1781,8 @@ public final class ActivityManagerService extends ActivityManagerNative } } - int i=0, num=0; + int i = 0; + int num = 0; long[] tmp = new long[1]; do { ProcessRecord proc; @@ -11249,13 +11255,18 @@ public final class ActivityManagerService extends ActivityManagerNative try { if (AppGlobals.getPackageManager().hasSystemUidErrors()) { - Message msg = Message.obtain(); - msg.what = SHOW_UID_ERROR_MSG; - mHandler.sendMessage(msg); + Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your" + + " data partition or your device will be unstable."); + mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget(); } } catch (RemoteException e) { } + if (!Build.isFingerprintConsistent()) { + Slog.e(TAG, "Build fingerprint is not consistent, warning user"); + mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget(); + } + long ident = Binder.clearCallingIdentity(); try { Intent intent = new Intent(Intent.ACTION_USER_STARTED); @@ -13961,7 +13972,9 @@ public final class ActivityManagerService extends ActivityManagerNative ArrayList procMems = new ArrayList(); final SparseArray procMemsMap = new SparseArray(); - long nativePss=0, dalvikPss=0, otherPss=0; + long nativePss = 0; + long dalvikPss = 0; + long otherPss = 0; long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length]; From 6eb093909c5711f2482952e3d85dab66bad234c3 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 14 Nov 2014 15:57:59 -0800 Subject: [PATCH 2/2] Prevent user ID reuse until after reboot. We're still seeing rare cases where a device struggles to create a new user, probably because of a subtle bug in the FUSE daemon. To work around this, only allow user IDs reuse after reboot. Bug: 8302014 Change-Id: Id7f9fb539c6d6d1ff3d47d941af1d9e6b93eca03 --- .../android/server/pm/UserManagerService.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 0cf2249396c06..db0f53bf2f680 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1298,7 +1298,12 @@ public class UserManagerService extends IUserManager.Stub { if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) { return false; } + + // We remember deleted user IDs to prevent them from being + // reused during the current boot; they can still be reused + // after a reboot. mRemovingUserIds.put(userHandle, true); + try { mAppOpsService.removeUser(userHandle); } catch (RemoteException e) { @@ -1387,18 +1392,6 @@ public class UserManagerService extends IUserManager.Stub { // Remove this user from the list mUsers.remove(userHandle); - // Have user ID linger for several seconds to let external storage VFS - // cache entries expire. This must be greater than the 'entry_valid' - // timeout used by the FUSE daemon. - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - synchronized (mPackagesLock) { - mRemovingUserIds.delete(userHandle); - } - } - }, MINUTE_IN_MILLIS); - mRestrictionsPinStates.remove(userHandle); // Remove user file AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));