diff --git a/aosp_diff/preliminary/build/make/04_0004-Update-security_patch_level-string.patch b/aosp_diff/preliminary/build/make/04_0004-Update-security_patch_level-string.patch index afb9ccec64..178263906d 100644 --- a/aosp_diff/preliminary/build/make/04_0004-Update-security_patch_level-string.patch +++ b/aosp_diff/preliminary/build/make/04_0004-Update-security_patch_level-string.patch @@ -20,7 +20,7 @@ index 47bb92c142..2d0ac256a4 100644 # It must match one of the Android Security Patch Level strings of the Public Security Bulletins. # If there is no $PLATFORM_SECURITY_PATCH set, keep it empty. - PLATFORM_SECURITY_PATCH := 2022-02-05 -+ PLATFORM_SECURITY_PATCH := 2023-11-01 ++ PLATFORM_SECURITY_PATCH := 2023-12-01 endif .KATI_READONLY := PLATFORM_SECURITY_PATCH diff --git a/aosp_diff/preliminary/frameworks/av/29_0029-httplive-fix-use-after-free.bulletin.patch b/aosp_diff/preliminary/frameworks/av/29_0029-httplive-fix-use-after-free.bulletin.patch new file mode 100644 index 0000000000..f041ba31c6 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/av/29_0029-httplive-fix-use-after-free.bulletin.patch @@ -0,0 +1,107 @@ +From cfd4960f97e80809c0ae14b04547c18be6cd4b31 Mon Sep 17 00:00:00 2001 +From: Toni Heidenreich +Date: Wed, 6 Sep 2023 12:49:33 +0000 +Subject: [PATCH] httplive: fix use-after-free + +Implement a mutex to ensure secure multi-threaded +access to the KeyedVector in MetaDataBase. +Concurrent access by different threads can lead +to accessing the wrong memory location due to +potential changes in the vector + +Bug: 298057702 +Test: HTTP Live Streaming test +(cherry picked from https://partner-android-review.googlesource.com/q/commit:a2dfb31957a9d5358d0219a0eda7dcb5b0fff5fe) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:90fb4ca425444429ada6ce0de1c13d35829bc196) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3c1d9613ef64e01d2e81c4aa44c90dcd8ca958b9) +Merged-In: I46b05c85d9c39f4ce549efc160c08a0646c9fd0a +Change-Id: I46b05c85d9c39f4ce549efc160c08a0646c9fd0a +--- + media/libstagefright/foundation/MetaDataBase.cpp | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp +index 3f050ea6aa..aa6ca10967 100644 +--- a/media/libstagefright/foundation/MetaDataBase.cpp ++++ b/media/libstagefright/foundation/MetaDataBase.cpp +@@ -23,6 +23,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -78,6 +80,7 @@ struct MetaDataBase::Rect { + + + struct MetaDataBase::MetaDataInternal { ++ std::mutex mLock; + KeyedVector mItems; + }; + +@@ -102,10 +105,12 @@ MetaDataBase::~MetaDataBase() { + } + + void MetaDataBase::clear() { ++ std::lock_guard guard(mInternalData->mLock); + mInternalData->mItems.clear(); + } + + bool MetaDataBase::remove(uint32_t key) { ++ std::lock_guard guard(mInternalData->mLock); + ssize_t i = mInternalData->mItems.indexOfKey(key); + + if (i < 0) { +@@ -252,6 +257,7 @@ bool MetaDataBase::setData( + uint32_t key, uint32_t type, const void *data, size_t size) { + bool overwrote_existing = true; + ++ std::lock_guard guard(mInternalData->mLock); + ssize_t i = mInternalData->mItems.indexOfKey(key); + if (i < 0) { + typed_data item; +@@ -269,6 +275,7 @@ bool MetaDataBase::setData( + + bool MetaDataBase::findData(uint32_t key, uint32_t *type, + const void **data, size_t *size) const { ++ std::lock_guard guard(mInternalData->mLock); + ssize_t i = mInternalData->mItems.indexOfKey(key); + + if (i < 0) { +@@ -283,6 +290,7 @@ bool MetaDataBase::findData(uint32_t key, uint32_t *type, + } + + bool MetaDataBase::hasData(uint32_t key) const { ++ std::lock_guard guard(mInternalData->mLock); + ssize_t i = mInternalData->mItems.indexOfKey(key); + + if (i < 0) { +@@ -429,6 +437,7 @@ static void MakeFourCCString(uint32_t x, char *s) { + + String8 MetaDataBase::toString() const { + String8 s; ++ std::lock_guard guard(mInternalData->mLock); + for (int i = mInternalData->mItems.size(); --i >= 0;) { + int32_t key = mInternalData->mItems.keyAt(i); + char cc[5]; +@@ -443,6 +452,7 @@ String8 MetaDataBase::toString() const { + } + + void MetaDataBase::dumpToLog() const { ++ std::lock_guard guard(mInternalData->mLock); + for (int i = mInternalData->mItems.size(); --i >= 0;) { + int32_t key = mInternalData->mItems.keyAt(i); + char cc[5]; +@@ -455,6 +465,7 @@ void MetaDataBase::dumpToLog() const { + #if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__) + status_t MetaDataBase::writeToParcel(Parcel &parcel) { + status_t ret; ++ std::lock_guard guard(mInternalData->mLock); + size_t numItems = mInternalData->mItems.size(); + ret = parcel.writeUint32(uint32_t(numItems)); + if (ret) { +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/av/30_0030-Correct-attribution-source-for-MMAP-thread.bulletin.patch b/aosp_diff/preliminary/frameworks/av/30_0030-Correct-attribution-source-for-MMAP-thread.bulletin.patch new file mode 100644 index 0000000000..677e91103c --- /dev/null +++ b/aosp_diff/preliminary/frameworks/av/30_0030-Correct-attribution-source-for-MMAP-thread.bulletin.patch @@ -0,0 +1,54 @@ +From b4910062d576833cf0c99b3fb2f0e685faafc9d0 Mon Sep 17 00:00:00 2001 +From: Atneya Nair +Date: Wed, 10 May 2023 21:37:41 -0700 +Subject: [PATCH] Correct attribution source for MMAP thread + +Ensure that the package name, which is used for listening for appops +below getInputForAttr, is corrected for MMAP threads. + +Bug: 268724205 +Test: AudioRecordTest +Test: Oboetester MMAP record silenced when backgrounded - 6s +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f59db5cb1be38abce4c3c4f553090e527a6d4513) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5be19e855d2a9b772d43aacf0af2848d862a1b90) +Merged-In: Ia6fc1bff815bbbb2fee8bc1a60569a663a713e4b +Change-Id: Ia6fc1bff815bbbb2fee8bc1a60569a663a713e4b +--- + services/audioflinger/Threads.cpp | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp +index 7f2680014d..0c0c618e99 100644 +--- a/services/audioflinger/Threads.cpp ++++ b/services/audioflinger/Threads.cpp +@@ -9188,6 +9188,9 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, + audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE; + + audio_io_handle_t io = mId; ++ AttributionSourceState adjAttributionSource = AudioFlinger::checkAttributionSourcePackage( ++ client.attributionSource); ++ + if (isOutput()) { + audio_config_t config = AUDIO_CONFIG_INITIALIZER; + config.sample_rate = mSampleRate; +@@ -9201,7 +9204,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, + ret = AudioSystem::getOutputForAttr(&mAttr, &io, + mSessionId, + &stream, +- client.attributionSource, ++ adjAttributionSource, + &config, + flags, + &deviceId, +@@ -9218,7 +9221,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, + ret = AudioSystem::getInputForAttr(&mAttr, &io, + RECORD_RIID_INVALID, + mSessionId, +- client.attributionSource, ++ adjAttributionSource, + &config, + AUDIO_INPUT_FLAG_MMAP_NOIRQ, + &deviceId, +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/av/31_0031-Condition-background-record-restriction-on-Sdk.bulletin.patch b/aosp_diff/preliminary/frameworks/av/31_0031-Condition-background-record-restriction-on-Sdk.bulletin.patch new file mode 100644 index 0000000000..e5c9a56d80 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/av/31_0031-Condition-background-record-restriction-on-Sdk.bulletin.patch @@ -0,0 +1,78 @@ +From 302959a3f62dd7f4dcc5fac20d44ede9d09ff567 Mon Sep 17 00:00:00 2001 +From: Atneya Nair +Date: Wed, 9 Aug 2023 16:21:48 -0700 +Subject: [PATCH] Condition background record restriction on Sdk + +To prevent breaking existing apps, modify the checks around when +an app should have its recording silenced to retain prior behavior +unless an app has targetSdk U or greater. + +Test: oboetester conditionally restricted based on targetSdk level +Bug: 268724205 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc4f375d570965775634d90856719b812aee9865) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a5ed2002773feb3dd371cc473fc0a6ff2dfd21b6) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:382a9eaf46cf53b986494a694c9a87b8be8a28e4) +Merged-In: I42b6cbca60db6ce1a073254239b48e9104c4ebfb +Change-Id: I42b6cbca60db6ce1a073254239b48e9104c4ebfb +--- + .../service/AudioPolicyService.cpp | 26 +++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp +index 4d0e1f12a6..eb6666165d 100644 +--- a/services/audiopolicy/service/AudioPolicyService.cpp ++++ b/services/audiopolicy/service/AudioPolicyService.cpp +@@ -25,6 +25,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -77,6 +78,27 @@ static void destroyAudioPolicyManager(AudioPolicyInterface *interface) + { + delete interface; + } ++ ++namespace { ++int getTargetSdkForPackageName(std::string_view packageName) { ++ const auto binder = defaultServiceManager()->checkService(String16{"package_native"}); ++ int targetSdk = -1; ++ if (binder != nullptr) { ++ const auto pm = interface_cast(binder); ++ if (pm != nullptr) { ++ const auto status = pm->getTargetSdkVersionForPackage( ++ String16{packageName.data(), packageName.size()}, &targetSdk); ++ return status.isOk() ? targetSdk : -1; ++ } ++ } ++ return targetSdk; ++} ++ ++bool doesPackageTargetAtLeastU(std::string_view packageName) { ++ constexpr int ANDROID_API_U = 34; ++ return getTargetSdkForPackageName(packageName) >= ANDROID_API_U; ++} ++} // anonymous + // ---------------------------------------------------------------------------- + + AudioPolicyService::AudioPolicyService() +@@ -1482,10 +1504,14 @@ void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() + checkOp(); + mOpCallback = new RecordAudioOpCallback(this); + ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); ++ int flags = doesPackageTargetAtLeastU( ++ mAttributionSource.packageName.value_or("")) ? ++ AppOpsManager::WATCH_FOREGROUND_CHANGES : 0; + // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too + // since it controls the mic permission for legacy apps. + mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( + mAttributionSource.packageName.value_or(""))), ++ flags, + mOpCallback); + } + +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0209-On-device-lockdown-always-show-the-keyguard.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0209-On-device-lockdown-always-show-the-keyguard.bulletin.patch new file mode 100644 index 0000000000..481ddb9090 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0209-On-device-lockdown-always-show-the-keyguard.bulletin.patch @@ -0,0 +1,54 @@ +From f88afd13d35ee1d105ae538f990319de704d2741 Mon Sep 17 00:00:00 2001 +From: Beverly +Date: Mon, 8 May 2023 16:33:12 +0000 +Subject: [PATCH] On device lockdown, always show the keyguard + +Manual test steps: +1. Enable app pinning and disable "Ask for PIN before unpinning" setting +2. Pin an app (ie: Settings) +3. Lockdown from the power menu +Observe: user is brought to the keyguard, primary auth is required +to enter the device. After entering credential, the device is still in +app pinning mode. + +Test: atest KeyguardViewMediatorTest +Test: manual steps outlined above +Bug: 218495634 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b23c2d5fb6630ea0da503b937f62880594b13e94) +Merged-In: I9a7c5e1acadabd4484e58573331f98dba895f2a2 +Change-Id: I9a7c5e1acadabd4484e58573331f98dba895f2a2 +--- + .../systemui/keyguard/KeyguardViewMediator.java | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +index 37c26187176c..6cfd5e0ec5f8 100644 +--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java ++++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +@@ -678,6 +678,13 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, + notifyHasLockscreenWallpaperChanged(hasLockscreenWallpaper); + } + } ++ ++ @Override ++ public void onStrongAuthStateChanged(int userId) { ++ if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { ++ doKeyguardLocked(null); ++ } ++ } + }; + + ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() { +@@ -1524,7 +1531,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, + } + + // if another app is disabling us, don't show +- if (!mExternallyEnabled) { ++ if (!mExternallyEnabled ++ && !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); + + mNeedToReshowWhenReenabled = true; +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0210-Visit-Uris-added-by-WearableExtender.patch b/aosp_diff/preliminary/frameworks/base/99_0210-Visit-Uris-added-by-WearableExtender.patch new file mode 100644 index 0000000000..7bc386b631 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0210-Visit-Uris-added-by-WearableExtender.patch @@ -0,0 +1,98 @@ +From a58832bb0e337959a3d15a168fd4e695404d110a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= +Date: Wed, 5 Jul 2023 13:52:21 +0200 +Subject: [PATCH 01/14] Visit Uris added by WearableExtender + +Bug: 283962802 +Test: atest + manual (POC app now crashes on notify() as expected) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3d36966ea2aeebc3501a69a8ef7afce5ef593cee) +Merged-In: I0da18c631eb5e4844a48760c7aaedab715a0bfed +Change-Id: I0da18c631eb5e4844a48760c7aaedab715a0bfed +--- + core/java/android/app/Notification.java | 17 +++++++++++++++- + .../NotificationManagerServiceTest.java | 20 +++++++++++++++++++ + 2 files changed, 36 insertions(+), 1 deletion(-) + +diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java +index 0f918a8631b6..ae357755a1ca 100644 +--- a/core/java/android/app/Notification.java ++++ b/core/java/android/app/Notification.java +@@ -2092,6 +2092,10 @@ public class Notification implements Parcelable + } + } + ++ private void visitUris(@NonNull Consumer visitor) { ++ visitIconUri(visitor, getIcon()); ++ } ++ + @Override + public Action clone() { + return new Action( +@@ -2777,7 +2781,7 @@ public class Notification implements Parcelable + + if (actions != null) { + for (Action action : actions) { +- visitIconUri(visitor, action.getIcon()); ++ action.visitUris(visitor); + } + } + +@@ -2865,6 +2869,11 @@ public class Notification implements Parcelable + if (mBubbleMetadata != null) { + visitIconUri(visitor, mBubbleMetadata.getIcon()); + } ++ ++ if (extras != null && extras.containsKey(WearableExtender.EXTRA_WEARABLE_EXTENSIONS)) { ++ WearableExtender extender = new WearableExtender(this); ++ extender.visitUris(visitor); ++ } + } + + /** +@@ -11424,6 +11433,12 @@ public class Notification implements Parcelable + mFlags &= ~mask; + } + } ++ ++ private void visitUris(@NonNull Consumer visitor) { ++ for (Action action : mActions) { ++ action.visitUris(visitor); ++ } ++ } + } + + /** +diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +index c73e9cc28d0b..49700d78f320 100755 +--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java ++++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +@@ -4619,6 +4619,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { + verify(visitor, times(1)).accept(eq(largeIconPrivate.getUri())); + } + ++ @Test ++ public void testVisitUris_wearableExtender() { ++ Icon actionIcon = Icon.createWithContentUri("content://media/action"); ++ Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction"); ++ PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent(), ++ PendingIntent.FLAG_IMMUTABLE); ++ Notification n = new Notification.Builder(mContext, "a") ++ .setSmallIcon(android.R.drawable.sym_def_app_icon) ++ .addAction(new Notification.Action.Builder(actionIcon, "Hey!", intent).build()) ++ .extend(new Notification.WearableExtender().addAction( ++ new Notification.Action.Builder(wearActionIcon, "Wear!", intent).build())) ++ .build(); ++ ++ Consumer visitor = (Consumer) spy(Consumer.class); ++ n.visitUris(visitor); ++ ++ verify(visitor).accept(eq(actionIcon.getUri())); ++ verify(visitor).accept(eq(wearActionIcon.getUri())); ++ } ++ + @Test + public void testSetNotificationPolicy_preP_setOldFields() { + ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class); +-- +2.17.1 + diff --git a/aosp_diff/preliminary/frameworks/base/99_0211-Fix-bypass-BAL-via-requestGeofence-.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0211-Fix-bypass-BAL-via-requestGeofence-.bulletin.patch new file mode 100644 index 0000000000..a873492531 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0211-Fix-bypass-BAL-via-requestGeofence-.bulletin.patch @@ -0,0 +1,29 @@ +From 6726ac5596181d5f5a6dab6b038f1b9830462f3e Mon Sep 17 00:00:00 2001 +From: Lifu Tang +Date: Wed, 5 Jul 2023 13:03:00 -0700 +Subject: [PATCH] Fix bypass BAL via `requestGeofence` + +Bug: 273729172 +Test: manually +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7f9be7c3c859dc82d37452570d9878b58f6437a9) +Merged-In: Ia8094244f908b20d42711b6ea8f58f9b3345b563 +Change-Id: Ia8094244f908b20d42711b6ea8f58f9b3345b563 +--- + services/core/java/com/android/server/PendingIntentUtils.java | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/services/core/java/com/android/server/PendingIntentUtils.java b/services/core/java/com/android/server/PendingIntentUtils.java +index 1600101b20f4..a72a4d254a2a 100644 +--- a/services/core/java/com/android/server/PendingIntentUtils.java ++++ b/services/core/java/com/android/server/PendingIntentUtils.java +@@ -34,6 +34,7 @@ public class PendingIntentUtils { + public static Bundle createDontSendToRestrictedAppsBundle(@Nullable Bundle bundle) { + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setDontSendToRestrictedApps(true); ++ options.setPendingIntentBackgroundActivityLaunchAllowed(false); + if (bundle == null) { + return options.toBundle(); + } +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0212-Visit-Uris-related-to-Notification-style-extras.patch b/aosp_diff/preliminary/frameworks/base/99_0212-Visit-Uris-related-to-Notification-style-extras.patch new file mode 100644 index 0000000000..57664c0997 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0212-Visit-Uris-related-to-Notification-style-extras.patch @@ -0,0 +1,118 @@ +From 5ab69073e99febc34e1ae204f22a94cc341ffebf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= +Date: Fri, 11 Aug 2023 18:27:57 +0200 +Subject: [PATCH 02/13] Visit Uris related to Notification style extras + +Even if the corresponding styles themselves were not applied to the Notification.Builder. + +Test: atest NotificationManagerServiceTest +Bug: 287640400 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:87db980ca1270083a2ba3c7317402a0cd289fd65) +Merged-In: I25acab19be7dd486aabede8c91dbad5a1a217abf +Change-Id: I25acab19be7dd486aabede8c91dbad5a1a217abf +--- + core/java/android/app/Notification.java | 17 ++++---- + .../NotificationManagerServiceTest.java | 43 +++++++++++++++++++ + 2 files changed, 51 insertions(+), 9 deletions(-) + +diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java +index ae357755a1ca..15e755e20c64 100644 +--- a/core/java/android/app/Notification.java ++++ b/core/java/android/app/Notification.java +@@ -2811,11 +2811,6 @@ public class Notification implements Parcelable + } + } + +- final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON); +- if (person != null) { +- visitor.accept(person.getIconUri()); +- } +- + final RemoteInputHistoryItem[] history = getParcelableArrayFromBundle(extras, + Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, RemoteInputHistoryItem.class); + if (history != null) { +@@ -2826,9 +2821,14 @@ public class Notification implements Parcelable + } + } + } +- } + +- if (isStyle(MessagingStyle.class) && extras != null) { ++ // Extras for MessagingStyle. We visit them even if not isStyle(MessagingStyle), since ++ // Notification Listeners might use directly (without the isStyle check). ++ final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON); ++ if (person != null) { ++ visitor.accept(person.getIconUri()); ++ } ++ + final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES); + if (!ArrayUtils.isEmpty(messages)) { + for (MessagingStyle.Message message : MessagingStyle.Message +@@ -2856,9 +2856,8 @@ public class Notification implements Parcelable + } + + visitIconUri(visitor, extras.getParcelable(EXTRA_CONVERSATION_ICON)); +- } + +- if (isStyle(CallStyle.class) & extras != null) { ++ // Extras for CallStyle (same reason for visiting without checking isStyle). + Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON); + if (callPerson != null) { + visitor.accept(callPerson.getIconUri()); +diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +index 49700d78f320..148e42a9b55a 100755 +--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java ++++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +@@ -4619,6 +4619,49 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { + verify(visitor, times(1)).accept(eq(largeIconPrivate.getUri())); + } + ++ @Test ++ public void testVisitUris_styleExtrasWithoutStyle() { ++ Notification notification = new Notification.Builder(mContext, "a") ++ .setSmallIcon(android.R.drawable.sym_def_app_icon) ++ .build(); ++ ++ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle( ++ personWithIcon("content://user")) ++ .addHistoricMessage(new Notification.MessagingStyle.Message("Heyhey!", ++ System.currentTimeMillis(), ++ personWithIcon("content://historicalMessenger"))) ++ .addMessage(new Notification.MessagingStyle.Message("Are you there", ++ System.currentTimeMillis(), ++ personWithIcon("content://messenger"))) ++ .setShortcutIcon( ++ Icon.createWithContentUri("content://conversationShortcut")); ++ messagingStyle.addExtras(notification.extras); // Instead of Builder.setStyle(style). ++ ++ Notification.CallStyle callStyle = Notification.CallStyle.forOngoingCall( ++ personWithIcon("content://caller"), ++ PendingIntent.getActivity(mContext, 0, new Intent(), ++ PendingIntent.FLAG_IMMUTABLE)) ++ .setVerificationIcon(Icon.createWithContentUri("content://callVerification")); ++ callStyle.addExtras(notification.extras); // Same. ++ ++ Consumer visitor = (Consumer) spy(Consumer.class); ++ notification.visitUris(visitor); ++ ++ verify(visitor).accept(eq(Uri.parse("content://user"))); ++ verify(visitor).accept(eq(Uri.parse("content://historicalMessenger"))); ++ verify(visitor).accept(eq(Uri.parse("content://messenger"))); ++ verify(visitor).accept(eq(Uri.parse("content://conversationShortcut"))); ++ verify(visitor).accept(eq(Uri.parse("content://caller"))); ++ verify(visitor).accept(eq(Uri.parse("content://callVerification"))); ++ } ++ ++ private static Person personWithIcon(String iconUri) { ++ return new Person.Builder() ++ .setName("Mr " + iconUri) ++ .setIcon(Icon.createWithContentUri(iconUri)) ++ .build(); ++ } ++ + @Test + public void testVisitUris_wearableExtender() { + Icon actionIcon = Icon.createWithContentUri("content://media/action"); +-- +2.17.1 + diff --git a/aosp_diff/preliminary/frameworks/base/99_0213-RESTRICT-AUTOMERGE-Drop-invalid-data-.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0213-RESTRICT-AUTOMERGE-Drop-invalid-data-.bulletin.patch new file mode 100644 index 0000000000..4c1841c9a4 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0213-RESTRICT-AUTOMERGE-Drop-invalid-data-.bulletin.patch @@ -0,0 +1,126 @@ +From ae1a63390d4b7fc2152417ca2bdd2ef09c18598b Mon Sep 17 00:00:00 2001 +From: Kweku Adams +Date: Fri, 23 Sep 2022 21:06:53 +0000 +Subject: [PATCH] RESTRICT AUTOMERGE: Drop invalid data. + +Drop invalid data when writing or reading from XML. PersistableBundle +does lazy unparcelling, so checking the values during unparcelling would +remove the benefit of the lazy unparcelling. Checking the validity when +writing to or reading from XML seems like the best alternative. + +Bug: 246542285 +Bug: 247513680 +Test: install test app with invalid job config, start app to schedule job, then check logcat and jobscheduler persisted file +(cherry picked from commit 666e8ac60a31e2cc52b335b41004263f28a8db06) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0e0819c9d6a957e56764c89e68542bb51bdb7db4) +Merged-In: Ie817aa0993e9046cb313a750d2323cadc8c1ef15 +Change-Id: Ie817aa0993e9046cb313a750d2323cadc8c1ef15 +--- + core/java/android/os/PersistableBundle.java | 42 +++++++++++++++++---- + 1 file changed, 34 insertions(+), 8 deletions(-) + +diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java +index e5e9b5f6f53c..9718b52eafeb 100644 +--- a/core/java/android/os/PersistableBundle.java ++++ b/core/java/android/os/PersistableBundle.java +@@ -21,6 +21,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; + import android.annotation.NonNull; + import android.annotation.Nullable; + import android.util.ArrayMap; ++import android.util.Slog; + import android.util.TypedXmlPullParser; + import android.util.TypedXmlSerializer; + import android.util.Xml; +@@ -46,6 +47,8 @@ import java.util.ArrayList; + */ + public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable, + XmlUtils.WriteMapCallback { ++ private static final String TAG = "PersistableBundle"; ++ + private static final String TAG_PERSISTABLEMAP = "pbundle_as_map"; + + /** An unmodifiable {@code PersistableBundle} that is always {@link #isEmpty() empty}. */ +@@ -110,7 +113,11 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa + * @hide + */ + public PersistableBundle(Bundle b) { +- this(b.getMap()); ++ this(b, true); ++ } ++ ++ private PersistableBundle(Bundle b, boolean throwException) { ++ this(b.getMap(), throwException); + } + + /** +@@ -119,7 +126,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa + * @param map a Map containing only those items that can be persisted. + * @throws IllegalArgumentException if any element of #map cannot be persisted. + */ +- private PersistableBundle(ArrayMap map) { ++ private PersistableBundle(ArrayMap map, boolean throwException) { + super(); + mFlags = FLAG_DEFUSABLE; + +@@ -128,16 +135,23 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa + + // Now verify each item throwing an exception if there is a violation. + final int N = mMap.size(); +- for (int i=0; i= 0; --i) { + Object value = mMap.valueAt(i); + if (value instanceof ArrayMap) { + // Fix up any Maps by replacing them with PersistableBundles. +- mMap.setValueAt(i, new PersistableBundle((ArrayMap) value)); ++ mMap.setValueAt(i, ++ new PersistableBundle((ArrayMap) value, throwException)); + } else if (value instanceof Bundle) { +- mMap.setValueAt(i, new PersistableBundle(((Bundle) value))); ++ mMap.setValueAt(i, new PersistableBundle((Bundle) value, throwException)); + } else if (!isValidType(value)) { +- throw new IllegalArgumentException("Bad value in PersistableBundle key=" +- + mMap.keyAt(i) + " value=" + value); ++ final String errorMsg = "Bad value in PersistableBundle key=" ++ + mMap.keyAt(i) + " value=" + value; ++ if (throwException) { ++ throw new IllegalArgumentException(errorMsg); ++ } else { ++ Slog.wtfStack(TAG, errorMsg); ++ mMap.removeAt(i); ++ } + } + } + } +@@ -257,6 +271,15 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa + /** @hide */ + public void saveToXml(TypedXmlSerializer out) throws IOException, XmlPullParserException { + unparcel(); ++ // Explicitly drop invalid types an attacker may have added before persisting. ++ for (int i = mMap.size() - 1; i >= 0; --i) { ++ final Object value = mMap.valueAt(i); ++ if (!isValidType(value)) { ++ Slog.e(TAG, "Dropping bad data before persisting: " ++ + mMap.keyAt(i) + "=" + value); ++ mMap.removeAt(i); ++ } ++ } + XmlUtils.writeMapXml(mMap, out, this); + } + +@@ -311,9 +334,12 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa + while (((event = in.next()) != XmlPullParser.END_DOCUMENT) && + (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) { + if (event == XmlPullParser.START_TAG) { ++ // Don't throw an exception when restoring from XML since an attacker could try to ++ // input invalid data in the persisted file. + return new PersistableBundle((ArrayMap) + XmlUtils.readThisArrayMapXml(in, startTag, tagName, +- new MyReadMapCallback())); ++ new MyReadMapCallback()), ++ /* throwException */ false); + } + } + return EMPTY; +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0214-Validate-URI-based-shortcut-icon-at-creation-time-.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0214-Validate-URI-based-shortcut-icon-at-creation-time-.bulletin.patch new file mode 100644 index 0000000000..aa7c735bb2 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0214-Validate-URI-based-shortcut-icon-at-creation-time-.bulletin.patch @@ -0,0 +1,62 @@ +From 70cd64efdb577b6d8a3f4766b9a64f888abca639 Mon Sep 17 00:00:00 2001 +From: Pinyao Ting +Date: Wed, 12 Jul 2023 21:38:36 +0000 +Subject: [PATCH] Validate URI-based shortcut icon at creation time. + +Bug: 288113797 +Test: manual +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3d41fb7620ffb9c81b23977c8367c323e4721e65) +Merged-In: I392f8e923923bf40827a2b6207c4eaa262694fbc +Change-Id: I392f8e923923bf40827a2b6207c4eaa262694fbc +--- + .../android/server/pm/ShortcutService.java | 22 +++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java +index fd7da4b21066..64ba790c3361 100644 +--- a/services/core/java/com/android/server/pm/ShortcutService.java ++++ b/services/core/java/com/android/server/pm/ShortcutService.java +@@ -34,6 +34,7 @@ import android.app.usage.UsageStatsManagerInternal; + import android.appwidget.AppWidgetProviderInfo; + import android.content.BroadcastReceiver; + import android.content.ComponentName; ++import android.content.ContentProvider; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; +@@ -1887,11 +1888,32 @@ public class ShortcutService extends IShortcutService.Stub { + } + if (shortcut.getIcon() != null) { + ShortcutInfo.validateIcon(shortcut.getIcon()); ++ validateIconURI(shortcut); + } + + shortcut.replaceFlags(shortcut.getFlags() & ShortcutInfo.FLAG_LONG_LIVED); + } + ++ // Validates the calling process has permission to access shortcut icon's image uri ++ private void validateIconURI(@NonNull final ShortcutInfo si) { ++ final int callingUid = injectBinderCallingUid(); ++ final Icon icon = si.getIcon(); ++ if (icon == null) { ++ // There's no icon in this shortcut, nothing to validate here. ++ return; ++ } ++ int iconType = icon.getType(); ++ if (iconType != Icon.TYPE_URI && iconType != Icon.TYPE_URI_ADAPTIVE_BITMAP) { ++ // The icon is not URI-based, nothing to validate. ++ return; ++ } ++ final Uri uri = icon.getUri(); ++ mUriGrantsManagerInternal.checkGrantUriPermission(callingUid, si.getPackage(), ++ ContentProvider.getUriWithoutUserId(uri), ++ Intent.FLAG_GRANT_READ_URI_PERMISSION, ++ ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(callingUid))); ++ } ++ + private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) { + fixUpIncomingShortcutInfo(shortcut, forUpdate, /*forPinRequest=*/ false); + } +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0215-Disable-priority-conversation-widget-for-secondary-users.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0215-Disable-priority-conversation-widget-for-secondary-users.bulletin.patch new file mode 100644 index 0000000000..67594a2d39 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0215-Disable-priority-conversation-widget-for-secondary-users.bulletin.patch @@ -0,0 +1,506 @@ +From d76c64bca7c03a9bd3f058cb8db80e650e24364e Mon Sep 17 00:00:00 2001 +From: Julia Reynolds +Date: Fri, 4 Aug 2023 13:29:29 -0400 +Subject: [PATCH] Disable priority conversation widget for secondary users + +Test: NotificationConversationInfoTest.java +Test: make a conversation priority on the primary user +Test: make a conversation priority on a secondary user +Bug: 288896269 +(cherry picked from commit adf620316dcfaf19d7d4a73e2c63322b4a3a4d3a) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b0522df0a33d0165656797df7edab978cb403bd4) +Merged-In: I3f3991d2cb7fb9970cc8ada39ceae9a7ff2fcb31 +Change-Id: I3f3991d2cb7fb9970cc8ada39ceae9a7ff2fcb31 +--- + .../dagger/NotificationsModule.java | 3 + + .../row/NotificationConversationInfo.java | 11 ++- + .../row/NotificationGutsManager.java | 7 ++ + .../row/NotificationConversationInfoTest.java | 71 +++++++++++++++++++ + .../row/NotificationGutsManagerTest.java | 6 +- + 5 files changed, 95 insertions(+), 3 deletions(-) + +diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +index 6964838e7e41..b9db5b7644a4 100644 +--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java ++++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +@@ -21,6 +21,7 @@ import android.content.Context; + import android.content.pm.LauncherApps; + import android.content.pm.ShortcutManager; + import android.os.Handler; ++import android.os.UserManager; + import android.view.accessibility.AccessibilityManager; + + import com.android.internal.logging.UiEventLogger; +@@ -133,6 +134,7 @@ public interface NotificationsModule { + HighPriorityProvider highPriorityProvider, + INotificationManager notificationManager, + NotificationEntryManager notificationEntryManager, ++ UserManager userManager, + PeopleSpaceWidgetManager peopleSpaceWidgetManager, + LauncherApps launcherApps, + ShortcutManager shortcutManager, +@@ -152,6 +154,7 @@ public interface NotificationsModule { + highPriorityProvider, + notificationManager, + notificationEntryManager, ++ userManager, + peopleSpaceWidgetManager, + launcherApps, + shortcutManager, +diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +index 134f24e7e646..513447fd1315 100644 +--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java ++++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +@@ -48,6 +48,7 @@ import android.os.Bundle; + import android.os.Handler; + import android.os.RemoteException; + import android.os.UserHandle; ++import android.os.UserManager; + import android.service.notification.StatusBarNotification; + import android.text.TextUtils; + import android.transition.ChangeBounds; +@@ -118,6 +119,8 @@ public class NotificationConversationInfo extends LinearLayout implements + private NotificationGuts mGutsContainer; + private OnConversationSettingsClickListener mOnConversationSettingsClickListener; + ++ private UserManager mUm; ++ + @VisibleForTesting + boolean mSkipPost = false; + private int mActualHeight; +@@ -152,10 +155,12 @@ public class NotificationConversationInfo extends LinearLayout implements + mPressedApply = true; + + // If the user selected Priority and the previous selection was not priority, show a +- // People Tile add request. ++ // People Tile add request if for same profile group. + if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) { + mShadeController.animateCollapsePanels(); +- mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle()); ++ if (mUm.isSameProfileGroup(UserHandle.USER_SYSTEM, mSbn.getNormalizedUserId())) { ++ mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle()); ++ } + } + mGutsContainer.closeControls(v, true); + }; +@@ -189,6 +194,7 @@ public class NotificationConversationInfo extends LinearLayout implements + @Action int selectedAction, + ShortcutManager shortcutManager, + PackageManager pm, ++ UserManager um, + PeopleSpaceWidgetManager peopleSpaceWidgetManager, + INotificationManager iNotificationManager, + OnUserInteractionCallback onUserInteractionCallback, +@@ -214,6 +220,7 @@ public class NotificationConversationInfo extends LinearLayout implements + mEntry = entry; + mSbn = entry.getSbn(); + mPm = pm; ++ mUm = um; + mAppName = mPackageName; + mOnSettingsClickListener = onSettingsClick; + mNotificationChannel = notificationChannel; +diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +index 4319e29985d8..17f1fc419acf 100644 +--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java ++++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +@@ -31,6 +31,7 @@ import android.net.Uri; + import android.os.Bundle; + import android.os.Handler; + import android.os.UserHandle; ++import android.os.UserManager; + import android.provider.Settings; + import android.service.notification.StatusBarNotification; + import android.util.ArraySet; +@@ -124,6 +125,9 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx + private final INotificationManager mNotificationManager; + private final NotificationEntryManager mNotificationEntryManager; + private final PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; ++ ++ private final UserManager mUserManager; ++ + private final LauncherApps mLauncherApps; + private final ShortcutManager mShortcutManager; + private final UserContextProvider mContextTracker; +@@ -142,6 +146,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx + HighPriorityProvider highPriorityProvider, + INotificationManager notificationManager, + NotificationEntryManager notificationEntryManager, ++ UserManager userManager, + PeopleSpaceWidgetManager peopleSpaceWidgetManager, + LauncherApps launcherApps, + ShortcutManager shortcutManager, +@@ -160,6 +165,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx + mHighPriorityProvider = highPriorityProvider; + mNotificationManager = notificationManager; + mNotificationEntryManager = notificationEntryManager; ++ mUserManager = userManager; + mPeopleSpaceWidgetManager = peopleSpaceWidgetManager; + mLauncherApps = launcherApps; + mShortcutManager = shortcutManager; +@@ -482,6 +488,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx + notificationInfoView.getSelectedAction(), + mShortcutManager, + pmUser, ++ mUserManager, + mPeopleSpaceWidgetManager, + mNotificationManager, + mOnUserInteractionCallback, +diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +index dc6d744637b5..f76a40f99310 100644 +--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java ++++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +@@ -62,6 +62,7 @@ import android.graphics.drawable.Drawable; + import android.graphics.drawable.Icon; + import android.os.Handler; + import android.os.UserHandle; ++import android.os.UserManager; + import android.service.notification.StatusBarNotification; + import android.test.suitebuilder.annotation.SmallTest; + import android.testing.AndroidTestingRunner; +@@ -132,6 +133,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + @Mock + private PackageManager mMockPackageManager; + @Mock ++ private UserManager mUserManager; ++ @Mock + private OnUserInteractionCallback mOnUserInteractionCallback; + @Mock + private BubblesManager mBubblesManager; +@@ -239,6 +242,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -264,6 +268,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -317,6 +322,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -343,6 +349,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -368,6 +375,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -404,6 +412,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -430,6 +439,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -460,6 +470,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -485,6 +496,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -514,6 +526,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -543,6 +556,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -575,6 +589,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -613,6 +628,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -642,6 +658,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -678,6 +695,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -707,6 +725,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -752,6 +771,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -796,6 +816,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -841,6 +862,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -879,6 +901,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -916,6 +939,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -957,6 +981,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, // no action selected by default + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -988,6 +1013,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + NotificationConversationInfo.ACTION_FAVORITE, // "Favorite" selected by default + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1018,6 +1044,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1055,6 +1082,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1092,6 +1120,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1128,6 +1157,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1163,6 +1193,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1189,6 +1220,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1210,12 +1242,14 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + + @Test + public void testSelectPriorityRequestsPinPeopleTile() { ++ when(mUserManager.isSameProfileGroup(anyInt(), anyInt())).thenReturn(true); + //WHEN channel is default importance + mNotificationChannel.setImportantConversation(false); + mNotificationInfo.bindNotification( + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1241,12 +1275,48 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + verify(mPeopleSpaceWidgetManager, times(1)).requestPinAppWidget(any(), any()); + } + ++ @Test ++ public void testSelectPriorityRequestsPinPeopleTile_noMultiuser() { ++ when(mUserManager.isSameProfileGroup(anyInt(), anyInt())).thenReturn(false); ++ //WHEN channel is default importance ++ mNotificationChannel.setImportantConversation(false); ++ mNotificationInfo.bindNotification( ++ -1, ++ mShortcutManager, ++ mMockPackageManager, ++ mUserManager, ++ mPeopleSpaceWidgetManager, ++ mMockINotificationManager, ++ mOnUserInteractionCallback, ++ TEST_PACKAGE_NAME, ++ mNotificationChannel, ++ mEntry, ++ mBubbleMetadata, ++ null, ++ mIconFactory, ++ mContext, ++ true, ++ mTestHandler, ++ mTestHandler, null, Optional.of(mBubblesManager), ++ mShadeController); ++ ++ // WHEN user clicks "priority" ++ mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE); ++ ++ // and then done ++ mNotificationInfo.findViewById(R.id.done).performClick(); ++ ++ // No widget prompt; on a secondary user ++ verify(mPeopleSpaceWidgetManager, never()).requestPinAppWidget(any(), any()); ++ } ++ + @Test + public void testSelectDefaultDoesNotRequestPinPeopleTile() { + mNotificationInfo.bindNotification( + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +@@ -1282,6 +1352,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { + -1, + mShortcutManager, + mMockPackageManager, ++ mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, +diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +index 9f537f5b6afc..d052a1c84285 100644 +--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java ++++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +@@ -54,6 +54,7 @@ import android.content.pm.ShortcutManager; + import android.graphics.Color; + import android.os.Binder; + import android.os.Handler; ++import android.os.UserManager; + import android.provider.Settings; + import android.service.notification.StatusBarNotification; + import android.testing.AndroidTestingRunner; +@@ -141,6 +142,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase { + @Mock private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; + @Mock private AssistantFeedbackController mAssistantFeedbackController; + ++ @Mock private UserManager mUserManager; ++ + @Before + public void setUp() { + mTestableLooper = TestableLooper.get(this); +@@ -158,7 +161,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase { + + mGutsManager = new NotificationGutsManager(mContext, + () -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider, +- mINotificationManager, mNotificationEntryManager, mPeopleSpaceWidgetManager, ++ mINotificationManager, mNotificationEntryManager, mUserManager, ++ mPeopleSpaceWidgetManager, + mLauncherApps, mShortcutManager, mChannelEditorDialogController, mContextTracker, + mAssistantFeedbackController, Optional.of(mBubblesManager), + new UiEventLoggerFake(), mOnUserInteractionCallback, mShadeController); +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0216-Require-permission-to-unlock-keyguard.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0216-Require-permission-to-unlock-keyguard.bulletin.patch new file mode 100644 index 0000000000..a69140c2d9 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0216-Require-permission-to-unlock-keyguard.bulletin.patch @@ -0,0 +1,60 @@ +From 2b36798cc5c9a8fc5afa03103932feb6c01f9c19 Mon Sep 17 00:00:00 2001 +From: Marzia Favaro +Date: Mon, 31 Jul 2023 15:10:34 +0000 +Subject: [PATCH] Require permission to unlock keyguard + +Bug: 288896339 +Test: Manual, verify that the app which can be found on the bug can no longer call +keyguardGoingAway successfully + + +Require permission to unlock keyguard + +Bug: 288896339 +Test: Manual, verify that the app which can be found on the bug can no longer call +keyguardGoingAway successfully +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bd2aa5d309c5bf8e73161975bd5aba7945b25e84) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:be6ececad17f268b20cc252b29cbf3e848aef8ae) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7f28e3eaaf7c91c6b22ef89a9f18bfe081ba5b1e) +Merged-In: I7ba7e56f954c8e6f1f734311f735215918975bc6 +Change-Id: I7ba7e56f954c8e6f1f734311f735215918975bc6 +--- + core/java/android/app/IActivityTaskManager.aidl | 1 + + .../java/com/android/server/wm/ActivityTaskManagerService.java | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl +index 74d51a0bcf63..fa3a5d51f0cc 100644 +--- a/core/java/android/app/IActivityTaskManager.aidl ++++ b/core/java/android/app/IActivityTaskManager.aidl +@@ -245,6 +245,7 @@ interface IActivityTaskManager { + * {@link android.view.WindowManagerPolicyConstants#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE} + * etc. + */ ++ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD)") + void keyguardGoingAway(int flags); + + void suppressResizeConfigChanges(boolean suppress); +diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +index 987cff95bba3..bcb5e0db15e8 100644 +--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java ++++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +@@ -18,6 +18,7 @@ package com.android.server.wm; + + import static android.Manifest.permission.BIND_VOICE_INTERACTION; + import static android.Manifest.permission.CHANGE_CONFIGURATION; ++import static android.Manifest.permission.CONTROL_KEYGUARD; + import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; + import static android.Manifest.permission.INTERACT_ACROSS_USERS; + import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; +@@ -3312,6 +3313,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { + + @Override + public void keyguardGoingAway(int flags) { ++ mAmInternal.enforceCallingPermission(CONTROL_KEYGUARD, "unlock keyguard"); + enforceNotIsolatedCaller("keyguardGoingAway"); + final long token = Binder.clearCallingIdentity(); + try { +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0217-Restrict-number-of-shortcuts-can-be-added-through-addDynamicShor.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0217-Restrict-number-of-shortcuts-can-be-added-through-addDynamicShor.bulletin.patch new file mode 100644 index 0000000000..6ffca98cb6 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0217-Restrict-number-of-shortcuts-can-be-added-through-addDynamicShor.bulletin.patch @@ -0,0 +1,42 @@ +From d85791da431fc34b1454a01f2f839be9036c317c Mon Sep 17 00:00:00 2001 +From: Pinyao Ting +Date: Thu, 8 Jun 2023 14:38:19 -0700 +Subject: [PATCH] Restrict number of shortcuts can be added through + addDynamicShortcuts + +This CL fixes the issue where, when an app have multiple main +activities, the total number of shortcuts can grow indefinitely if they +were published through addDynamicShortcuts. + +Bug: 281061287 +Test: manual +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3215e73e36aa0463429226b5743ce24badf31227) +Merged-In: Ib3eecefee34517b670c59dd5b8526fe9eb24f463 +Change-Id: Ib3eecefee34517b670c59dd5b8526fe9eb24f463 +--- + services/core/java/com/android/server/pm/ShortcutPackage.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java +index e40075371910..1a71ca8d4e97 100644 +--- a/services/core/java/com/android/server/pm/ShortcutPackage.java ++++ b/services/core/java/com/android/server/pm/ShortcutPackage.java +@@ -359,6 +359,7 @@ class ShortcutPackage extends ShortcutPackageItem { + // Extract Icon and update the icon res ID and the bitmap path. + s.saveIconAndFixUpShortcutLocked(newShortcut); + s.fixUpShortcutResourceNamesAndValues(newShortcut); ++ ensureShortcutCountBeforePush(); + saveShortcut(newShortcut); + } + +@@ -405,7 +406,6 @@ class ShortcutPackage extends ShortcutPackageItem { + @NonNull List changedShortcuts) { + Preconditions.checkArgument(newShortcut.isEnabled(), + "pushDynamicShortcuts() cannot publish disabled shortcuts"); +- ensureShortcutCountBeforePush(); + + newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); + +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0218-Use-readUniqueFileDescriptor-in-incidentd-service.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0218-Use-readUniqueFileDescriptor-in-incidentd-service.bulletin.patch new file mode 100644 index 0000000000..ccc3ddf32b --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0218-Use-readUniqueFileDescriptor-in-incidentd-service.bulletin.patch @@ -0,0 +1,67 @@ +From 81496664cfc3fded06754721549665c681915b11 Mon Sep 17 00:00:00 2001 +From: Pawan Wagh +Date: Tue, 13 Jun 2023 17:37:26 +0000 +Subject: [PATCH] Use readUniqueFileDescriptor in incidentd service + +readFileDescriptor doesn't provide ownership of the fds. fdopen +needs ownership of the fds. Fds read from parcel should be duped +in this scenario and readUniqueFileDescriptor dups fds internally. + +Test: m incidentd_service_fuzzer && adb sync data && adb shell /data/fuzz/x86_64/incidentd_service_fuzzer/incidentd_service_fuzzer +Test: atest incidentd_test +Bug: 286931110 +Bug: 283699145 + +(cherry picked from commit ba78ef276951269f7b024baebdf1b8fa40bedb23) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:598dc664d4844363be12e0d164e1e522f92fa23f) +Merged-In: Ibe03a17dee91ac5bf25d123d4fd9c0bdd3c7d80e +Change-Id: Ibe03a17dee91ac5bf25d123d4fd9c0bdd3c7d80e +--- + cmds/incidentd/src/IncidentService.cpp | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp +index 13bf197aa9dc..421301adbff0 100644 +--- a/cmds/incidentd/src/IncidentService.cpp ++++ b/cmds/incidentd/src/IncidentService.cpp +@@ -500,9 +500,13 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* + + switch (code) { + case SHELL_COMMAND_TRANSACTION: { +- int in = data.readFileDescriptor(); +- int out = data.readFileDescriptor(); +- int err = data.readFileDescriptor(); ++ unique_fd in, out, err; ++ if (status_t status = data.readUniqueFileDescriptor(&in); status != OK) return status; ++ ++ if (status_t status = data.readUniqueFileDescriptor(&out); status != OK) return status; ++ ++ if (status_t status = data.readUniqueFileDescriptor(&err); status != OK) return status; ++ + int argc = data.readInt32(); + Vector args; + for (int i = 0; i < argc && data.dataAvail() > 0; i++) { +@@ -512,15 +516,15 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* + sp resultReceiver = + IResultReceiver::asInterface(data.readStrongBinder()); + +- FILE* fin = fdopen(in, "r"); +- FILE* fout = fdopen(out, "w"); +- FILE* ferr = fdopen(err, "w"); ++ FILE* fin = fdopen(in.release(), "r"); ++ FILE* fout = fdopen(out.release(), "w"); ++ FILE* ferr = fdopen(err.release(), "w"); + + if (fin == NULL || fout == NULL || ferr == NULL) { + resultReceiver->send(NO_MEMORY); + } else { +- err = command(fin, fout, ferr, args); +- resultReceiver->send(err); ++ status_t result = command(fin, fout, ferr, args); ++ resultReceiver->send(result); + } + + if (fin != NULL) { +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0219-Validate-userId-when-publishing-shortcuts.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0219-Validate-userId-when-publishing-shortcuts.bulletin.patch new file mode 100644 index 0000000000..02ac0ac47e --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0219-Validate-userId-when-publishing-shortcuts.bulletin.patch @@ -0,0 +1,32 @@ +From 3e64d4d941000081d7020f7911bb36e1517f500b Mon Sep 17 00:00:00 2001 +From: Pinyao Ting +Date: Mon, 24 Jul 2023 14:58:56 -0700 +Subject: [PATCH] Validate userId when publishing shortcuts + +Bug: 288110451 +Test: manual +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:01bfd04ff445db6290ae430d44ea1bf1a115fe3c) +Merged-In: Idbde676f871db83825155730e3714f3727e25762 +Change-Id: Idbde676f871db83825155730e3714f3727e25762 +--- + services/core/java/com/android/server/pm/ShortcutService.java | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java +index 64ba790c3361..e83f14fdadab 100644 +--- a/services/core/java/com/android/server/pm/ShortcutService.java ++++ b/services/core/java/com/android/server/pm/ShortcutService.java +@@ -1720,6 +1720,10 @@ public class ShortcutService extends IShortcutService.Stub { + android.util.EventLog.writeEvent(0x534e4554, "109824443", -1, ""); + throw new SecurityException("Shortcut package name mismatch"); + } ++ final int callingUid = injectBinderCallingUid(); ++ if (UserHandle.getUserId(callingUid) != si.getUserId()) { ++ throw new SecurityException("User-ID in shortcut doesn't match the caller"); ++ } + } + + private void verifyShortcutInfoPackages( +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0220-Revert-On-device-lockdown-always-show-the-keyguard-.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0220-Revert-On-device-lockdown-always-show-the-keyguard-.bulletin.patch new file mode 100644 index 0000000000..6547078747 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0220-Revert-On-device-lockdown-always-show-the-keyguard-.bulletin.patch @@ -0,0 +1,48 @@ +From 25240a9c6473f8f2bcb6a3d5048ec670ad364144 Mon Sep 17 00:00:00 2001 +From: Beverly Tai +Date: Thu, 14 Sep 2023 20:50:28 +0000 +Subject: [PATCH] Revert "On device lockdown, always show the keyguard" + +This reverts commit b23c2d5fb6630ea0da503b937f62880594b13e94. + +Reason for revert: b/300463732 regression +Bug: 300463732 +Bug: 218495634 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f57217125f2b124c16c463ef4507fb054cc1ba4f) +Merged-In: I31485d0d8caa3060e998636b071dbe03f6b4fc82 +Change-Id: I31485d0d8caa3060e998636b071dbe03f6b4fc82 +--- + .../systemui/keyguard/KeyguardViewMediator.java | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +index 27759a62094c..82dc0dff67b8 100644 +--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java ++++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +@@ -678,13 +678,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, + notifyHasLockscreenWallpaperChanged(hasLockscreenWallpaper); + } + } +- +- @Override +- public void onStrongAuthStateChanged(int userId) { +- if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { +- doKeyguardLocked(null); +- } +- } + }; + + ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() { +@@ -1531,8 +1524,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, + } + + // if another app is disabling us, don't show +- if (!mExternallyEnabled +- && !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { ++ if (!mExternallyEnabled) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); + + mNeedToReshowWhenReenabled = true; +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0221-Updated-always-show-the-keyguard-on-device-lockdown.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0221-Updated-always-show-the-keyguard-on-device-lockdown.bulletin.patch new file mode 100644 index 0000000000..6e8247dc2c --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0221-Updated-always-show-the-keyguard-on-device-lockdown.bulletin.patch @@ -0,0 +1,74 @@ +From a6bf6bdef5071a523ae5205d5a056dae26fa0d4a Mon Sep 17 00:00:00 2001 +From: Beverly Tai +Date: Tue, 19 Sep 2023 21:01:11 +0000 +Subject: [PATCH] Updated: always show the keyguard on device lockdown + +Additionally, don't hide keyguard when it's disabled if the user has locked +down the device. + +Manual test steps: + 1. Enable app pinning and disable "Ask for PIN before unpinning" setting + 2. Pin an app (ie: Settings) + 3. Lockdown from the power menu + 4. Observe: user is brought to the keyguard, primary auth is + required to enter the device. + => After entering correct credential, the device is still in + app pinning mode. + => After entering an incorrect credential, the keyguard remains + showing and the user can attempt again up to the limit + +Bug: 300463732 +Bug: 218495634 +Test: atest KeyguardViewMediatorTest +Test: manual +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:35a6e2f2c952440b1102033b2c3e496438503cff) +Merged-In: I70fdae80f717712b3dfc9df54b9649959b4bb8f0 +Change-Id: I70fdae80f717712b3dfc9df54b9649959b4bb8f0 +--- + .../systemui/keyguard/KeyguardViewMediator.java | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +index 82dc0dff67b8..807af1b1382d 100644 +--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java ++++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +@@ -663,6 +663,13 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, + } + } + ++ @Override ++ public void onStrongAuthStateChanged(int userId) { ++ if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { ++ doKeyguardLocked(null); ++ } ++ } ++ + @Override + public void onTrustChanged(int userId) { + if (userId == KeyguardUpdateMonitor.getCurrentUser()) { +@@ -1307,6 +1314,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, + mExternallyEnabled = enabled; + + if (!enabled && mShowing) { ++ if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { ++ Log.d(TAG, "keyguardEnabled(false) overridden by user lockdown"); ++ return; ++ } + if (mExitSecureCallback != null) { + if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring"); + // we're in the process of handling a request to verify the user +@@ -1523,8 +1534,9 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, + return; + } + +- // if another app is disabling us, don't show +- if (!mExternallyEnabled) { ++ // if another app is disabling us, don't show unless we're in lockdown mode ++ if (!mExternallyEnabled ++ && !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); + + mNeedToReshowWhenReenabled = true; +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0222-Move-startWatchingModeWithFlags-to-the-native-supported-binder-c.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0222-Move-startWatchingModeWithFlags-to-the-native-supported-binder-c.bulletin.patch new file mode 100644 index 0000000000..373ca5b2ca --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0222-Move-startWatchingModeWithFlags-to-the-native-supported-binder-c.bulletin.patch @@ -0,0 +1,41 @@ +From 1857ee3fd7e7386c09ced900538f02909726427e Mon Sep 17 00:00:00 2001 +From: Evan Severson +Date: Tue, 4 Apr 2023 14:49:26 -0700 +Subject: [PATCH] Move startWatchingModeWithFlags to the native supported + binder calls + +Bug: 247768581 +Test: Add logging to verify invocation +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b1f82ee37403e40513ef3b9e2657feb3871c4e71) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:fc85ac068d58f5cc690d5d587a46f6f691b0ce3a) +Merged-In: I54eefca5f0aa4f924debc1817b04a103b6e8e2e6 +Change-Id: I54eefca5f0aa4f924debc1817b04a103b6e8e2e6 +--- + core/java/com/android/internal/app/IAppOpsService.aidl | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl +index 88447daf7338..ff3c015cf66f 100644 +--- a/core/java/com/android/internal/app/IAppOpsService.aidl ++++ b/core/java/com/android/internal/app/IAppOpsService.aidl +@@ -52,6 +52,8 @@ interface IAppOpsService { + int checkAudioOperation(int code, int usage, int uid, String packageName); + boolean shouldCollectNotes(int opCode); + void setCameraAudioRestriction(int mode); ++ void startWatchingModeWithFlags(int op, String packageName, int flags, ++ IAppOpsCallback callback); + // End of methods also called by native code. + // Any new method exposed to native must be added after the last one, do not reorder + +@@ -110,8 +112,6 @@ interface IAppOpsService { + void startWatchingStarted(in int[] ops, IAppOpsStartedCallback callback); + void stopWatchingStarted(IAppOpsStartedCallback callback); + +- void startWatchingModeWithFlags(int op, String packageName, int flags, IAppOpsCallback callback); +- + void startWatchingNoted(in int[] ops, IAppOpsNotedCallback callback); + void stopWatchingNoted(IAppOpsNotedCallback callback); + +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0223-RESTRICT-AUTOMERGE-Check-URI-permissions-for-resumab.patch b/aosp_diff/preliminary/frameworks/base/99_0223-RESTRICT-AUTOMERGE-Check-URI-permissions-for-resumab.patch new file mode 100644 index 0000000000..62b6adefe8 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0223-RESTRICT-AUTOMERGE-Check-URI-permissions-for-resumab.patch @@ -0,0 +1,390 @@ +From c5ce680b74d8eb273c813643f5a130dd5ad1e04f Mon Sep 17 00:00:00 2001 +From: Beth Thibodeau +Date: Tue, 8 Aug 2023 16:19:48 -0500 +Subject: [PATCH] RESTRICT AUTOMERGE: Check URI permissions for resumable media + artwork + +When resumable media is added that has artwork set via URI, check the +permissions for the URI before attempting to load it + +Test: atest MediaDataManagerTest UriGrantsManagerServiceTest +Test: manual with test app +Bug: 284297452 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ffae193f19f902d4ae890be579cd44573feeaedc) +Merged-In: Ie79915d3d1712f08dc2e8dfbd5bc7fd32bb308a3 +Change-Id: Ie79915d3d1712f08dc2e8dfbd5bc7fd32bb308a3 +--- + core/java/android/app/IUriGrantsManager.aidl | 3 + + .../systemui/media/MediaDataManager.kt | 36 ++++- + .../systemui/media/MediaDataManagerTest.kt | 128 +++++++++++++++++- + .../server/uri/UriGrantsManagerService.java | 42 ++++++ + 4 files changed, 202 insertions(+), 7 deletions(-) + +diff --git a/core/java/android/app/IUriGrantsManager.aidl b/core/java/android/app/IUriGrantsManager.aidl +index 9e7f2fecfea0..b630d034dca9 100644 +--- a/core/java/android/app/IUriGrantsManager.aidl ++++ b/core/java/android/app/IUriGrantsManager.aidl +@@ -39,4 +39,7 @@ interface IUriGrantsManager { + void clearGrantedUriPermissions(in String packageName, int userId); + ParceledListSlice getUriPermissions(in String packageName, boolean incoming, + boolean persistedOnly); ++ ++ int checkGrantUriPermission_ignoreNonSystem( ++ int sourceUid, String targetPkg, in Uri uri, int modeFlags, int userId); + } +diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +index ab98869132de..699a79cbfbad 100644 +--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt ++++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +@@ -18,15 +18,18 @@ package com.android.systemui.media + + import android.app.Notification + import android.app.PendingIntent ++import android.app.UriGrantsManager + import android.app.smartspace.SmartspaceConfig + import android.app.smartspace.SmartspaceManager + import android.app.smartspace.SmartspaceSession + import android.app.smartspace.SmartspaceTarget + import android.content.BroadcastReceiver ++import android.content.ContentProvider + import android.content.ContentResolver + import android.content.Context + import android.content.Intent + import android.content.IntentFilter ++import android.content.pm.PackageManager + import android.graphics.Bitmap + import android.graphics.Canvas + import android.graphics.ImageDecoder +@@ -38,6 +41,7 @@ import android.media.session.MediaController + import android.media.session.MediaSession + import android.net.Uri + import android.os.Parcelable ++import android.os.Process + import android.os.UserHandle + import android.provider.Settings + import android.service.notification.StatusBarNotification +@@ -497,7 +501,13 @@ class MediaDataManager( + // Album art + var artworkBitmap = desc.iconBitmap + if (artworkBitmap == null && desc.iconUri != null) { +- artworkBitmap = loadBitmapFromUri(desc.iconUri!!) ++ val appUid = try { ++ context.packageManager.getApplicationInfo(packageName, 0)?.uid!! ++ } catch (e: PackageManager.NameNotFoundException) { ++ Log.w(TAG, "Could not get app UID for $packageName", e) ++ Process.INVALID_UID ++ } ++ artworkBitmap = loadBitmapFromUriForUser(desc.iconUri!!, userId, appUid, packageName) + } + val artworkIcon = if (artworkBitmap != null) { + Icon.createWithBitmap(artworkBitmap) +@@ -674,6 +684,30 @@ class MediaDataManager( + false + } + } ++ ++ /** Returns a bitmap if the user can access the given URI, else null */ ++ private fun loadBitmapFromUriForUser( ++ uri: Uri, ++ userId: Int, ++ appUid: Int, ++ packageName: String, ++ ): Bitmap? { ++ try { ++ val ugm = UriGrantsManager.getService() ++ ugm.checkGrantUriPermission_ignoreNonSystem( ++ appUid, ++ packageName, ++ ContentProvider.getUriWithoutUserId(uri), ++ Intent.FLAG_GRANT_READ_URI_PERMISSION, ++ ContentProvider.getUserIdFromUri(uri, userId) ++ ) ++ return loadBitmapFromUri(uri) ++ } catch (e: SecurityException) { ++ Log.e(TAG, "Failed to get URI permission: $e") ++ } ++ return null ++ } ++ + /** + * Load a bitmap from a URI + * @param uri the uri to load +diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +index e6d3c8a6c04e..d6ee9dda3efb 100644 +--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt ++++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +@@ -1,21 +1,26 @@ + package com.android.systemui.media + ++import android.app.IUriGrantsManager + import android.app.Notification.MediaStyle + import android.app.PendingIntent ++import android.app.UriGrantsManager + import android.app.smartspace.SmartspaceAction + import android.app.smartspace.SmartspaceTarget + import android.content.Intent + import android.graphics.Bitmap ++import android.graphics.ImageDecoder + import android.media.MediaDescription + import android.media.MediaMetadata + import android.media.session.MediaController + import android.media.session.MediaSession ++import android.net.Uri + import android.os.Bundle + import android.provider.Settings + import android.service.notification.StatusBarNotification + import android.testing.AndroidTestingRunner + import android.testing.TestableLooper.RunWithLooper + import androidx.test.filters.SmallTest ++import com.android.dx.mockito.inline.extended.ExtendedMockito + import com.android.systemui.R + import com.android.systemui.SysuiTestCase + import com.android.systemui.broadcast.BroadcastDispatcher +@@ -24,6 +29,7 @@ import com.android.systemui.plugins.ActivityStarter + import com.android.systemui.statusbar.SbnBuilder + import com.android.systemui.tuner.TunerService + import com.android.systemui.util.concurrency.FakeExecutor ++import com.android.systemui.util.mockito.any + import com.android.systemui.util.mockito.capture + import com.android.systemui.util.mockito.eq + import com.android.systemui.util.time.FakeSystemClock +@@ -35,6 +41,7 @@ import org.junit.Test + import org.junit.runner.RunWith + import org.mockito.ArgumentCaptor + import org.mockito.ArgumentMatchers.anyBoolean ++import org.mockito.ArgumentMatchers.anyInt + import org.mockito.Captor + import org.mockito.Mock + import org.mockito.Mockito +@@ -42,8 +49,10 @@ import org.mockito.Mockito.mock + import org.mockito.Mockito.never + import org.mockito.Mockito.reset + import org.mockito.Mockito.verify ++import org.mockito.MockitoSession + import org.mockito.junit.MockitoJUnit + import org.mockito.Mockito.`when` as whenever ++import org.mockito.quality.Strictness + + private const val KEY = "KEY" + private const val KEY_2 = "KEY_2" +@@ -95,12 +104,23 @@ class MediaDataManagerTest : SysuiTestCase() { + private val clock = FakeSystemClock() + @Mock private lateinit var tunerService: TunerService + @Captor lateinit var tunableCaptor: ArgumentCaptor ++ @Mock private lateinit var ugm: IUriGrantsManager ++ @Mock private lateinit var imageSource: ImageDecoder.Source + + private val originalSmartspaceSetting = Settings.Secure.getInt(context.contentResolver, + Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 1) + ++ private lateinit var staticMockSession: MockitoSession ++ + @Before + fun setup() { ++ staticMockSession = ++ ExtendedMockito.mockitoSession() ++ .mockStatic(UriGrantsManager::class.java) ++ .mockStatic(ImageDecoder::class.java) ++ .strictness(Strictness.LENIENT) ++ .startMocking() ++ whenever(UriGrantsManager.getService()).thenReturn(ugm) + foregroundExecutor = FakeExecutor(clock) + backgroundExecutor = FakeExecutor(clock) + smartspaceMediaDataProvider = SmartspaceMediaDataProvider() +@@ -166,6 +186,7 @@ class MediaDataManagerTest : SysuiTestCase() { + + @After + fun tearDown() { ++ staticMockSession.finishMocking() + session.release() + mediaDataManager.destroy() + Settings.Secure.putInt(context.contentResolver, +@@ -174,12 +195,9 @@ class MediaDataManagerTest : SysuiTestCase() { + + @Test + fun testSetTimedOut_active_deactivatesMedia() { +- val data = MediaData(userId = USER_ID, initialized = true, backgroundColor = 0, app = null, +- appIcon = null, artist = null, song = null, artwork = null, actions = emptyList(), +- actionsToShowInCompact = emptyList(), packageName = "INVALID", token = null, +- clickIntent = null, device = null, active = true, resumeAction = null) +- mediaDataManager.onNotificationAdded(KEY, mediaNotification) +- mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = data) ++ addNotificationAndLoad() ++ val data = mediaDataCaptor.value ++ assertThat(data.active).isTrue() + + mediaDataManager.setTimedOut(KEY, timedOut = true) + assertThat(data.active).isFalse() +@@ -626,4 +644,102 @@ class MediaDataManagerTest : SysuiTestCase() { + assertThat(mediaDataCaptor.value.actionsToShowInCompact.size).isEqualTo( + MediaDataManager.MAX_COMPACT_ACTIONS) + } ++ ++ @Test ++ fun testResumeMediaLoaded_hasArtPermission_artLoaded() { ++ // When resume media is loaded and user/app has permission to access the art URI, ++ whenever( ++ ugm.checkGrantUriPermission_ignoreNonSystem( ++ anyInt(), ++ any(), ++ any(), ++ anyInt(), ++ anyInt() ++ ) ++ ) ++ .thenReturn(1) ++ val artwork = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) ++ val uri = Uri.parse("content://example") ++ whenever(ImageDecoder.createSource(any(), eq(uri))).thenReturn(imageSource) ++ whenever(ImageDecoder.decodeBitmap(any(), any())).thenReturn(artwork) ++ ++ val desc = ++ MediaDescription.Builder().run { ++ setTitle(SESSION_TITLE) ++ setIconUri(uri) ++ build() ++ } ++ addResumeControlAndLoad(desc) ++ ++ // Then the artwork is loaded ++ assertThat(mediaDataCaptor.value.artwork).isNotNull() ++ } ++ ++ @Test ++ fun testResumeMediaLoaded_noArtPermission_noArtLoaded() { ++ // When resume media is loaded and user/app does not have permission to access the art URI ++ whenever( ++ ugm.checkGrantUriPermission_ignoreNonSystem( ++ anyInt(), ++ any(), ++ any(), ++ anyInt(), ++ anyInt() ++ ) ++ ) ++ .thenThrow(SecurityException("Test no permission")) ++ val artwork = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) ++ val uri = Uri.parse("content://example") ++ whenever(ImageDecoder.createSource(any(), eq(uri))).thenReturn(imageSource) ++ whenever(ImageDecoder.decodeBitmap(any(), any())).thenReturn(artwork) ++ ++ val desc = ++ MediaDescription.Builder().run { ++ setTitle(SESSION_TITLE) ++ setIconUri(uri) ++ build() ++ } ++ addResumeControlAndLoad(desc) ++ ++ // Then the artwork is not loaded ++ assertThat(mediaDataCaptor.value.artwork).isNull() ++ } ++ ++ /** ++ * Helper function to add a media notification and capture the resulting MediaData ++ */ ++ private fun addNotificationAndLoad() { ++ mediaDataManager.onNotificationAdded(KEY, mediaNotification) ++ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) ++ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) ++ verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), ++ eq(false)) ++ } ++ ++ /** Helper function to add a resumption control and capture the resulting MediaData */ ++ private fun addResumeControlAndLoad( ++ desc: MediaDescription, ++ packageName: String = PACKAGE_NAME ++ ) { ++ mediaDataManager.addResumptionControls( ++ USER_ID, ++ desc, ++ Runnable {}, ++ session.sessionToken, ++ APP_NAME, ++ pendingIntent, ++ packageName ++ ) ++ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) ++ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) ++ ++ verify(listener) ++ .onMediaDataLoaded( ++ eq(packageName), ++ eq(null), ++ capture(mediaDataCaptor), ++ eq(true), ++ eq(false) ++ ) ++ } + } +diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java +index 4e453f378cbc..d261e7f4c9ec 100644 +--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java ++++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java +@@ -41,6 +41,7 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG; + + import android.annotation.NonNull; + import android.annotation.Nullable; ++import android.annotation.RequiresPermission; + import android.app.ActivityManager; + import android.app.ActivityManagerInternal; + import android.app.AppGlobals; +@@ -62,6 +63,7 @@ import android.os.Handler; + import android.os.IBinder; + import android.os.Looper; + import android.os.Message; ++import android.os.Process; + import android.os.RemoteException; + import android.os.SystemClock; + import android.os.UserHandle; +@@ -1302,6 +1304,46 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { + return false; + } + ++ /** ++ * Check if the targetPkg can be granted permission to access uri by ++ * the callingUid using the given modeFlags. See {@link #checkGrantUriPermissionUnlocked}. ++ * ++ * @param callingUid The uid of the grantor app that has permissions to the uri. ++ * @param targetPkg The package name of the granted app that needs permissions to the uri. ++ * @param uri The uri for which permissions should be granted. ++ * @param modeFlags The modes to grant. See {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}, etc. ++ * @param userId The userId in which the uri is to be resolved. ++ * @return uid of the target or -1 if permission grant not required. Returns -1 if the caller ++ * does not hold INTERACT_ACROSS_USERS_FULL ++ * @throws SecurityException if the grant is not allowed. ++ */ ++ @Override ++ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) ++ public int checkGrantUriPermission_ignoreNonSystem(int callingUid, String targetPkg, Uri uri, ++ int modeFlags, int userId) { ++ if (!isCallerIsSystemOrPrivileged()) { ++ return Process.INVALID_UID; ++ } ++ final long origId = Binder.clearCallingIdentity(); ++ try { ++ return checkGrantUriPermissionUnlocked(callingUid, targetPkg, uri, modeFlags, ++ userId); ++ } finally { ++ Binder.restoreCallingIdentity(origId); ++ } ++ } ++ ++ private boolean isCallerIsSystemOrPrivileged() { ++ final int uid = Binder.getCallingUid(); ++ if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) { ++ return true; ++ } ++ return ActivityManager.checkComponentPermission( ++ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, ++ uid, /* owningUid = */-1, /* exported = */ true) ++ == PackageManager.PERMISSION_GRANTED; ++ } ++ + @GuardedBy("mLock") + private void writeGrantedUriPermissionsLocked() { + if (DEBUG) Slog.v(TAG, "writeGrantedUriPermissions()"); +-- +2.17.1 + diff --git a/aosp_diff/preliminary/frameworks/native/20_0020-Add-AppOps-overload-to-be-able-to-watch-foreground-changes-.bulletin.patch b/aosp_diff/preliminary/frameworks/native/20_0020-Add-AppOps-overload-to-be-able-to-watch-foreground-changes-.bulletin.patch new file mode 100644 index 0000000000..c44cc4f20f --- /dev/null +++ b/aosp_diff/preliminary/frameworks/native/20_0020-Add-AppOps-overload-to-be-able-to-watch-foreground-changes-.bulletin.patch @@ -0,0 +1,110 @@ +From a59266f3ee1cca5a75028b72769b7d7fb1d2f11c Mon Sep 17 00:00:00 2001 +From: Evan Severson +Date: Tue, 4 Apr 2023 14:46:06 -0700 +Subject: [PATCH] Add AppOps overload to be able to watch foreground changes. + +We have never offered the native API to register mode watchers that are +invoked for foregroundness changes when the raw mode is MODE_FOREGROUND. + +Test: Add logging to verify invocation +Bug: 247768581 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:949cb3d098fd98715826fc92ea3c26a51aa2d976) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:130ff33dfeb3c0702636db090399f114fde86174) +Merged-In: I89af46de557fbfc31d69613367a4e26a5222430a +Change-Id: I89af46de557fbfc31d69613367a4e26a5222430a +--- + libs/permission/AppOpsManager.cpp | 8 ++++++++ + libs/permission/IAppOpsService.cpp | 11 +++++++++++ + libs/permission/include/binder/AppOpsManager.h | 6 ++++++ + libs/permission/include/binder/IAppOpsService.h | 3 +++ + 4 files changed, 28 insertions(+) + +diff --git a/libs/permission/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp +index baa9d7511..695927418 100644 +--- a/libs/permission/AppOpsManager.cpp ++++ b/libs/permission/AppOpsManager.cpp +@@ -146,6 +146,14 @@ void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName, + } + } + ++void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName, int32_t flags, ++ const sp& callback) { ++ sp service = getService(); ++ if (service != nullptr) { ++ service->startWatchingModeWithFlags(op, packageName, flags, callback); ++ } ++} ++ + void AppOpsManager::stopWatchingMode(const sp& callback) { + sp service = getService(); + if (service != nullptr) { +diff --git a/libs/permission/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp +index d59f44562..7f235a454 100644 +--- a/libs/permission/IAppOpsService.cpp ++++ b/libs/permission/IAppOpsService.cpp +@@ -166,6 +166,17 @@ public: + } + return reply.readBool(); + } ++ ++ virtual void startWatchingModeWithFlags(int32_t op, const String16& packageName, ++ int32_t flags, const sp& callback) { ++ Parcel data, reply; ++ data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor()); ++ data.writeInt32(op); ++ data.writeString16(packageName); ++ data.writeInt32(flags); ++ data.writeStrongBinder(IInterface::asBinder(callback)); ++ remote()->transact(START_WATCHING_MODE_WITH_FLAGS_TRANSACTION, data, &reply); ++ } + }; + + IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService") +diff --git a/libs/permission/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h +index e3d705fa3..97b91ed52 100644 +--- a/libs/permission/include/binder/AppOpsManager.h ++++ b/libs/permission/include/binder/AppOpsManager.h +@@ -150,6 +150,10 @@ public: + _NUM_OP = 116 + }; + ++ enum { ++ WATCH_FOREGROUND_CHANGES = 1 << 0 ++ }; ++ + AppOpsManager(); + + int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage); +@@ -173,6 +177,8 @@ public: + const std::optional& attributionTag); + void startWatchingMode(int32_t op, const String16& packageName, + const sp& callback); ++ void startWatchingMode(int32_t op, const String16& packageName, int32_t flags, ++ const sp& callback); + void stopWatchingMode(const sp& callback); + int32_t permissionToOpCode(const String16& permission); + void setCameraAudioRestriction(int32_t mode); +diff --git a/libs/permission/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h +index 22f056b23..918fcdbce 100644 +--- a/libs/permission/include/binder/IAppOpsService.h ++++ b/libs/permission/include/binder/IAppOpsService.h +@@ -52,6 +52,8 @@ public: + const String16& packageName) = 0; + virtual void setCameraAudioRestriction(int32_t mode) = 0; + virtual bool shouldCollectNotes(int32_t opCode) = 0; ++ virtual void startWatchingModeWithFlags(int32_t op, const String16& packageName, ++ int32_t flags, const sp& callback) = 0; + + enum { + CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, +@@ -64,6 +66,7 @@ public: + CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7, + SHOULD_COLLECT_NOTES_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8, + SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+9, ++ START_WATCHING_MODE_WITH_FLAGS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+10, + }; + + enum { +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/packages/apps/Bluetooth/04_0004-Fix-UAF-in-CallbackEnv.bulletin.patch b/aosp_diff/preliminary/packages/apps/Bluetooth/04_0004-Fix-UAF-in-CallbackEnv.bulletin.patch new file mode 100644 index 0000000000..7524d55fa9 --- /dev/null +++ b/aosp_diff/preliminary/packages/apps/Bluetooth/04_0004-Fix-UAF-in-CallbackEnv.bulletin.patch @@ -0,0 +1,41 @@ +From 4b614b162bb4d21ee6df2a8b850cb0bed40313eb Mon Sep 17 00:00:00 2001 +From: Brian Delwiche +Date: Thu, 5 Oct 2023 00:01:03 +0000 +Subject: [PATCH] Fix UAF in ~CallbackEnv + +com_android_bluetooth_btservice_AdapterService does not null its local +JNI environment variable after detaching the thread (which frees the +environment context), allowing UAF under certain conditions. + +Null the variable in this case. + +Testing here was done through a custom unit test; see patchsets 4-6 for +contents. However, unit testing of the JNI layer is problematic in +production, so that part of the patch is omitted for final merge. + +Bug: 291500341 +Test: atest bluetooth_test_gd_unit, atest net_test_stack_btm +Tag: #security +Ignore-AOSP-First: Security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5f543d919c4067f2f4925580fd8a690ba3440e80) +Merged-In: I3e5e3c51412640aa19f0981caaa809313d6ad030 +Change-Id: I3e5e3c51412640aa19f0981caaa809313d6ad030 +--- + jni/com_android_bluetooth_btservice_AdapterService.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp +index 62c7d522d..e26171ef8 100644 +--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp ++++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp +@@ -582,6 +582,7 @@ static void callback_thread_event(bt_cb_thread_evt event) { + } + vm->DetachCurrentThread(); + sHaveCallbackThread = false; ++ callbackEnv = NULL; + } + } + +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/packages/apps/Launcher3/03_0003-Fix-permission-bypass-in-legacy-shortcut.bulletin.patch b/aosp_diff/preliminary/packages/apps/Launcher3/03_0003-Fix-permission-bypass-in-legacy-shortcut.bulletin.patch new file mode 100644 index 0000000000..d95404ca3c --- /dev/null +++ b/aosp_diff/preliminary/packages/apps/Launcher3/03_0003-Fix-permission-bypass-in-legacy-shortcut.bulletin.patch @@ -0,0 +1,43 @@ +From 8a0d866766ef66f6a337ee0eae33675fc5a83fa8 Mon Sep 17 00:00:00 2001 +From: Pinyao Ting +Date: Tue, 12 Sep 2023 22:37:16 +0000 +Subject: [PATCH] Fix permission bypass in legacy shortcut + +Intent created for Chooser should not be allowed in legacy shortcuts +since it doesn't make sense for user to tap on a shortcut in homescreen +to share, the expected share flow started from ShareSheet. + +Bug: 295334906, 295045199 +Test: manual +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b7b192bd7f24a2aa7d6881ee949657c9760c0305) +Merged-In: I8d0cbccdc31bd4cb927830e5ecf841147400fdfa +Change-Id: I8d0cbccdc31bd4cb927830e5ecf841147400fdfa +--- + .../android/launcher3/util/PackageManagerHelper.java | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java +index 1bcdab142..e44f68251 100644 +--- a/src/com/android/launcher3/util/PackageManagerHelper.java ++++ b/src/com/android/launcher3/util/PackageManagerHelper.java +@@ -138,15 +138,8 @@ public class PackageManagerHelper { + public boolean hasPermissionForActivity(Intent intent, String srcPackage) { + // b/270152142 + if (Intent.ACTION_CHOOSER.equals(intent.getAction())) { +- final Bundle extras = intent.getExtras(); +- if (extras == null) { +- return true; +- } +- // If given intent is ACTION_CHOOSER, verify srcPackage has permission over EXTRA_INTENT +- intent = (Intent) extras.getParcelable(Intent.EXTRA_INTENT); +- if (intent == null) { +- return true; +- } ++ // Chooser shortcuts is not a valid target ++ return false; + } + ResolveInfo target = mPm.resolveActivity(intent, 0); + if (target == null) { +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/packages/services/Telecomm/14_0014-Resolve-account-image-icon-profile-boundary-exploit-.bulletin.patch b/aosp_diff/preliminary/packages/services/Telecomm/14_0014-Resolve-account-image-icon-profile-boundary-exploit-.bulletin.patch new file mode 100644 index 0000000000..564262095d --- /dev/null +++ b/aosp_diff/preliminary/packages/services/Telecomm/14_0014-Resolve-account-image-icon-profile-boundary-exploit-.bulletin.patch @@ -0,0 +1,111 @@ +From aea8bc8cf985953671a6408d03bab0d0d79ca615 Mon Sep 17 00:00:00 2001 +From: Pranav Madapurmath +Date: Wed, 5 Apr 2023 21:36:12 +0000 +Subject: [PATCH] Resolve account image icon profile boundary exploit. + +Because Telecom grants the INTERACT_ACROSS_USERS permission, an exploit +is possible where the user can upload an image icon (belonging to +another user) via registering a phone account. This CL provides a +lightweight solution for parsing the image URI to detect profile +exploitation. + +Fixes: 273502295 +Fixes: 296915211 +Test: Unit test to enforce successful/failure path +(cherry picked from commit d0d1d38e37de54e58a7532a0020582fbd7d476b7) +(cherry picked from commit e7d0ca3fe5be6e393f643f565792ea5e7ed05f48) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a604311f86ea8136ca2ac9f9ff0af7fa57ee3f42) +Merged-In: I2b6418f019a373ee9f02ba8683e5b694e7ab80a5 +Change-Id: I2b6418f019a373ee9f02ba8683e5b694e7ab80a5 +--- + .../server/telecom/TelecomServiceImpl.java | 22 +++++++++++++++++++ + .../telecom/tests/TelecomServiceImplTest.java | 21 ++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java +index e44835c8..864181c1 100644 +--- a/src/com/android/server/telecom/TelecomServiceImpl.java ++++ b/src/com/android/server/telecom/TelecomServiceImpl.java +@@ -42,6 +42,7 @@ import android.content.pm.ApplicationInfo; + import android.content.pm.PackageManager; + import android.content.pm.ParceledListSlice; + import android.content.pm.ResolveInfo; ++import android.graphics.drawable.Icon; + import android.net.Uri; + import android.os.Binder; + import android.os.Build; +@@ -554,6 +555,9 @@ public class TelecomServiceImpl { + .build(); + } + ++ // Validate the profile boundary of the given image URI. ++ validateAccountIconUserBoundary(account.getIcon()); ++ + final long token = Binder.clearCallingIdentity(); + try { + mPhoneAccountRegistrar.registerPhoneAccount(account); +@@ -2543,4 +2547,22 @@ public class TelecomServiceImpl { + mContext.sendBroadcast(intent); + } + } ++ ++ private void validateAccountIconUserBoundary(Icon icon) { ++ // Refer to Icon#getUriString for context. The URI string is invalid for icons of ++ // incompatible types. ++ if (icon != null && (icon.getType() == Icon.TYPE_URI ++ || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) { ++ String encodedUser = icon.getUri().getEncodedUserInfo(); ++ // If there is no encoded user, the URI is calling into the calling user space ++ if (encodedUser != null) { ++ int userId = Integer.parseInt(encodedUser); ++ if (userId != UserHandle.getUserId(Binder.getCallingUid())) { ++ // If we are transcending the profile boundary, throw an error. ++ throw new IllegalArgumentException("Attempting to register a phone account with" ++ + " an image icon belonging to another user."); ++ } ++ } ++ } ++ } + } +diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java +index 1f29750b..e0e38a72 100644 +--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java ++++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java +@@ -31,6 +31,7 @@ import android.content.Context; + import android.content.Intent; + import android.content.pm.ApplicationInfo; + import android.content.pm.PackageManager; ++import android.graphics.drawable.Icon; + import android.net.Uri; + import android.os.Binder; + import android.os.Build; +@@ -591,6 +592,26 @@ public class TelecomServiceImplTest extends TelecomTestCase { + } + } + ++ @SmallTest ++ @Test ++ public void testRegisterPhoneAccountImageIconCrossUser() throws RemoteException { ++ String packageNameToUse = "com.android.officialpackage"; ++ PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName( ++ packageNameToUse, "cs"), "test", Binder.getCallingUserHandle()); ++ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); ++ PhoneAccount phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build(); ++ doReturn(PackageManager.PERMISSION_GRANTED) ++ .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE); ++ ++ // This should fail; security exception will be thrown. ++ registerPhoneAccountTestHelper(phoneAccount, false); ++ ++ icon = Icon.createWithContentUri("content://0@media/external/images/media/"); ++ phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build(); ++ // This should succeed. ++ registerPhoneAccountTestHelper(phoneAccount, true); ++ } ++ + @SmallTest + @Test + public void testUnregisterPhoneAccount() throws RemoteException { +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/40_0040-Reorganize-the-code-for-checking-auth-requirement.bulletin.patch b/aosp_diff/preliminary/system/bt/40_0040-Reorganize-the-code-for-checking-auth-requirement.bulletin.patch new file mode 100644 index 0000000000..bdb5a4d6fd --- /dev/null +++ b/aosp_diff/preliminary/system/bt/40_0040-Reorganize-the-code-for-checking-auth-requirement.bulletin.patch @@ -0,0 +1,133 @@ +From e98739434e47f8799c7e345be30b4d37cedba00f Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Wed, 13 Sep 2023 00:30:22 +0000 +Subject: [PATCH] Reorganize the code for checking auth requirement + +Original bug +Bug: 294854926 + +regressions: +Bug: 299570702 + +Test: Test: m com.android.btservices +Test: QA validation +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4c2b64caf4bb45c6c6ba010c2bfab304f3986509) +Merged-In: I976a5a6d7bb819fd6accdc71eb1501b9606f3ae4 +Change-Id: I976a5a6d7bb819fd6accdc71eb1501b9606f3ae4 +--- + stack/btm/btm_sec.cc | 95 ++++++++++++++++++++++++++------------------ + 1 file changed, 56 insertions(+), 39 deletions(-) + +diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc +index ce4bfa2d8..5e8e78e78 100644 +--- a/stack/btm/btm_sec.cc ++++ b/stack/btm/btm_sec.cc +@@ -4296,48 +4296,65 @@ tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec) { + + /* If connection is not authenticated and authentication is required */ + /* start authentication and return PENDING to the caller */ +- if ((((!(p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) && +- ((p_dev_rec->IsLocallyInitiated() && +- (p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)) || +- (!p_dev_rec->IsLocallyInitiated() && +- (p_dev_rec->security_required & BTM_SEC_IN_AUTHENTICATE)))) || +- (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED) && +- (!p_dev_rec->IsLocallyInitiated() && +- (p_dev_rec->security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN)))) && +- (p_dev_rec->hci_handle != HCI_INVALID_HANDLE)) { +- /* +- * We rely on BTM_SEC_16_DIGIT_PIN_AUTHED being set if MITM is in use, +- * as 16 DIGIT is only needed if MITM is not used. Unfortunately, the +- * BTM_SEC_AUTHENTICATED is used for both MITM and non-MITM +- * authenticated connections, hence we cannot distinguish here. +- */ +- +- LOG_DEBUG("Security Manager: Start authentication"); ++ if (p_dev_rec->hci_handle != HCI_INVALID_HANDLE) { ++ bool start_auth = false; ++ ++ // Check link status of BR/EDR ++ if (!(p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) { ++ if (p_dev_rec->IsLocallyInitiated()) { ++ if (p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE) { ++ LOG_DEBUG("Outgoing authentication Required"); ++ start_auth = true; ++ } ++ } else { ++ if (p_dev_rec->security_required & BTM_SEC_IN_AUTHENTICATE) { ++ LOG_DEBUG("Incoming authentication Required"); ++ start_auth = true; ++ } ++ } ++ } + +- /* +- * If we do have a link-key, but we end up here because we need an +- * upgrade, then clear the link-key known and authenticated flag before +- * restarting authentication. +- * WARNING: If the controller has link-key, it is optional and +- * recommended for the controller to send a Link_Key_Request. +- * In case we need an upgrade, the only alternative would be to delete +- * the existing link-key. That could lead to very bad user experience +- * or even IOP issues, if a reconnect causes a new connection that +- * requires an upgrade. +- */ +- if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) && +- (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED) && +- (!p_dev_rec->IsLocallyInitiated() && +- (p_dev_rec->security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN)))) { +- p_dev_rec->sec_flags &= +- ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED | +- BTM_SEC_AUTHENTICATED); ++ if (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED)) { ++ /* ++ * We rely on BTM_SEC_16_DIGIT_PIN_AUTHED being set if MITM is in use, ++ * as 16 DIGIT is only needed if MITM is not used. Unfortunately, the ++ * BTM_SEC_AUTHENTICATED is used for both MITM and non-MITM ++ * authenticated connections, hence we cannot distinguish here. ++ */ ++ if (!p_dev_rec->IsLocallyInitiated()) { ++ if (p_dev_rec->security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) { ++ LOG_DEBUG("BTM_SEC_IN_MIN_16_DIGIT_PIN Required"); ++ start_auth = true; ++ } ++ } + } + +- btm_sec_start_authentication(p_dev_rec); +- return (BTM_CMD_STARTED); +- } else { +- LOG_DEBUG("Authentication not required"); ++ if (start_auth) { ++ LOG_DEBUG("Security Manager: Start authentication"); ++ ++ /* ++ * If we do have a link-key, but we end up here because we need an ++ * upgrade, then clear the link-key known and authenticated flag before ++ * restarting authentication. ++ * WARNING: If the controller has link-key, it is optional and ++ * recommended for the controller to send a Link_Key_Request. ++ * In case we need an upgrade, the only alternative would be to delete ++ * the existing link-key. That could lead to very bad user experience ++ * or even IOP issues, if a reconnect causes a new connection that ++ * requires an upgrade. ++ */ ++ if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) && ++ (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED) && ++ (!p_dev_rec->IsLocallyInitiated() && ++ (p_dev_rec->security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN)))) { ++ p_dev_rec->sec_flags &= ++ ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED | ++ BTM_SEC_AUTHENTICATED); ++ } ++ ++ btm_sec_start_authentication(p_dev_rec); ++ return (BTM_CMD_STARTED); ++ } + } + + /* If connection is not encrypted and encryption is required */ +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/41_0041-Reject-access-to-secure-services-authenticated-from-temp-bonding.bulletin.patch b/aosp_diff/preliminary/system/bt/41_0041-Reject-access-to-secure-services-authenticated-from-temp-bonding.bulletin.patch new file mode 100644 index 0000000000..3a3a9cf5a6 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/41_0041-Reject-access-to-secure-services-authenticated-from-temp-bonding.bulletin.patch @@ -0,0 +1,40 @@ +From 6defc75a9322daf56170c7e12b557d9ad14bbecb Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Sat, 2 Sep 2023 04:27:29 +0000 +Subject: [PATCH] Reject access to secure services authenticated from temp + bonding [2] + +Reject access to service running on rfcomm + +this is a backport of +I10fcc2dcd78fc22ffbe3c425669fc9889b94a166 + +Bug: 294854926 +Test: m com.android.btservices +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:fcf6d4a112452e5d3a7076c7b38d8cc3ba938402) +Merged-In: I10fcc2dcd78fc22ffbe3c425669fc9889b94a166 +Change-Id: I10fcc2dcd78fc22ffbe3c425669fc9889b94a166 +--- + stack/btm/btm_sec.cc | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc +index 507ce044b..7d0a06c00 100644 +--- a/stack/btm/btm_sec.cc ++++ b/stack/btm/btm_sec.cc +@@ -1860,6 +1860,11 @@ tBTM_STATUS btm_sec_mx_access_request(const RawAddress& bd_addr, + p_callback, p_ref_data); + } else /* rc == BTM_SUCCESS */ + { ++ if (access_secure_service_from_temp_bond(p_dev_rec, ++ is_originator, security_required)) { ++ LOG_ERROR("Trying to access a secure rfcomm service from a temp bonding, reject"); ++ rc = BTM_FAILED_ON_SECURITY; ++ } + if (p_callback) { + LOG_DEBUG("Notifying client that security access has been granted"); + (*p_callback)(&bd_addr, transport, p_ref_data, rc); +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/42_0042-Reject-access-to-secure-service-authenticated-from-a-temp-bondin.bulletin.patch b/aosp_diff/preliminary/system/bt/42_0042-Reject-access-to-secure-service-authenticated-from-a-temp-bondin.bulletin.patch new file mode 100644 index 0000000000..44c48eb6a5 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/42_0042-Reject-access-to-secure-service-authenticated-from-a-temp-bondin.bulletin.patch @@ -0,0 +1,116 @@ +From 57d5d6e760c30ae65be25255638388f7975c2157 Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Sat, 2 Sep 2023 04:20:10 +0000 +Subject: [PATCH] Reject access to secure service authenticated from a temp + bonding [1] + +Rejecct access to services running on l2cap + +Backport of +Idef4ea28eb3d17b0807ab7dc6849433ddc5581b3 + +Bug: 294854926 +Test: m com.android.btservices +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bb6e130192fd14e588518dd746d428a1ad731a24) +Merged-In: Idef4ea28eb3d17b0807ab7dc6849433ddc5581b3 +Change-Id: Idef4ea28eb3d17b0807ab7dc6849433ddc5581b3 +--- + stack/btm/btm_sec.cc | 39 +++++++++++++++++++++++++++--- + stack/btm/security_device_record.h | 1 + + 2 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc +index b3d9fb2a9..507ce044b 100644 +--- a/stack/btm/btm_sec.cc ++++ b/stack/btm/btm_sec.cc +@@ -111,7 +111,7 @@ static tBTM_STATUS btm_sec_send_hci_disconnect(tBTM_SEC_DEV_REC* p_dev_rec, + uint16_t conn_handle); + tBTM_SEC_DEV_REC* btm_sec_find_dev_by_sec_state(uint8_t state); + +-static bool btm_dev_authenticated(tBTM_SEC_DEV_REC* p_dev_rec); ++static bool btm_dev_authenticated(const tBTM_SEC_DEV_REC* p_dev_rec); + static bool btm_dev_encrypted(tBTM_SEC_DEV_REC* p_dev_rec); + static uint16_t btm_sec_set_serv_level4_flags(uint16_t cur_security, + bool is_originator); +@@ -163,7 +163,7 @@ void NotifyBondingCanceled(tBTM_STATUS btm_status) { + * Returns bool true or false + * + ******************************************************************************/ +-static bool btm_dev_authenticated(tBTM_SEC_DEV_REC* p_dev_rec) { ++static bool btm_dev_authenticated(const tBTM_SEC_DEV_REC* p_dev_rec) { + if (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED) { + return (true); + } +@@ -203,6 +203,25 @@ static bool btm_dev_16_digit_authenticated(tBTM_SEC_DEV_REC* p_dev_rec) { + return (false); + } + ++/******************************************************************************* ++ * ++ * Function access_secure_service_from_temp_bond ++ * ++ * Description a utility function to test whether an access to ++ * secure service from temp bonding is happening ++ * ++ * Returns true if the aforementioned condition holds, ++ * false otherwise ++ * ++ ******************************************************************************/ ++static bool access_secure_service_from_temp_bond(const tBTM_SEC_DEV_REC* p_dev_rec, ++ bool locally_initiated, ++ uint16_t security_req) { ++ return !locally_initiated && (security_req & BTM_SEC_IN_AUTHENTICATE) && ++ btm_dev_authenticated(p_dev_rec) && ++ p_dev_rec->is_bond_type_temporary(); ++} ++ + /******************************************************************************* + * + * Function BTM_SecRegister +@@ -1573,9 +1592,13 @@ tBTM_STATUS btm_sec_l2cap_access_req_by_requirement( + } + + if (rc == BTM_SUCCESS) { ++ if (access_secure_service_from_temp_bond(p_dev_rec, is_originator, security_required)) { ++ LOG_ERROR("Trying to access a secure service from a temp bonding, rejecting"); ++ rc = BTM_FAILED_ON_SECURITY; ++ } + if (p_callback) +- (*p_callback)(&bd_addr, transport, (void*)p_ref_data, BTM_SUCCESS); +- return (BTM_SUCCESS); ++ (*p_callback)(&bd_addr, transport, (void*)p_ref_data, rc); ++ return (rc); + } + } + +@@ -4337,6 +4360,14 @@ tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec) { + return (BTM_FAILED_ON_SECURITY); + } + ++ ++ if (access_secure_service_from_temp_bond(p_dev_rec, ++ p_dev_rec->is_originator, ++ p_dev_rec->security_required)) { ++ LOG_ERROR("Trying to access a secure service from a temp bonding, rejecting"); ++ return (BTM_FAILED_ON_SECURITY); ++ } ++ + /* All required security procedures already established */ + p_dev_rec->security_required &= + ~(BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_IN_AUTHENTICATE | +diff --git a/stack/btm/security_device_record.h b/stack/btm/security_device_record.h +index 56d8108a0..6423810d9 100644 +--- a/stack/btm/security_device_record.h ++++ b/stack/btm/security_device_record.h +@@ -356,6 +356,7 @@ struct tBTM_SEC_DEV_REC { + uint16_t security_required, + tBTM_SEC_CALLBACK* p_callback, + void* p_ref_data); ++ friend tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec); + + public: + bool IsLocallyInitiated() const { return is_originator; } +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/43_0043-Reject-access-to-secure-service-authenticated-from-a-temp-bondi.bulletin.patch b/aosp_diff/preliminary/system/bt/43_0043-Reject-access-to-secure-service-authenticated-from-a-temp-bondi.bulletin.patch new file mode 100644 index 0000000000..46067ed355 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/43_0043-Reject-access-to-secure-service-authenticated-from-a-temp-bondi.bulletin.patch @@ -0,0 +1,47 @@ +From c6aae0a732befd36425a52136f472ec335f03b0d Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Wed, 13 Sep 2023 00:28:43 +0000 +Subject: [PATCH] Reject access to secure service authenticated from a temp + bonding [3] + +Allow access to rfcomm PSM by default + +Original bug +Bug: 294854926 + +Nearby regressions: +Bug: 298539299 + +Test: m com.android.btservices +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6a273c583f321c9ceed5237dc7de2bfeda719f44) +Merged-In: If1f7c9278a9e877f64ae78b6f067c597fb5d0e66 +Change-Id: If1f7c9278a9e877f64ae78b6f067c597fb5d0e66 +--- + stack/btm/btm_sec.cc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc +index 7d0a06c00..ce4bfa2d8 100644 +--- a/stack/btm/btm_sec.cc ++++ b/stack/btm/btm_sec.cc +@@ -1615,14 +1615,14 @@ tBTM_STATUS btm_sec_l2cap_access_req_by_requirement( + if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) { + if (is_originator) { + /* SM4 to SM4 -> always authenticate & encrypt */ +- security_required |= (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT); ++ security_required |= BTM_SEC_OUT_ENCRYPT; + } else /* acceptor */ + { + /* SM4 to SM4: the acceptor needs to make sure the authentication is + * already done */ + chk_acp_auth_done = true; + /* SM4 to SM4 -> always authenticate & encrypt */ +- security_required |= (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT); ++ security_required |= BTM_SEC_IN_ENCRYPT; + } + } else if (!(BTM_SM4_KNOWN & p_dev_rec->sm4)) { + /* the remote features are not known yet */ +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/44_0044-Enforce-authentication-if-encryption-is-required.bulletin.patch b/aosp_diff/preliminary/system/bt/44_0044-Enforce-authentication-if-encryption-is-required.bulletin.patch new file mode 100644 index 0000000000..4cc4a2b1c4 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/44_0044-Enforce-authentication-if-encryption-is-required.bulletin.patch @@ -0,0 +1,49 @@ +From eddc3380c3000a4e9301e35303b337fe42bcfae5 Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Wed, 13 Sep 2023 00:00:44 +0000 +Subject: [PATCH] Enforce authentication if encryption is required + +Original bug +Bug: 294854926 + +regressions: +Bug: 299570702 +Bug: 299561281 + +Test: Test: m com.android.btservices +Test: QA validation +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:475bb2486fdc5558363846873ca67fd994043e2e) +Merged-In: I0370ed2e3166d56f708e1981c2126526e1db9eaa +Change-Id: I0370ed2e3166d56f708e1981c2126526e1db9eaa +--- + stack/btm/btm_sec.cc | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc +index 5e8e78e78..bfb045c5a 100644 +--- a/stack/btm/btm_sec.cc ++++ b/stack/btm/btm_sec.cc +@@ -4302,13 +4302,15 @@ tBTM_STATUS btm_sec_execute_procedure(tBTM_SEC_DEV_REC* p_dev_rec) { + // Check link status of BR/EDR + if (!(p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) { + if (p_dev_rec->IsLocallyInitiated()) { +- if (p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE) { +- LOG_DEBUG("Outgoing authentication Required"); ++ if (p_dev_rec->security_required & ++ (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) { ++ LOG_DEBUG("Outgoing authentication/encryption Required"); + start_auth = true; + } + } else { +- if (p_dev_rec->security_required & BTM_SEC_IN_AUTHENTICATE) { +- LOG_DEBUG("Incoming authentication Required"); ++ if (p_dev_rec->security_required & ++ (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) { ++ LOG_DEBUG("Incoming authentication/encryption Required"); + start_auth = true; + } + } +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/45_0045-Factor-out-duplicate-code-for-parsing-gap-data.bulletin.patch b/aosp_diff/preliminary/system/bt/45_0045-Factor-out-duplicate-code-for-parsing-gap-data.bulletin.patch new file mode 100644 index 0000000000..ac9b188a44 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/45_0045-Factor-out-duplicate-code-for-parsing-gap-data.bulletin.patch @@ -0,0 +1,269 @@ +From 209da1de2da3d18c21d51237ad5cc43af88634f8 Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Fri, 22 Sep 2023 06:52:34 +0000 +Subject: [PATCH] Factor out duplicate code for parsing gap data + +This change is intended to be used to factor out +dup code for parsing GapData in StartAdvertisingSet +and make it easier to be tested. + +Backport of Ia39886c415218353b6f9d59d7d3f6d1160477d6c + +Bug: 296291440 +Test: atest net_test_main_shim +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b100ed7d1ec943e84fd96262304f41f87cf6e19f) +Merged-In: Ia39886c415218353b6f9d59d7d3f6d1160477d6c +Change-Id: Ia39886c415218353b6f9d59d7d3f6d1160477d6c +--- + main/Android.bp | 1 + + main/shim/Android.bp | 1 + + main/shim/BUILD.gn | 1 + + main/shim/le_advertising_manager.cc | 78 +++-------------------------- + main/shim/utils.cc | 40 +++++++++++++++ + main/shim/utils.h | 32 ++++++++++++ + 6 files changed, 82 insertions(+), 71 deletions(-) + create mode 100644 main/shim/utils.cc + create mode 100644 main/shim/utils.h + +diff --git a/main/Android.bp b/main/Android.bp +index 67cb3eca4..993a4b9a8 100644 +--- a/main/Android.bp ++++ b/main/Android.bp +@@ -239,6 +239,7 @@ cc_test { + "shim/metrics_api.cc", + "shim/shim.cc", + "shim/stack.cc", ++ "shim/utils.cc", + "test/main_shim_test.cc", + ], + static_libs: [ +diff --git a/main/shim/Android.bp b/main/shim/Android.bp +index b8aca32fa..b7fd7dfb2 100644 +--- a/main/shim/Android.bp ++++ b/main/shim/Android.bp +@@ -29,5 +29,6 @@ filegroup { + "metrics_api.cc", + "shim.cc", + "stack.cc", ++ "utils.cc", + ] + } +diff --git a/main/shim/BUILD.gn b/main/shim/BUILD.gn +index 5e6485898..d93a646ba 100644 +--- a/main/shim/BUILD.gn ++++ b/main/shim/BUILD.gn +@@ -35,6 +35,7 @@ source_set("LibBluetoothShimSources") { + "metrics_api.cc", + "shim.cc", + "stack.cc", ++ "utils.cc", + ] + + include_dirs = [ +diff --git a/main/shim/le_advertising_manager.cc b/main/shim/le_advertising_manager.cc +index a91f7426b..850beb866 100644 +--- a/main/shim/le_advertising_manager.cc ++++ b/main/shim/le_advertising_manager.cc +@@ -17,6 +17,7 @@ + #define LOG_TAG "bt_shim_advertiser" + + #include "le_advertising_manager.h" ++#include "utils.h" + + #include + #include +@@ -40,6 +41,7 @@ using bluetooth::hci::AddressType; + using bluetooth::hci::ErrorCode; + using bluetooth::hci::GapData; + using bluetooth::hci::OwnAddressType; ++using bluetooth::shim::parse_gap_data; + using std::vector; + + class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface, +@@ -79,22 +81,8 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface, + StatusCallback cb) override { + LOG(INFO) << __func__ << " in shim layer"; + +- size_t offset = 0; + std::vector advertising_data = {}; +- +- while (offset < data.size()) { +- GapData gap_data; +- uint8_t len = data[offset]; +- auto begin = data.begin() + offset; +- auto end = begin + len + 1; // 1 byte for len +- auto data_copy = std::make_shared>(begin, end); +- bluetooth::packet::PacketView packet( +- data_copy); +- GapData::Parse(&gap_data, packet.begin()); +- advertising_data.push_back(gap_data); +- offset += len + 1; // 1 byte for len +- } +- ++ parse_gap_data(data, advertising_data); + bluetooth::shim::GetAdvertising()->SetData(advertiser_id, set_scan_rsp, + advertising_data); + } +@@ -135,47 +123,9 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface, + periodic_params.periodic_advertising_properties; + config.periodic_advertising_parameters = periodic_parameters; + +- size_t offset = 0; +- while (offset < advertise_data.size()) { +- GapData gap_data; +- uint8_t len = advertise_data[offset]; +- auto begin = advertise_data.begin() + offset; +- auto end = begin + len + 1; // 1 byte for len +- auto data_copy = std::make_shared>(begin, end); +- bluetooth::packet::PacketView packet( +- data_copy); +- GapData::Parse(&gap_data, packet.begin()); +- config.advertisement.push_back(gap_data); +- offset += len + 1; // 1 byte for len +- } +- +- offset = 0; +- while (offset < scan_response_data.size()) { +- GapData gap_data; +- uint8_t len = scan_response_data[offset]; +- auto begin = scan_response_data.begin() + offset; +- auto end = begin + len + 1; // 1 byte for len +- auto data_copy = std::make_shared>(begin, end); +- bluetooth::packet::PacketView packet( +- data_copy); +- GapData::Parse(&gap_data, packet.begin()); +- config.scan_response.push_back(gap_data); +- offset += len + 1; // 1 byte for len +- } +- +- offset = 0; +- while (offset < periodic_data.size()) { +- GapData gap_data; +- uint8_t len = periodic_data[offset]; +- auto begin = periodic_data.begin() + offset; +- auto end = begin + len + 1; // 1 byte for len +- auto data_copy = std::make_shared>(begin, end); +- bluetooth::packet::PacketView packet( +- data_copy); +- GapData::Parse(&gap_data, packet.begin()); +- config.periodic_data.push_back(gap_data); +- offset += len + 1; // 1 byte for len +- } ++ parse_gap_data(advertise_data, config.advertisement); ++ parse_gap_data(scan_response_data, config.scan_response); ++ parse_gap_data(periodic_data, config.periodic_data); + + bluetooth::hci::AdvertiserId id = + bluetooth::shim::GetAdvertising()->ExtendedCreateAdvertiser( +@@ -202,22 +152,8 @@ class BleAdvertiserInterfaceImpl : public BleAdvertiserInterface, + StatusCallback cb) override { + LOG(INFO) << __func__ << " in shim layer"; + +- size_t offset = 0; + std::vector advertising_data = {}; +- +- while (offset < data.size()) { +- GapData gap_data; +- uint8_t len = data[offset]; +- auto begin = data.begin() + offset; +- auto end = begin + len + 1; // 1 byte for len +- auto data_copy = std::make_shared>(begin, end); +- bluetooth::packet::PacketView packet( +- data_copy); +- GapData::Parse(&gap_data, packet.begin()); +- advertising_data.push_back(gap_data); +- offset += len + 1; // 1 byte for len +- } +- ++ parse_gap_data(data, advertising_data); + bluetooth::shim::GetAdvertising()->SetPeriodicData(advertiser_id, + advertising_data); + } +diff --git a/main/shim/utils.cc b/main/shim/utils.cc +new file mode 100644 +index 000000000..dcf1725be +--- /dev/null ++++ b/main/shim/utils.cc +@@ -0,0 +1,40 @@ ++/* ++ * Copyright 2023 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "utils.h" ++ ++namespace bluetooth { ++namespace shim { ++void parse_gap_data(const std::vector &raw_data, ++ std::vector &output) { ++ size_t offset = 0; ++ while (offset < raw_data.size()) { ++ hci::GapData gap_data; ++ uint8_t len = raw_data[offset]; ++ ++ auto begin = raw_data.begin() + offset; ++ auto end = begin + len + 1; // 1 byte for len ++ auto data_copy = std::make_shared>(begin, end); ++ bluetooth::packet::PacketView packet( ++ data_copy); ++ hci::GapData::Parse(&gap_data, packet.begin()); ++ output.push_back(gap_data); ++ offset += len + 1; // 1 byte for len ++ } ++} ++ ++} // namespace shim ++} // namespace bluetooth +diff --git a/main/shim/utils.h b/main/shim/utils.h +new file mode 100644 +index 000000000..56da2a0a0 +--- /dev/null ++++ b/main/shim/utils.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright 2023 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++#pragma once ++#include ++ ++#include "hci/hci_packets.h" ++ ++namespace bluetooth { ++namespace shim { ++/** ++ * @brief Parsing gap data from raw bytes ++ * ++ * @param raw_data input, raw bytes ++ * @param output vector of GapData ++ */ ++void parse_gap_data(const std::vector &raw_data, ++ std::vector &output); ++} // namespace shim ++} // namespace bluetooth +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/46_0046-Fix-an-OOB-bug-in-parse_gap_data.bulletin.patch b/aosp_diff/preliminary/system/bt/46_0046-Fix-an-OOB-bug-in-parse_gap_data.bulletin.patch new file mode 100644 index 0000000000..7bb6a39ad5 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/46_0046-Fix-an-OOB-bug-in-parse_gap_data.bulletin.patch @@ -0,0 +1,35 @@ +From 249f0187b400b164dcdae78ca6db441404a4d4b8 Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Tue, 3 Oct 2023 17:28:23 +0000 +Subject: [PATCH] Fix an OOB bug in parse_gap_data + +Bug: 277590580 +bug: 275553827 +Test: atest net_test_main_shim +Ignore-AOSP-First: security +Tag: #security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:98007dd44ef095cae8091b7a31b6c7456eb9db25) +Merged-In: I7fcb7c46f668f48560a72399a3c5087c6da3827f +Change-Id: I7fcb7c46f668f48560a72399a3c5087c6da3827f +--- + main/shim/utils.cc | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/main/shim/utils.cc b/main/shim/utils.cc +index dcf1725be..9f18ddc4f 100644 +--- a/main/shim/utils.cc ++++ b/main/shim/utils.cc +@@ -25,6 +25,10 @@ void parse_gap_data(const std::vector &raw_data, + hci::GapData gap_data; + uint8_t len = raw_data[offset]; + ++ if (offset + len + 1 > raw_data.size()) { ++ break; ++ } ++ + auto begin = raw_data.begin() + offset; + auto end = begin + len + 1; // 1 byte for len + auto data_copy = std::make_shared>(begin, end); +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/47_0047-Fix-timing-attack-in-BTM_BleVerifySignature.bulletin.patch b/aosp_diff/preliminary/system/bt/47_0047-Fix-timing-attack-in-BTM_BleVerifySignature.bulletin.patch new file mode 100644 index 0000000000..9dccdb9574 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/47_0047-Fix-timing-attack-in-BTM_BleVerifySignature.bulletin.patch @@ -0,0 +1,46 @@ +From 82239082e0f2191c61b79638a4c48301a8811208 Mon Sep 17 00:00:00 2001 +From: Brian Delwiche +Date: Tue, 3 Oct 2023 21:27:49 +0000 +Subject: [PATCH] Fix timing attack in BTM_BleVerifySignature + +BTM_BleVerifySignature uses a stock memcmp, allowing signature contents +to be deduced through a side-channel attack. + +Change to CRYPTO_memcmp, which is hardened against this attack, to +eliminate this attack. + +Bug: 274478807 +Test: atest bluetooth_test_gd_unit +Tag: #security +Ignore-AOSP-First: Security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8fe5c711c9ec924b09e42888eb80f6f17b1c6630) +Merged-In: Id2451e3b37030c22e8880710f602d4a0b9d24a50 +Change-Id: Id2451e3b37030c22e8880710f602d4a0b9d24a50 +--- + stack/btm/btm_ble.cc | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/stack/btm/btm_ble.cc b/stack/btm/btm_ble.cc +index ae7b9ba59..601d85be0 100644 +--- a/stack/btm/btm_ble.cc ++++ b/stack/btm/btm_ble.cc +@@ -31,6 +31,7 @@ + #include "main/shim/btm_api.h" + #include "main/shim/l2c_api.h" + #include "main/shim/shim.h" ++#include "openssl/mem.h" + #include "stack/btm/btm_dev.h" + #include "stack/btm/btm_int_types.h" + #include "stack/btm/security_device_record.h" +@@ -1960,7 +1961,7 @@ bool BTM_BleVerifySignature(const RawAddress& bd_addr, uint8_t* p_orig, + + crypto_toolbox::aes_cmac(p_rec->ble.keys.pcsrk, p_orig, len, + BTM_CMAC_TLEN_SIZE, p_mac); +- if (memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0) { ++ if (CRYPTO_memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0) { + btm_ble_increment_sign_ctr(bd_addr, false); + verified = true; + } +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/bt/48_0048-Add-bounds-checks-in-btif_avrcp_audio_track-cc.bulletin.patch b/aosp_diff/preliminary/system/bt/48_0048-Add-bounds-checks-in-btif_avrcp_audio_track-cc.bulletin.patch new file mode 100644 index 0000000000..4fb57098c9 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/48_0048-Add-bounds-checks-in-btif_avrcp_audio_track-cc.bulletin.patch @@ -0,0 +1,64 @@ +From 2e88f0f504f8319e2f1f644cce0147ee908f78ac Mon Sep 17 00:00:00 2001 +From: Brian Delwiche +Date: Fri, 19 May 2023 23:33:49 +0000 +Subject: [PATCH] Add bounds checks in btif_avrcp_audio_track.cc + +Fuzz testing reveals that the transcodeQ*ToFloat family of functions are +not bounds checked, causing a potential OOB write. + +Check these functions against bounds of the destination array. + +Bug: 275895309 +Test: atest bluetooth_test_gd_unit, net_test_stack_btm +Tag: #security +Ignore-AOSP-First: Security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ff1a4a98c75ac9d6b850655efb1eeaae3503a511) +Merged-In: I7d47860e7636282e3f7f1b8001aa1aa3b6d0c12e +Change-Id: I7d47860e7636282e3f7f1b8001aa1aa3b6d0c12e +--- + btif/src/btif_avrcp_audio_track.cc | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/btif/src/btif_avrcp_audio_track.cc b/btif/src/btif_avrcp_audio_track.cc +index 8ca5c9798..e17f80f5f 100644 +--- a/btif/src/btif_avrcp_audio_track.cc ++++ b/btif/src/btif_avrcp_audio_track.cc +@@ -23,6 +23,8 @@ + #include + #include + ++#include ++ + #include "bt_target.h" + #include "osi/include/log.h" + +@@ -152,7 +154,7 @@ static size_t transcodeQ15ToFloat(uint8_t* buffer, size_t length, + BtifAvrcpAudioTrack* trackHolder) { + size_t sampleSize = sampleSizeFor(trackHolder); + size_t i = 0; +- for (; i <= length / sampleSize; i++) { ++ for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) { + trackHolder->buffer[i] = ((int16_t*)buffer)[i] * kScaleQ15ToFloat; + } + return i * sampleSize; +@@ -162,7 +164,7 @@ static size_t transcodeQ23ToFloat(uint8_t* buffer, size_t length, + BtifAvrcpAudioTrack* trackHolder) { + size_t sampleSize = sampleSizeFor(trackHolder); + size_t i = 0; +- for (; i <= length / sampleSize; i++) { ++ for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) { + size_t offset = i * sampleSize; + int32_t sample = *((int32_t*)(buffer + offset - 1)) & 0x00FFFFFF; + trackHolder->buffer[i] = sample * kScaleQ23ToFloat; +@@ -174,7 +176,7 @@ static size_t transcodeQ31ToFloat(uint8_t* buffer, size_t length, + BtifAvrcpAudioTrack* trackHolder) { + size_t sampleSize = sampleSizeFor(trackHolder); + size_t i = 0; +- for (; i <= length / sampleSize; i++) { ++ for (; i < std::min(trackHolder->bufferLength, length / sampleSize); i++) { + trackHolder->buffer[i] = ((int32_t*)buffer)[i] * kScaleQ31ToFloat; + } + return i * sampleSize; +-- +2.42.0.820.g83a721a137-goog + diff --git a/aosp_diff/preliminary/system/netd/0001-Fix-Heap-use-after-free-in-MDnsSdListener-Monitor-run.bulletin.patch b/aosp_diff/preliminary/system/netd/0001-Fix-Heap-use-after-free-in-MDnsSdListener-Monitor-run.bulletin.patch new file mode 100644 index 0000000000..f9bde88f02 --- /dev/null +++ b/aosp_diff/preliminary/system/netd/0001-Fix-Heap-use-after-free-in-MDnsSdListener-Monitor-run.bulletin.patch @@ -0,0 +1,118 @@ +From b3407e31a0175b34b537a87d3c39661c9c1bcf8a Mon Sep 17 00:00:00 2001 +From: Lin Lee +Date: Mon, 7 Aug 2023 09:34:41 +0000 +Subject: [PATCH] Fix Heap-use-after-free in MDnsSdListener::Monitor::run + +Use thread join to avoid thread exiting after instance +recycled. + +Prior to implementing this patch, fuzzing would lead to a segmentation fault after approximately 500 rounds. With the addition of the patch, the fuzzing process can now be repeated for over 30,000 rounds. + +Test: m, fuzzing +Fuzzing: mma mdns_service_fuzzer && adb sync data && adb shell /data/fuzz/arm64/mdns_service_fuzzer/mdns_service_fuzzer + +Bug: 272382770 +Ignore-AOSP-First: Security Issue +(cherry picked from commit 9c0c15f80cffb98b36284dd169a2e62e059dbbe3) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:75e5e2e1faec7aa2812fc6fba30d6fe80558bacd) +Merged-In: I5bc85451b4e6539bad45ceb672924a37952cc138 +Change-Id: I5bc85451b4e6539bad45ceb672924a37952cc138 +--- + server/MDnsSdListener.cpp | 35 +++++++++++++++++++++++------------ + server/MDnsSdListener.h | 4 +++- + 2 files changed, 26 insertions(+), 13 deletions(-) + +diff --git a/server/MDnsSdListener.cpp b/server/MDnsSdListener.cpp +index 42dcddf3..d551d37c 100644 +--- a/server/MDnsSdListener.cpp ++++ b/server/MDnsSdListener.cpp +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #define LOG_TAG "MDnsDS" + #define DBG 1 +@@ -527,12 +528,18 @@ MDnsSdListener::Monitor::Monitor() { + mPollSize = 10; + socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, mCtrlSocketPair); + +- const int rval = ::android::netdutils::threadLaunch(this); +- if (rval != 0) { +- ALOGW("Error spawning monitor thread: %s (%d)", strerror(-rval), -rval); +- } ++ mRescanThread = new std::thread(&Monitor::run, this); ++ if (!mRescanThread->joinable()) ALOGE("Unable to launch thread."); + } + ++MDnsSdListener::Monitor::~Monitor() { ++ if (VDBG) ALOGD("Monitor recycling"); ++ close(mCtrlSocketPair[1]); // interrupt poll in MDnsSdListener::Monitor::run() and revent will ++ // be 17 = POLLIN | POLLHUP ++ mRescanThread->join(); ++ delete mRescanThread; ++ if (VDBG) ALOGD("Monitor recycled"); ++} + #define NAP_TIME 200 // 200 ms between polls + static int wait_for_property(const char *name, const char *desired_value, int maxwait) + { +@@ -611,14 +618,18 @@ void MDnsSdListener::Monitor::run() { + } + } + if (VDBG) ALOGD("controlSocket shows revent= %d", mPollFds[0].revents); +- switch (mPollFds[0].revents) { +- case POLLIN: { +- char readBuf[2]; +- read(mCtrlSocketPair[0], &readBuf, 1); +- if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]); +- if (memcmp(RESCAN, readBuf, 1) == 0) { +- pollCount = rescan(); +- } ++ if (mPollFds[0].revents & POLLHUP) { ++ free(mPollFds); ++ free(mPollRefs); ++ if (VDBG) ALOGD("Monitor thread leaving."); ++ return; ++ } ++ if (mPollFds[0].revents == POLLIN) { ++ char readBuf[2]; ++ read(mCtrlSocketPair[0], &readBuf, 1); ++ if (DBG) ALOGD("MDnsSdListener::Monitor got %c", readBuf[0]); ++ if (memcmp(RESCAN, readBuf, 1) == 0) { ++ pollCount = rescan(); + } + } + mPollFds[0].revents = 0; +diff --git a/server/MDnsSdListener.h b/server/MDnsSdListener.h +index 83cf23e3..196419b1 100644 +--- a/server/MDnsSdListener.h ++++ b/server/MDnsSdListener.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #include "NetdCommand.h" + +@@ -71,7 +72,7 @@ private: + class Monitor { + public: + Monitor(); +- virtual ~Monitor() {} ++ ~Monitor(); + DNSServiceRef *allocateServiceRef(int id, Context *c); + void startMonitoring(int id); + DNSServiceRef *lookupServiceRef(int id); +@@ -102,6 +103,7 @@ private: + int mPollSize; + int mCtrlSocketPair[2]; + std::mutex mMutex; ++ std::thread* mRescanThread; + }; + + class Handler : public NetdCommand { +-- +2.42.0.820.g83a721a137-goog +