From 1b9d5f6f2419d339a062768848d34056e6bab7a7 Mon Sep 17 00:00:00 2001 From: "Alam, SahibeX" Date: Sat, 25 Nov 2023 00:18:34 +0530 Subject: [PATCH] ASB - December 2023 Security Patches integration Integrating Security Patches Test done: STS r21 TCs Passed Tracked-On: OAM-113582 Signed-off-by: Alam, SahibeX --- ...4-Update-security_patch_level-string.patch | 2 +- ...httplive-fix-use-after-free.bulletin.patch | 107 ++++ ...tion-source-for-MMAP-thread.bulletin.patch | 54 ++ ...d-record-restriction-on-Sdk.bulletin.patch | 78 +++ ...ce-lockdown-always-show-the-keyguard.patch | 54 ++ ...Visit-Uris-added-by-WearableExtender.patch | 98 ++++ ...ss-BAL-via-requestGeofence-.bulletin.patch | 29 + ...related-to-Notification-style-extras.patch | 118 +++++ ...UTOMERGE-Drop-invalid-data-.bulletin.patch | 126 +++++ ...-conversation-widget-for-secondary-u.patch | 501 ++++++++++++++++++ ...tcut-icon-at-creation-time-.bulletin.patch | 62 +++ ...rmission-to-unlock-keyguard.bulletin.patch | 60 +++ ...dded-through-addDynamicShor.bulletin.patch | 42 ++ ...riptor-in-incidentd-service.bulletin.patch | 67 +++ ...d-when-publishing-shortcuts.bulletin.patch | 32 ++ ...ce-lockdown-always-show-the-keyguard.patch | 48 ++ ...show-the-keyguard-on-device-lockdown.patch | 74 +++ ...e-native-supported-binder-c.bulletin.patch | 41 ++ ...GE-Check-URI-permissions-for-resumab.patch | 386 ++++++++++++++ ...o-watch-foreground-changes-.bulletin.patch | 110 ++++ ...0004-Fix-UAF-in-CallbackEnv.bulletin.patch | 41 ++ ...n-bypass-in-legacy-shortcut.bulletin.patch | 43 ++ ...n-profile-boundary-exploit-.bulletin.patch | 111 ++++ ...r-checking-auth-requirement.bulletin.patch | 133 +++++ ...enticated-from-temp-bonding.bulletin.patch | 40 ++ ...nticated-from-a-temp-bondin.bulletin.patch | 116 ++++ ...enticated-from-a-temp-bondi.bulletin.patch | 47 ++ ...n-if-encryption-is-required.bulletin.patch | 49 ++ ...e-code-for-parsing-gap-data.bulletin.patch | 269 ++++++++++ ...n-OOB-bug-in-parse_gap_data.bulletin.patch | 35 ++ ...k-in-BTM_BleVerifySignature.bulletin.patch | 46 ++ ...n-btif_avrcp_audio_track-cc.bulletin.patch | 64 +++ ...-MDnsSdListener-Monitor-run.bulletin.patch | 118 +++++ 33 files changed, 3200 insertions(+), 1 deletion(-) create mode 100644 aosp_diff/preliminary/frameworks/av/29_0029-httplive-fix-use-after-free.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/av/30_0030-Correct-attribution-source-for-MMAP-thread.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/av/31_0031-Condition-background-record-restriction-on-Sdk.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0209-On-device-lockdown-always-show-the-keyguard.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0210-Visit-Uris-added-by-WearableExtender.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0211-Fix-bypass-BAL-via-requestGeofence-.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0212-Visit-Uris-related-to-Notification-style-extras.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0213-RESTRICT-AUTOMERGE-Drop-invalid-data-.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0214-Disable-priority-conversation-widget-for-secondary-u.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0215-Validate-URI-based-shortcut-icon-at-creation-time-.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0216-Require-permission-to-unlock-keyguard.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0217-Restrict-number-of-shortcuts-can-be-added-through-addDynamicShor.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0218-Use-readUniqueFileDescriptor-in-incidentd-service.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0219-Validate-userId-when-publishing-shortcuts.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0220-Revert-On-device-lockdown-always-show-the-keyguard.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0221-Updated-always-show-the-keyguard-on-device-lockdown.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0222-Move-startWatchingModeWithFlags-to-the-native-supported-binder-c.bulletin.patch create mode 100644 aosp_diff/preliminary/frameworks/base/99_0223-RESTRICT-AUTOMERGE-Check-URI-permissions-for-resumab.patch create mode 100644 aosp_diff/preliminary/frameworks/native/20_0020-Add-AppOps-overload-to-be-able-to-watch-foreground-changes-.bulletin.patch create mode 100644 aosp_diff/preliminary/packages/apps/Bluetooth/04_0004-Fix-UAF-in-CallbackEnv.bulletin.patch create mode 100644 aosp_diff/preliminary/packages/apps/Launcher3/03_0003-Fix-permission-bypass-in-legacy-shortcut.bulletin.patch create mode 100644 aosp_diff/preliminary/packages/services/Telecomm/14_0014-Resolve-account-image-icon-profile-boundary-exploit-.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/40_0040-Reorganize-the-code-for-checking-auth-requirement.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/41_0041-Reject-access-to-secure-services-authenticated-from-temp-bonding.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/42_0042-Reject-access-to-secure-service-authenticated-from-a-temp-bondin.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/43_0043-Reject-access-to-secure-service-authenticated-from-a-temp-bondi.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/44_0044-Enforce-authentication-if-encryption-is-required.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/45_0045-Factor-out-duplicate-code-for-parsing-gap-data.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/46_0046-Fix-an-OOB-bug-in-parse_gap_data.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/47_0047-Fix-timing-attack-in-BTM_BleVerifySignature.bulletin.patch create mode 100644 aosp_diff/preliminary/system/bt/48_0048-Add-bounds-checks-in-btif_avrcp_audio_track-cc.bulletin.patch create mode 100644 aosp_diff/preliminary/system/netd/0001-Fix-Heap-use-after-free-in-MDnsSdListener-Monitor-run.bulletin.patch 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..59c67c0659 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/av/29_0029-httplive-fix-use-after-free.bulletin.patch @@ -0,0 +1,107 @@ +From 76225338a8be623cb7db32213192fbbc7c73895e 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..22a4e52d67 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/av/30_0030-Correct-attribution-source-for-MMAP-thread.bulletin.patch @@ -0,0 +1,54 @@ +From f7b5a2f8c3fb7daa1213fce472df3cd2c05e535f 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 6dfaf7e068..670f1a09a9 100644 +--- a/services/audioflinger/Threads.cpp ++++ b/services/audioflinger/Threads.cpp +@@ -9504,6 +9504,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; +@@ -9517,7 +9520,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, + ret = AudioSystem::getOutputForAttr(&mAttr, &io, + mSessionId, + &stream, +- client.attributionSource, ++ adjAttributionSource, + &config, + flags, + &deviceId, +@@ -9534,7 +9537,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..e14459075e --- /dev/null +++ b/aosp_diff/preliminary/frameworks/av/31_0031-Condition-background-record-restriction-on-Sdk.bulletin.patch @@ -0,0 +1,78 @@ +From 3c28a81aa632b38329c824e6eb500c3940834d8b 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 102b376ded..d74c3546ec 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() +@@ -1550,10 +1572,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.patch b/aosp_diff/preliminary/frameworks/base/99_0209-On-device-lockdown-always-show-the-keyguard.patch new file mode 100644 index 0000000000..3aac01b92f --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0209-On-device-lockdown-always-show-the-keyguard.patch @@ -0,0 +1,54 @@ +From 65f3760253722d932ce9cf99497748332b49c219 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:100ae42365d7fc8ba7d241e8c9a7ef6aa0cdb961) +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 2c596d1b97e8..9c7d9f9f13c5 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() { +@@ -1525,7 +1532,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.17.1 + 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..3cd3cae74f --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0210-Visit-Uris-added-by-WearableExtender.patch @@ -0,0 +1,98 @@ +From 4a93235cf0229fc65406d27e8428898842de0bde 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] 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..ce98f17654 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0211-Fix-bypass-BAL-via-requestGeofence-.bulletin.patch @@ -0,0 +1,29 @@ +From d030cfd73ddf8fa191909681af0e0b71f7b4a7a1 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..02549fab23 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0212-Visit-Uris-related-to-Notification-style-extras.patch @@ -0,0 +1,118 @@ +From 6fea5c203802a921baac58bf0260ef389448e35e 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] 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..95f9a14a45 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0213-RESTRICT-AUTOMERGE-Drop-invalid-data-.bulletin.patch @@ -0,0 +1,126 @@ +From bdf1a2937abc81d0c86bc4ce0e621e7794baee73 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:a495a282660940657ed20670c35c6d83fa1de054) +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-Disable-priority-conversation-widget-for-secondary-u.patch b/aosp_diff/preliminary/frameworks/base/99_0214-Disable-priority-conversation-widget-for-secondary-u.patch new file mode 100644 index 0000000000..a37f3998c6 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0214-Disable-priority-conversation-widget-for-secondary-u.patch @@ -0,0 +1,501 @@ +From 3b2f3ed0816beb4e8dc1f44d126ede559bfb4c13 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:95659d74cfa1f6d7a9796b5d595c99df253ec054) +Merged-In: I3f3991d2cb7fb9970cc8ada39ceae9a7ff2fcb31 +Change-Id: I3f3991d2cb7fb9970cc8ada39ceae9a7ff2fcb31 +--- + .../dagger/NotificationsModule.java | 3 + + .../row/NotificationConversationInfo.java | 9 ++- + .../row/NotificationGutsManager.java | 7 ++ + .../row/NotificationConversationInfoTest.java | 71 +++++++++++++++++++ + .../row/NotificationGutsManagerTest.java | 5 +- + 5 files changed, 93 insertions(+), 2 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..d817244223c2 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; +@@ -155,7 +158,9 @@ public class NotificationConversationInfo extends LinearLayout implements + // People Tile add request. + 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..b888cfd181a3 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, +@@ -159,6 +164,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx + mAccessibilityManager = accessibilityManager; + mHighPriorityProvider = highPriorityProvider; + mNotificationManager = notificationManager; ++ mUserManager = userManager; + mNotificationEntryManager = notificationEntryManager; + mPeopleSpaceWidgetManager = peopleSpaceWidgetManager; + mLauncherApps = launcherApps; +@@ -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..c996779947ea 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,7 @@ 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.17.1 + diff --git a/aosp_diff/preliminary/frameworks/base/99_0215-Validate-URI-based-shortcut-icon-at-creation-time-.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0215-Validate-URI-based-shortcut-icon-at-creation-time-.bulletin.patch new file mode 100644 index 0000000000..fee8631d0d --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0215-Validate-URI-based-shortcut-icon-at-creation-time-.bulletin.patch @@ -0,0 +1,62 @@ +From f8c2411e2151526f753b29a8b123170754a867cd 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 940eb345c06d..ee63f3b7f216 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; +@@ -1900,11 +1901,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_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..2143b12f20 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0216-Require-permission-to-unlock-keyguard.bulletin.patch @@ -0,0 +1,60 @@ +From 5c1ac2cb77bbd6d1040258769805e649f5dd6089 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:9be3a7bf92b0dc5a60421eda34ff9c7f792cafd3) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6568e40be92a15def8e0b6da9c3a18633a71cc3b) +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 2be78033ddf7..eabd0069f26a 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 ae3e214f1518..1182f5d4a05d 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; +@@ -3369,6 +3370,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..6ebcc55655 --- /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 f155cd02a720e60bc25584f86162312e64fbcf00 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..19d7c2059c --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0218-Use-readUniqueFileDescriptor-in-incidentd-service.bulletin.patch @@ -0,0 +1,67 @@ +From 825a59b3ca271690db1af6663130ead730ceb411 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:db60b2f5e004a4b303c70bdecb94d4b40f29cc33) +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..38506f6460 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0219-Validate-userId-when-publishing-shortcuts.bulletin.patch @@ -0,0 +1,32 @@ +From 1cf1b7d442c32365ec7580716787fae6207cf699 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 ee63f3b7f216..550e0e2622d7 100644 +--- a/services/core/java/com/android/server/pm/ShortcutService.java ++++ b/services/core/java/com/android/server/pm/ShortcutService.java +@@ -1733,6 +1733,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.patch b/aosp_diff/preliminary/frameworks/base/99_0220-Revert-On-device-lockdown-always-show-the-keyguard.patch new file mode 100644 index 0000000000..faeae15d4e --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0220-Revert-On-device-lockdown-always-show-the-keyguard.patch @@ -0,0 +1,48 @@ +From a517c9c9f37587e5df85f9cce59a0dbab701a48a Mon Sep 17 00:00:00 2001 +From: Beverly Tai +Date: Thu, 14 Sep 2023 20:51:27 +0000 +Subject: [PATCH] Revert "On device lockdown, always show the keyguard" + +This reverts commit 100ae42365d7fc8ba7d241e8c9a7ef6aa0cdb961. + +Reason for revert: b/300463732 regression +Bug: 300463732 +Bug: 218495634 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:996896e672f28aa96a3d8158192de3cd4a105bc3) +Merged-In: Ida8f2ab5e4ac79b38c21ba7bacfe9c374c9cc600 +Change-Id: Ida8f2ab5e4ac79b38c21ba7bacfe9c374c9cc600 +--- + .../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 9c7d9f9f13c5..2c596d1b97e8 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() { +@@ -1532,8 +1525,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.17.1 + diff --git a/aosp_diff/preliminary/frameworks/base/99_0221-Updated-always-show-the-keyguard-on-device-lockdown.patch b/aosp_diff/preliminary/frameworks/base/99_0221-Updated-always-show-the-keyguard-on-device-lockdown.patch new file mode 100644 index 0000000000..85b88451ae --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0221-Updated-always-show-the-keyguard-on-device-lockdown.patch @@ -0,0 +1,74 @@ +From 32b7d285c5fe392354921df6c01eb758e35e88ed Mon Sep 17 00:00:00 2001 +From: Beverly Tai +Date: Tue, 19 Sep 2023 20:44:04 +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:faaf58d3b910c388b0a7c51dc370a7ae18e7cec2) +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 2c596d1b97e8..c8a759ee9950 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() { +@@ -1308,6 +1315,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 +@@ -1524,8 +1535,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.17.1 + 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..6ec27b70d8 --- /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 32691367d0b84ad607cd66eb9d1f75632d6f7576 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..83e906fd00 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0223-RESTRICT-AUTOMERGE-Check-URI-permissions-for-resumab.patch @@ -0,0 +1,386 @@ +From 19b852487363010f15e01f385330539d02868544 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:1f758ee33f19efce1b57270d518e444d13309731) +Merged-In: Ie79915d3d1712f08dc2e8dfbd5bc7fd32bb308a3 +Change-Id: Ie79915d3d1712f08dc2e8dfbd5bc7fd32bb308a3 +--- + core/java/android/app/IUriGrantsManager.aidl | 3 + + .../systemui/media/MediaDataManager.kt | 35 ++++- + .../systemui/media/MediaDataManagerTest.kt | 129 +++++++++++++++++- + .../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..76322a08d1c3 100644 +--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt ++++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +@@ -18,11 +18,13 @@ 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 +@@ -38,6 +40,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 +500,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 +683,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..907cf79ab7b4 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,103 @@ 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(0), 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(0), ++ 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..7adbc4f3f4 --- /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 b7c81325ecba3f8ac08f7ddb0ca0c4ebaa12b9a8 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..9fb5408f2f --- /dev/null +++ b/aosp_diff/preliminary/packages/apps/Bluetooth/04_0004-Fix-UAF-in-CallbackEnv.bulletin.patch @@ -0,0 +1,41 @@ +From 4a2f8c63e96b000378866a57548c63309c51ab2c 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..2e6917dbbf --- /dev/null +++ b/aosp_diff/preliminary/packages/apps/Launcher3/03_0003-Fix-permission-bypass-in-legacy-shortcut.bulletin.patch @@ -0,0 +1,43 @@ +From 0b48cd0b6cd5ba540f305b9c7f4ea754ff20c605 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..b0cf379833 --- /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 74cf226b7d68c6d261887bf759e28a1c20c48c60 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 605f8f2a..0771f589 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; +@@ -561,6 +562,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); +@@ -2576,4 +2580,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 c5307694..eb348f21 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; +@@ -602,6 +603,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..5456702db0 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/40_0040-Reorganize-the-code-for-checking-auth-requirement.bulletin.patch @@ -0,0 +1,133 @@ +From 2f932385f8fbec62d6c258cd51eafbe67847a10b 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..c79fa62165 --- /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 572aac6a64d7a99f77b506a385a91aaf48bf0ffa 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..b341bf560e --- /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 110773169f021071bac2b8addb43779a1c4af910 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..fe3d364876 --- /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 e9fa581c0ce2508ad53b2194a40dc45bb3c2b465 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..ee98dddf3e --- /dev/null +++ b/aosp_diff/preliminary/system/bt/44_0044-Enforce-authentication-if-encryption-is-required.bulletin.patch @@ -0,0 +1,49 @@ +From 668e56a55c0322468b8129123a2ff7803e299d79 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..a6ee66fe6b --- /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 2e99f5abe55ce26c742625b2b2c2adb54bc06de4 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..ae96d4e4d6 --- /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 bf86140902ddb1ce32e7ed7985fb3635435874dc 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..8248848612 --- /dev/null +++ b/aosp_diff/preliminary/system/bt/47_0047-Fix-timing-attack-in-BTM_BleVerifySignature.bulletin.patch @@ -0,0 +1,46 @@ +From 76d689c66f71ad114613dd7fe32169e0098d3bb4 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..4b6327fadc --- /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 ad5bc71d67d134767837f311b35ca4a22e6e4297 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..50781510c9 --- /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 fd5d292aa75a855efaab095d30f8dc83e6e02cc5 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 +