diff options
author | Hao Ke <haok@google.com> | 2022-10-04 19:43:58 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-10-18 18:56:01 +0000 |
commit | 3a3063d4abc747ec2f49f7c7c3fa816e8b854d06 (patch) | |
tree | bdbbc03a4da4157f708d7260647f82d3d953e604 | |
parent | 1ddd72a3516f378b71d00b6567fa2b432daa3de8 (diff) | |
download | base-3a3063d4abc747ec2f49f7c7c3fa816e8b854d06.tar.gz |
Add safety checks on KEY_INTENT mismatch.
For many years, Parcel mismatch typed exploits has been using the
AccoungManagerService's passing of KEY_INTENT workflow, as a foothold of
launching arbitrary intents. We are adding an extra check on the service
side to simulate the final deserialization of the KEY_INTENT value, to
make sure the client side won't get a mismatched KEY_INTENT value.
Bug: 250588548
Bug: 240138294
Test: atest CtsAccountManagerTestCases
Test: local test, also see b/250588548
Change-Id: I433e34f6e21ce15c89825044a15b1dec46bb25cc
(cherry picked from commit eb9a0566a583fa13f8aff671c41f78a9e33eab82)
Merged-In: I433e34f6e21ce15c89825044a15b1dec46bb25cc
-rw-r--r-- | services/core/java/com/android/server/accounts/AccountManagerService.java | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index ae2f93449c86..a8672ff38e9d 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -88,6 +88,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.stats.devicepolicy.DevicePolicyEnums; import android.text.TextUtils; +import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -3097,7 +3098,7 @@ public class AccountManagerService */ if (!checkKeyIntent( Binder.getCallingUid(), - intent)) { + result)) { onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "invalid intent in bundle returned"); return; @@ -3516,7 +3517,7 @@ public class AccountManagerService && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { if (!checkKeyIntent( Binder.getCallingUid(), - intent)) { + result)) { onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "invalid intent in bundle returned"); return; @@ -4867,7 +4868,13 @@ public class AccountManagerService * into launching arbitrary intents on the device via by tricking to click authenticator * supplied entries in the system Settings app. */ - protected boolean checkKeyIntent(int authUid, Intent intent) { + protected boolean checkKeyIntent(int authUid, Bundle bundle) { + if (!checkKeyIntentParceledCorrectly(bundle)) { + EventLog.writeEvent(0x534e4554, "250588548", authUid, ""); + return false; + } + + Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT); // Explicitly set an empty ClipData to ensure that we don't offer to // promote any Uris contained inside for granting purposes if (intent.getClipData() == null) { @@ -4904,6 +4911,25 @@ public class AccountManagerService } } + /** + * Simulate the client side's deserialization of KEY_INTENT value, to make sure they don't + * violate our security policy. + * + * In particular we want to make sure the Authenticator doesn't trick users + * into launching arbitrary intents on the device via exploiting any other Parcel read/write + * mismatch problems. + */ + private boolean checkKeyIntentParceledCorrectly(Bundle bundle) { + Parcel p = Parcel.obtain(); + p.writeBundle(bundle); + p.setDataPosition(0); + Bundle simulateBundle = p.readBundle(); + p.recycle(); + Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT); + Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT); + return (intent.filterEquals(simulateIntent)); + } + private boolean isExportedSystemActivity(ActivityInfo activityInfo) { String className = activityInfo.name; return "android".equals(activityInfo.packageName) && @@ -5050,7 +5076,7 @@ public class AccountManagerService && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { if (!checkKeyIntent( Binder.getCallingUid(), - intent)) { + result)) { onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "invalid intent in bundle returned"); return; |