Merge "Add safety checks on KEY_INTENT mismatch." into qt-dev am: 459808b2c0 am: 64e4cbc1d8 am: ac02d51ea3 am: c3cde6206d am: 926e1629cb

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20105519

Change-Id: I3a6b174d8925ff17220621a561d6d9c8209fec70
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hao Ke
2022-10-05 21:43:46 +00:00
committed by Automerger Merge Worker

View File

@@ -88,6 +88,7 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.stats.devicepolicy.DevicePolicyEnums; import android.stats.devicepolicy.DevicePolicyEnums;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.util.Slog; import android.util.Slog;
@@ -3097,7 +3098,7 @@ public class AccountManagerService
*/ */
if (!checkKeyIntent( if (!checkKeyIntent(
Binder.getCallingUid(), Binder.getCallingUid(),
intent)) { result)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"invalid intent in bundle returned"); "invalid intent in bundle returned");
return; return;
@@ -3516,7 +3517,7 @@ public class AccountManagerService
&& (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
if (!checkKeyIntent( if (!checkKeyIntent(
Binder.getCallingUid(), Binder.getCallingUid(),
intent)) { result)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"invalid intent in bundle returned"); "invalid intent in bundle returned");
return; return;
@@ -4867,7 +4868,13 @@ public class AccountManagerService
* into launching arbitrary intents on the device via by tricking to click authenticator * into launching arbitrary intents on the device via by tricking to click authenticator
* supplied entries in the system Settings app. * 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 // Explicitly set an empty ClipData to ensure that we don't offer to
// promote any Uris contained inside for granting purposes // promote any Uris contained inside for granting purposes
if (intent.getClipData() == null) { 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) { private boolean isExportedSystemActivity(ActivityInfo activityInfo) {
String className = activityInfo.name; String className = activityInfo.name;
return "android".equals(activityInfo.packageName) && return "android".equals(activityInfo.packageName) &&
@@ -5050,7 +5076,7 @@ public class AccountManagerService
&& (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
if (!checkKeyIntent( if (!checkKeyIntent(
Binder.getCallingUid(), Binder.getCallingUid(),
intent)) { result)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"invalid intent in bundle returned"); "invalid intent in bundle returned");
return; return;