From ad298935a273558db9bb05c3467d5d408eedda20 Mon Sep 17 00:00:00 2001 From: Tad Date: Mon, 13 Nov 2023 18:46:57 -0500 Subject: [PATCH] 16.0 November ASB work Signed-off-by: Tad --- .../android_frameworks_av/373949.patch | 79 ++ .../android_frameworks_av/373950.patch | 72 ++ .../373951-backport.patch | 52 ++ .../android_frameworks_base/373953.patch | 31 + .../android_frameworks_base/373955.patch | 68 ++ .../373957-backport.patch | 817 ++++++++++++++++++ Scripts/LineageOS-15.1/Patch.sh | 2 +- Scripts/LineageOS-16.0/Patch.sh | 18 +- 8 files changed, 1134 insertions(+), 5 deletions(-) create mode 100644 Patches/LineageOS-16.0/android_frameworks_av/373949.patch create mode 100644 Patches/LineageOS-16.0/android_frameworks_av/373950.patch create mode 100644 Patches/LineageOS-16.0/android_frameworks_base/373951-backport.patch create mode 100644 Patches/LineageOS-16.0/android_frameworks_base/373953.patch create mode 100644 Patches/LineageOS-16.0/android_frameworks_base/373955.patch create mode 100644 Patches/LineageOS-16.0/android_packages_providers_TelephonyProvider/373957-backport.patch diff --git a/Patches/LineageOS-16.0/android_frameworks_av/373949.patch b/Patches/LineageOS-16.0/android_frameworks_av/373949.patch new file mode 100644 index 00000000..bcde2adf --- /dev/null +++ b/Patches/LineageOS-16.0/android_frameworks_av/373949.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shruti Bihani +Date: Mon, 10 Jul 2023 08:53:42 +0000 +Subject: [PATCH] Fix for heap buffer overflow issue flagged by fuzzer test. + +OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. + +Similar checks have been added wherever applicable on other such methods of the class. + +Bug: 243463593 +Test: Build mtp_packet_fuzzer and run on the target device +(cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1401a723899766632363129265b30d433ac69c44) +Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b +Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b +--- + media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 9 deletions(-) + +diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp +index 3dd4248e4c..917967cf17 100644 +--- a/media/mtp/MtpPacket.cpp ++++ b/media/mtp/MtpPacket.cpp +@@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { + } + + uint16_t MtpPacket::getUInt16(int offset) const { +- return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; ++ if ((unsigned long)(offset+2) <= mBufferSize) { ++ return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; ++ } ++ else { ++ ALOGE("offset for buffer read is greater than buffer size!"); ++ abort(); ++ } + } + + uint32_t MtpPacket::getUInt32(int offset) const { +- return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | +- ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; ++ if ((unsigned long)(offset+4) <= mBufferSize) { ++ return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | ++ ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; ++ } ++ else { ++ ALOGE("offset for buffer read is greater than buffer size!"); ++ abort(); ++ } + } + + void MtpPacket::putUInt16(int offset, uint16_t value) { +- mBuffer[offset++] = (uint8_t)(value & 0xFF); +- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); ++ if ((unsigned long)(offset+2) <= mBufferSize) { ++ mBuffer[offset++] = (uint8_t)(value & 0xFF); ++ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); ++ } ++ else { ++ ALOGE("offset for buffer write is greater than buffer size!"); ++ } + } + + void MtpPacket::putUInt32(int offset, uint32_t value) { +- mBuffer[offset++] = (uint8_t)(value & 0xFF); +- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); +- mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); +- mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); ++ if ((unsigned long)(offset+4) <= mBufferSize) { ++ mBuffer[offset++] = (uint8_t)(value & 0xFF); ++ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); ++ mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); ++ mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); ++ } ++ else { ++ ALOGE("offset for buffer write is greater than buffer size!"); ++ } + } + + uint16_t MtpPacket::getContainerCode() const { diff --git a/Patches/LineageOS-16.0/android_frameworks_av/373950.patch b/Patches/LineageOS-16.0/android_frameworks_av/373950.patch new file mode 100644 index 00000000..03d599d5 --- /dev/null +++ b/Patches/LineageOS-16.0/android_frameworks_av/373950.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shruti Bihani +Date: Thu, 13 Jul 2023 09:19:08 +0000 +Subject: [PATCH] Fix heap-use-after-free issue flagged by fuzzer test. + +A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. + +Bug: 243381410 +Test: Build mtp_handle_fuzzer and run on the target device +(cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:73d89318a658ece5f337c5f9c1ec1149c52eb722) +Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 +Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 +--- + media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ + media/mtp/MtpFfsHandle.h | 4 ++++ + 2 files changed, 18 insertions(+) + +diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp +index f25fc71752..60af36457b 100644 +--- a/media/mtp/MtpFfsHandle.cpp ++++ b/media/mtp/MtpFfsHandle.cpp +@@ -294,6 +294,10 @@ int MtpFfsHandle::start(bool ptp) { + } + + void MtpFfsHandle::close() { ++ auto timeout = std::chrono::seconds(2); ++ std::unique_lock lk(m); ++ cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); ++ + io_destroy(mCtx); + closeEndpoints(); + closeConfig(); +@@ -660,6 +664,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { + char *temp = new char[me.length]; + memcpy(temp, me.data, me.length); + me.data = temp; ++ ++ std::unique_lock lk(m); ++ child_threads++; ++ lk.unlock(); ++ + std::thread t([this, me]() { return this->doSendEvent(me); }); + t.detach(); + return 0; +@@ -671,6 +680,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { + if (static_cast(ret) != length) + PLOG(ERROR) << "Mtp error sending event thread!"; + delete[] reinterpret_cast(me.data); ++ ++ std::unique_lock lk(m); ++ child_threads--; ++ lk.unlock(); ++ cv.notify_one(); + } + + } // namespace android +diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h +index fe343f74f6..ae78db2877 100644 +--- a/media/mtp/MtpFfsHandle.h ++++ b/media/mtp/MtpFfsHandle.h +@@ -58,6 +58,10 @@ protected: + + bool mCanceled; + ++ std::mutex m; ++ std::condition_variable cv; ++ std::atomic child_threads{0}; ++ + android::base::unique_fd mControl; + // "in" from the host's perspective => sink for mtp server + android::base::unique_fd mBulkIn; diff --git a/Patches/LineageOS-16.0/android_frameworks_base/373951-backport.patch b/Patches/LineageOS-16.0/android_frameworks_base/373951-backport.patch new file mode 100644 index 00000000..7cd01f22 --- /dev/null +++ b/Patches/LineageOS-16.0/android_frameworks_base/373951-backport.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nan Wu +Date: Fri, 16 Jun 2023 14:42:24 +0000 +Subject: [PATCH] DO NOT MERGE Fix BAL via notification.publicVersion + +We stripped the token that allows app to retrieve their own notification +and fire their own PI to launch activities from background. But we +forgot to strip the token from notification.publicVersion + +Bug: 278558814 +Test: NotificationManagerTest#testActivityStartFromRetrievedNotification_isBlocked +(cherry picked from commit cf851d81a954f0a6dd0c2fd7defa93932539e7f9) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1896c2e7068c9ec1ab8355d863d7e8107d5d5706) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:75fcbb37617246c43c2af34b12c9ae4b4043f9ac) +Merged-In: I8f25d7a5e47890a0496af023149717e1df482f98 +Change-Id: I8f25d7a5e47890a0496af023149717e1df482f98 +--- + core/java/android/app/Notification.java | 7 +++++-- + .../server/notification/NotificationManagerService.java | 2 +- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java +index b2daecc659cc..d456e3d57039 100644 +--- a/core/java/android/app/Notification.java ++++ b/core/java/android/app/Notification.java +@@ -2860,8 +2860,11 @@ public class Notification implements Parcelable + * + * @hide + */ +- public void setAllowlistToken(@Nullable IBinder token) { +- mWhitelistToken = token; ++ public void clearAllowlistToken() { ++ mWhitelistToken = null; ++ if (publicVersion != null) { ++ publicVersion.clearAllowlistToken(); ++ } + } + + /** +diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java +index ca0ec012fb60..a1e8cd15fd7e 100755 +--- a/services/core/java/com/android/server/notification/NotificationManagerService.java ++++ b/services/core/java/com/android/server/notification/NotificationManagerService.java +@@ -2702,7 +2702,7 @@ public class NotificationManagerService extends SystemService { + // Remove background token before returning notification to untrusted app, this + // ensures the app isn't able to perform background operations that are + // associated with notification interactions. +- notification.setAllowlistToken(null); ++ notification.clearAllowlistToken(); + return new StatusBarNotification( + sbn.getPackageName(), + sbn.getOpPkg(), diff --git a/Patches/LineageOS-16.0/android_frameworks_base/373953.patch b/Patches/LineageOS-16.0/android_frameworks_base/373953.patch new file mode 100644 index 00000000..fa11b7b7 --- /dev/null +++ b/Patches/LineageOS-16.0/android_frameworks_base/373953.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: kumarashishg +Date: Thu, 3 Aug 2023 12:01:29 +0000 +Subject: [PATCH] Use type safe API of readParcelableArray + +Bug: 291299076 +Test: Build and flash the device and check if it throws exception for +non UsbInterface object +Test: atest CtsUsbManagerTestCases +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:85d7e6712a9eeeed3bdd68ea3c3862c7e88bfe70) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:60bfbde79f2ffb012abced55d358fdf6380c0bae) +Merged-In: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503 +Change-Id: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503 +--- + core/java/android/hardware/usb/UsbConfiguration.java | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java +index 6ce420191ed3..34f5c9d0602f 100644 +--- a/core/java/android/hardware/usb/UsbConfiguration.java ++++ b/core/java/android/hardware/usb/UsbConfiguration.java +@@ -172,7 +172,8 @@ public class UsbConfiguration implements Parcelable { + String name = in.readString(); + int attributes = in.readInt(); + int maxPower = in.readInt(); +- Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader()); ++ Parcelable[] interfaces = in.readParcelableArray( ++ UsbInterface.class.getClassLoader(), UsbInterface.class); + UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower); + configuration.setInterfaces(interfaces); + return configuration; diff --git a/Patches/LineageOS-16.0/android_frameworks_base/373955.patch b/Patches/LineageOS-16.0/android_frameworks_base/373955.patch new file mode 100644 index 00000000..d0201dc4 --- /dev/null +++ b/Patches/LineageOS-16.0/android_frameworks_base/373955.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Songchun Fan +Date: Mon, 14 Aug 2023 15:24:11 -0700 +Subject: [PATCH] verify ringtone URI before setting + +Similar to ag/24422287, but the same URI verification should be done in +SettingsProvider as well, which can be called by apps via +Settings.System API or ContentProvider APIs without using +RingtoneManager. + +BUG: 227201030 +Test: manual with a test app. Will add a CTS test. +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b234678ec122994ccbfc52ac48aafdad7fdb1ed) +Merged-In: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b +Change-Id: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b +--- + .../providers/settings/SettingsProvider.java | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +index 8e8ee46b8488..b65b612ecad5 100644 +--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java ++++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +@@ -1497,6 +1497,9 @@ public class SettingsProvider extends ContentProvider { + cacheName = Settings.System.ALARM_ALERT_CACHE; + } + if (cacheName != null) { ++ if (!isValidAudioUri(name, value)) { ++ return false; ++ } + final File cacheFile = new File( + getRingtoneCacheDir(owningUserId), cacheName); + cacheFile.delete(); +@@ -1529,6 +1532,34 @@ public class SettingsProvider extends ContentProvider { + } + } + ++ private boolean isValidAudioUri(String name, String uri) { ++ if (uri != null) { ++ Uri audioUri = Uri.parse(uri); ++ if (Settings.AUTHORITY.equals( ++ ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) { ++ // Don't accept setting the default uri to self-referential URIs like ++ // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this ++ // setting. ++ return false; ++ } ++ final String mimeType = getContext().getContentResolver().getType(audioUri); ++ if (mimeType == null) { ++ Slog.e(LOG_TAG, ++ "mutateSystemSetting for setting: " + name + " URI: " + audioUri ++ + " ignored: failure to find mimeType (no access from this context?)"); ++ return false; ++ } ++ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg") ++ || mimeType.equals("application/x-flac"))) { ++ Slog.e(LOG_TAG, ++ "mutateSystemSetting for setting: " + name + " URI: " + audioUri ++ + " ignored: associated mimeType: " + mimeType + " is not an audio type"); ++ return false; ++ } ++ } ++ return true; ++ } ++ + private boolean hasWriteSecureSettingsPermission() { + // Write secure settings is a more protected permission. If caller has it we are good. + if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) diff --git a/Patches/LineageOS-16.0/android_packages_providers_TelephonyProvider/373957-backport.patch b/Patches/LineageOS-16.0/android_packages_providers_TelephonyProvider/373957-backport.patch new file mode 100644 index 00000000..5b5a0b48 --- /dev/null +++ b/Patches/LineageOS-16.0/android_packages_providers_TelephonyProvider/373957-backport.patch @@ -0,0 +1,817 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aishwarya Mallampati +Date: Wed, 23 Aug 2023 18:30:46 +0000 +Subject: [PATCH] DO NOT MERGE Block access to sms/mms db from work profile. + +Bug: 289242655 +Test: Manually verified work profile cannot access personal sms by +following steps mentioned in b/289242655#comment26 +- atest SmsProviderTest +- atest MmsProviderTest +- atest SmsBackupRestoreTest +- QA performed regression testing and confirmed fix is working as intended here: b/294459052#comment30 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:950a7e5a4bf1b38e846fe00642105479efded57d) +Merged-In: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277 +Change-Id: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277 +--- + .../providers/telephony/MmsProvider.java | 41 ++++- + .../telephony/MmsSmsDatabaseHelper.java | 156 +++++++++------- + .../providers/telephony/MmsSmsProvider.java | 36 ++++ + .../providers/telephony/SmsProvider.java | 35 ++++ + .../providers/telephony/MmsProviderTest.java | 173 ++++++++++++++++++ + .../telephony/MmsProviderTestable.java | 77 ++++++++ + .../providers/telephony/SmsProviderTest.java | 55 ++++++ + 7 files changed, 503 insertions(+), 70 deletions(-) + create mode 100644 tests/src/com/android/providers/telephony/MmsProviderTest.java + create mode 100644 tests/src/com/android/providers/telephony/MmsProviderTestable.java + +diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java +index 7546c246..9f58fc33 100644 +--- a/src/com/android/providers/telephony/MmsProvider.java ++++ b/src/com/android/providers/telephony/MmsProvider.java +@@ -25,6 +25,7 @@ import android.content.Context; + import android.content.Intent; + import android.content.UriMatcher; + import android.database.Cursor; ++import android.database.MatrixCursor; + import android.database.sqlite.SQLiteDatabase; + import android.database.sqlite.SQLiteException; + import android.database.sqlite.SQLiteOpenHelper; +@@ -34,6 +35,7 @@ import android.os.Binder; + import android.os.FileUtils; + import android.os.ParcelFileDescriptor; + import android.os.UserHandle; ++import android.os.UserManager; + import android.provider.BaseColumns; + import android.provider.Telephony; + import android.provider.Telephony.CanonicalAddressesColumns; +@@ -50,6 +52,8 @@ import android.text.TextUtils; + import android.util.EventLog; + import android.util.Log; + ++import com.android.internal.annotations.VisibleForTesting; ++ + import com.google.android.mms.pdu.PduHeaders; + import com.google.android.mms.util.DownloadDrmHelper; + +@@ -94,6 +98,16 @@ public class MmsProvider extends ContentProvider { + @Override + public Cursor query(Uri uri, String[] projection, + String selection, String[] selectionArgs, String sortOrder) { ++ Cursor emptyCursor = new MatrixCursor((projection == null) ? ++ (new String[] {}) : projection); ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to query mms, return empty cursor. ++ Log.e(TAG, "Managed profile is not allowed to query MMS."); ++ return emptyCursor; ++ } ++ + // First check if a restricted view of the "pdu" table should be used based on the + // caller's identity. Only system, phone or the default sms app can have full access + // of mms data. For other apps, we present a restricted view which only contains sent +@@ -307,6 +321,14 @@ public class MmsProvider extends ContentProvider { + + @Override + public Uri insert(Uri uri, ContentValues values) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to insert mms, return null. ++ Log.e(TAG, "Managed profile is not allowed to insert MMS."); ++ return null; ++ } ++ + final int callerUid = Binder.getCallingUid(); + final String callerPkg = getCallingPackage(); + int msgBox = Mms.MESSAGE_BOX_ALL; +@@ -622,6 +644,14 @@ public class MmsProvider extends ContentProvider { + @Override + public int delete(Uri uri, String selection, + String[] selectionArgs) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to delete mms, return 0. ++ Log.e(TAG, "Managed profile is not allowed to delete MMS."); ++ return 0; ++ } ++ + int match = sURLMatcher.match(uri); + if (LOCAL_LOGV) { + Log.v(TAG, "Delete uri=" + uri + ", match=" + match); +@@ -774,6 +804,14 @@ public class MmsProvider extends ContentProvider { + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to update mms, return 0. ++ Log.e(TAG, "Managed profile is not allowed to update MMS."); ++ return 0; ++ } ++ + // The _data column is filled internally in MmsProvider, so this check is just to avoid + // it from being inadvertently set. This is not supposed to be a protection against + // malicious attack, since sql injection could still be attempted to bypass the check. On +@@ -1062,7 +1100,8 @@ public class MmsProvider extends ContentProvider { + sURLMatcher.addURI("mms", "resetFilePerm/*", MMS_PART_RESET_FILE_PERMISSION); + } + +- private SQLiteOpenHelper mOpenHelper; ++ @VisibleForTesting ++ public SQLiteOpenHelper mOpenHelper; + + private static String concatSelections(String selection1, String selection2) { + if (TextUtils.isEmpty(selection1)) { +diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java +index 738963ed..3d765333 100644 +--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java ++++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java +@@ -708,78 +708,96 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper { + } + } + ++ @VisibleForTesting ++ public static String CREATE_ADDR_TABLE_STR = ++ "CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" + ++ Addr._ID + " INTEGER PRIMARY KEY," + ++ Addr.MSG_ID + " INTEGER," + ++ Addr.CONTACT_ID + " INTEGER," + ++ Addr.ADDRESS + " TEXT," + ++ Addr.TYPE + " INTEGER," + ++ Addr.CHARSET + " INTEGER);"; ++ ++ @VisibleForTesting ++ public static String CREATE_PART_TABLE_STR = ++ "CREATE TABLE " + MmsProvider.TABLE_PART + " (" + ++ Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + ++ Part.MSG_ID + " INTEGER," + ++ Part.SEQ + " INTEGER DEFAULT 0," + ++ Part.CONTENT_TYPE + " TEXT," + ++ Part.NAME + " TEXT," + ++ Part.CHARSET + " INTEGER," + ++ Part.CONTENT_DISPOSITION + " TEXT," + ++ Part.FILENAME + " TEXT," + ++ Part.CONTENT_ID + " TEXT," + ++ Part.CONTENT_LOCATION + " TEXT," + ++ Part.CT_START + " INTEGER," + ++ Part.CT_TYPE + " TEXT," + ++ Part._DATA + " TEXT," + ++ Part.TEXT + " TEXT);"; ++ ++ public static String CREATE_PDU_TABLE_STR = ++ "CREATE TABLE " + MmsProvider.TABLE_PDU + " (" + ++ Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + ++ Mms.THREAD_ID + " INTEGER," + ++ Mms.DATE + " INTEGER," + ++ Mms.DATE_SENT + " INTEGER DEFAULT 0," + ++ Mms.MESSAGE_BOX + " INTEGER," + ++ Mms.READ + " INTEGER DEFAULT 0," + ++ Mms.MESSAGE_ID + " TEXT," + ++ Mms.SUBJECT + " TEXT," + ++ Mms.SUBJECT_CHARSET + " INTEGER," + ++ Mms.CONTENT_TYPE + " TEXT," + ++ Mms.CONTENT_LOCATION + " TEXT," + ++ Mms.EXPIRY + " INTEGER," + ++ Mms.MESSAGE_CLASS + " TEXT," + ++ Mms.MESSAGE_TYPE + " INTEGER," + ++ Mms.MMS_VERSION + " INTEGER," + ++ Mms.MESSAGE_SIZE + " INTEGER," + ++ Mms.PRIORITY + " INTEGER," + ++ Mms.READ_REPORT + " INTEGER," + ++ Mms.REPORT_ALLOWED + " INTEGER," + ++ Mms.RESPONSE_STATUS + " INTEGER," + ++ Mms.STATUS + " INTEGER," + ++ Mms.TRANSACTION_ID + " TEXT," + ++ Mms.RETRIEVE_STATUS + " INTEGER," + ++ Mms.RETRIEVE_TEXT + " TEXT," + ++ Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," + ++ Mms.READ_STATUS + " INTEGER," + ++ Mms.CONTENT_CLASS + " INTEGER," + ++ Mms.RESPONSE_TEXT + " TEXT," + ++ Mms.DELIVERY_TIME + " INTEGER," + ++ Mms.DELIVERY_REPORT + " INTEGER," + ++ Mms.LOCKED + " INTEGER DEFAULT 0," + ++ Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT " ++ + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + ++ Mms.SEEN + " INTEGER DEFAULT 0," + ++ Mms.CREATOR + " TEXT," + ++ Mms.TEXT_ONLY + " INTEGER DEFAULT 0);"; ++ ++ @VisibleForTesting ++ public static String CREATE_RATE_TABLE_STR = ++ "CREATE TABLE " + MmsProvider.TABLE_RATE + " (" + ++ Rate.SENT_TIME + " INTEGER);"; ++ ++ @VisibleForTesting ++ public static String CREATE_DRM_TABLE_STR = ++ "CREATE TABLE " + MmsProvider.TABLE_DRM + " (" + ++ BaseColumns._ID + " INTEGER PRIMARY KEY," + ++ "_data TEXT);"; ++ + private void createMmsTables(SQLiteDatabase db) { + // N.B.: Whenever the columns here are changed, the columns in + // {@ref MmsSmsProvider} must be changed to match. +- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PDU + " (" + +- Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + +- Mms.THREAD_ID + " INTEGER," + +- Mms.DATE + " INTEGER," + +- Mms.DATE_SENT + " INTEGER DEFAULT 0," + +- Mms.MESSAGE_BOX + " INTEGER," + +- Mms.READ + " INTEGER DEFAULT 0," + +- Mms.MESSAGE_ID + " TEXT," + +- Mms.SUBJECT + " TEXT," + +- Mms.SUBJECT_CHARSET + " INTEGER," + +- Mms.CONTENT_TYPE + " TEXT," + +- Mms.CONTENT_LOCATION + " TEXT," + +- Mms.EXPIRY + " INTEGER," + +- Mms.MESSAGE_CLASS + " TEXT," + +- Mms.MESSAGE_TYPE + " INTEGER," + +- Mms.MMS_VERSION + " INTEGER," + +- Mms.MESSAGE_SIZE + " INTEGER," + +- Mms.PRIORITY + " INTEGER," + +- Mms.READ_REPORT + " INTEGER," + +- Mms.REPORT_ALLOWED + " INTEGER," + +- Mms.RESPONSE_STATUS + " INTEGER," + +- Mms.STATUS + " INTEGER," + +- Mms.TRANSACTION_ID + " TEXT," + +- Mms.RETRIEVE_STATUS + " INTEGER," + +- Mms.RETRIEVE_TEXT + " TEXT," + +- Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," + +- Mms.READ_STATUS + " INTEGER," + +- Mms.CONTENT_CLASS + " INTEGER," + +- Mms.RESPONSE_TEXT + " TEXT," + +- Mms.DELIVERY_TIME + " INTEGER," + +- Mms.DELIVERY_REPORT + " INTEGER," + +- Mms.LOCKED + " INTEGER DEFAULT 0," + +- Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT " +- + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + +- Mms.SEEN + " INTEGER DEFAULT 0," + +- Mms.CREATOR + " TEXT," + +- Mms.TEXT_ONLY + " INTEGER DEFAULT 0" + +- ");"); +- +- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" + +- Addr._ID + " INTEGER PRIMARY KEY," + +- Addr.MSG_ID + " INTEGER," + +- Addr.CONTACT_ID + " INTEGER," + +- Addr.ADDRESS + " TEXT," + +- Addr.TYPE + " INTEGER," + +- Addr.CHARSET + " INTEGER);"); +- +- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PART + " (" + +- Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + +- Part.MSG_ID + " INTEGER," + +- Part.SEQ + " INTEGER DEFAULT 0," + +- Part.CONTENT_TYPE + " TEXT," + +- Part.NAME + " TEXT," + +- Part.CHARSET + " INTEGER," + +- Part.CONTENT_DISPOSITION + " TEXT," + +- Part.FILENAME + " TEXT," + +- Part.CONTENT_ID + " TEXT," + +- Part.CONTENT_LOCATION + " TEXT," + +- Part.CT_START + " INTEGER," + +- Part.CT_TYPE + " TEXT," + +- Part._DATA + " TEXT," + +- Part.TEXT + " TEXT);"); +- +- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_RATE + " (" + +- Rate.SENT_TIME + " INTEGER);"); +- +- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_DRM + " (" + +- BaseColumns._ID + " INTEGER PRIMARY KEY," + +- "_data TEXT);"); ++ db.execSQL(CREATE_PDU_TABLE_STR); ++ ++ db.execSQL(CREATE_ADDR_TABLE_STR); ++ ++ db.execSQL(CREATE_PART_TABLE_STR); ++ ++ db.execSQL(CREATE_RATE_TABLE_STR); ++ ++ db.execSQL(CREATE_DRM_TABLE_STR); + + // Restricted view of pdu table, only sent/received messages without wap pushes + db.execSQL("CREATE VIEW " + MmsProvider.VIEW_PDU_RESTRICTED + " AS " + +diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java +index 1653cd98..ce83d679 100644 +--- a/src/com/android/providers/telephony/MmsSmsProvider.java ++++ b/src/com/android/providers/telephony/MmsSmsProvider.java +@@ -23,6 +23,7 @@ import android.content.Context; + import android.content.UriMatcher; + import android.database.Cursor; + import android.database.DatabaseUtils; ++import android.database.MatrixCursor; + import android.database.sqlite.SQLiteDatabase; + import android.database.sqlite.SQLiteOpenHelper; + import android.database.sqlite.SQLiteQueryBuilder; +@@ -30,6 +31,7 @@ import android.net.Uri; + import android.os.Binder; + import android.os.Bundle; + import android.os.UserHandle; ++import android.os.UserManager; + import android.provider.BaseColumns; + import android.provider.Telephony; + import android.provider.Telephony.CanonicalAddressesColumns; +@@ -323,6 +325,16 @@ public class MmsSmsProvider extends ContentProvider { + @Override + public Cursor query(Uri uri, String[] projection, + String selection, String[] selectionArgs, String sortOrder) { ++ Cursor emptyCursor = new MatrixCursor((projection == null) ? ++ (new String[] {}) : projection); ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to query mms/sms, return empty cursor. ++ Log.e(LOG_TAG, "Managed profile is not allowed to query MMS/SMS."); ++ return emptyCursor; ++ } ++ + // First check if restricted views of the "sms" and "pdu" tables should be used based on the + // caller's identity. Only system, phone or the default sms app can have full access + // of sms/mms data. For other apps, we present a restricted view which only contains sent +@@ -1216,6 +1228,14 @@ public class MmsSmsProvider extends ContentProvider { + @Override + public int delete(Uri uri, String selection, + String[] selectionArgs) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to delete mms/sms, return 0. ++ Log.e(LOG_TAG, "Managed profile is not allowed to delete MMS/SMS."); ++ return 0; ++ } ++ + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + Context context = getContext(); + int affectedRows = 0; +@@ -1272,6 +1292,14 @@ public class MmsSmsProvider extends ContentProvider { + + @Override + public Uri insert(Uri uri, ContentValues values) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to insert mms/sms, return null. ++ Log.e(LOG_TAG, "Managed profile is not allowed to insert MMS/SMS."); ++ return null; ++ } ++ + if (URI_MATCHER.match(uri) == URI_PENDING_MSG) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + long rowId = db.insert(TABLE_PENDING_MSG, null, values); +@@ -1283,6 +1311,14 @@ public class MmsSmsProvider extends ContentProvider { + @Override + public int update(Uri uri, ContentValues values, + String selection, String[] selectionArgs) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to update mms/sms, return 0. ++ Log.e(LOG_TAG, "Managed profile is not allowed to update MMS/SMS."); ++ return 0; ++ } ++ + final int callerUid = Binder.getCallingUid(); + final String callerPkg = getCallingPackage(); + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); +diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java +index 2b40d7eb..986c93a1 100644 +--- a/src/com/android/providers/telephony/SmsProvider.java ++++ b/src/com/android/providers/telephony/SmsProvider.java +@@ -32,6 +32,7 @@ import android.database.sqlite.SQLiteQueryBuilder; + import android.net.Uri; + import android.os.Binder; + import android.os.UserHandle; ++import android.os.UserManager; + import android.provider.Contacts; + import android.provider.Telephony; + import android.provider.Telephony.MmsSms; +@@ -113,6 +114,16 @@ public class SmsProvider extends ContentProvider { + @Override + public Cursor query(Uri url, String[] projectionIn, String selection, + String[] selectionArgs, String sort) { ++ Cursor emptyCursor = new MatrixCursor((projectionIn == null) ? ++ (new String[] {}) : projectionIn); ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to query sms, return empty cursor. ++ Log.e(TAG, "Managed profile is not allowed to query SMS."); ++ return emptyCursor; ++ } ++ + // First check if a restricted view of the "sms" table should be used based on the + // caller's identity. Only system, phone or the default sms app can have full access + // of sms data. For other apps, we present a restricted view which only contains sent +@@ -458,6 +469,14 @@ public class SmsProvider extends ContentProvider { + } + + private Uri insertInner(Uri url, ContentValues initialValues, int callerUid, String callerPkg) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to insert sms, return null. ++ Log.e(TAG, "Managed profile is not allowed to insert SMS."); ++ return null; ++ } ++ + ContentValues values; + long rowID; + int type = Sms.MESSAGE_TYPE_ALL; +@@ -651,6 +670,14 @@ public class SmsProvider extends ContentProvider { + + @Override + public int delete(Uri url, String where, String[] whereArgs) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to delete sms, return 0. ++ Log.e(TAG, "Managed profile is not allowed to delete SMS."); ++ return 0; ++ } ++ + int count; + int match = sURLMatcher.match(url); + SQLiteDatabase db = getWritableDatabase(match); +@@ -753,6 +780,14 @@ public class SmsProvider extends ContentProvider { + + @Override + public int update(Uri url, ContentValues values, String where, String[] whereArgs) { ++ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); ++ if ((userManager != null) && (userManager.isManagedProfile( ++ Binder.getCallingUserHandle().getIdentifier()))) { ++ // If work profile is trying to update sms, return 0. ++ Log.e(TAG, "Managed profile is not allowed to update SMS."); ++ return 0; ++ } ++ + final int callerUid = Binder.getCallingUid(); + final String callerPkg = getCallingPackage(); + int count = 0; +diff --git a/tests/src/com/android/providers/telephony/MmsProviderTest.java b/tests/src/com/android/providers/telephony/MmsProviderTest.java +new file mode 100644 +index 00000000..e1010e01 +--- /dev/null ++++ b/tests/src/com/android/providers/telephony/MmsProviderTest.java +@@ -0,0 +1,173 @@ ++/* ++ * Copyright (C) 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. ++ */ ++ ++package com.android.providers.telephony; ++ ++import static org.mockito.ArgumentMatchers.anyInt; ++import static org.mockito.ArgumentMatchers.anyString; ++import static org.mockito.ArgumentMatchers.eq; ++import static org.mockito.Mockito.mock; ++import static org.mockito.Mockito.when; ++ ++import android.app.AppOpsManager; ++import android.content.ContentValues; ++import android.content.Context; ++import android.content.pm.PackageManager; ++import android.content.pm.ProviderInfo; ++import android.database.ContentObserver; ++import android.database.Cursor; ++import android.net.Uri; ++import android.os.UserManager; ++import android.provider.Telephony; ++import android.telephony.TelephonyManager; ++import android.test.mock.MockContentResolver; ++import android.util.Log; ++ ++import junit.framework.TestCase; ++ ++import org.junit.Test; ++import org.mockito.Mock; ++import org.mockito.MockitoAnnotations; ++ ++public class MmsProviderTest extends TestCase { ++ private static final String TAG = "MmsProviderTest"; ++ ++ @Mock private Context mContext; ++ private MockContentResolver mContentResolver; ++ private MmsProviderTestable mMmsProviderTestable; ++ @Mock private PackageManager mPackageManager; ++ ++ private int notifyChangeCount; ++ private UserManager mUserManager; ++ ++ @Override ++ protected void setUp() throws Exception { ++ super.setUp(); ++ MockitoAnnotations.initMocks(this); ++ mMmsProviderTestable = new MmsProviderTestable(); ++ mUserManager = mock(UserManager.class); ++ ++ // setup mocks ++ when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))) ++ .thenReturn(mock(AppOpsManager.class)); ++ when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE))) ++ .thenReturn(mock(TelephonyManager.class)); ++ when(mContext.getSystemService(eq(Context.USER_SERVICE))) ++ .thenReturn(mUserManager); ++ ++ when(mContext.checkCallingOrSelfPermission(anyString())) ++ .thenReturn(PackageManager.PERMISSION_GRANTED); ++ when(mContext.getUserId()).thenReturn(0); ++ when(mContext.getPackageManager()).thenReturn(mPackageManager); ++ ++ /** ++ * This is used to give the MmsProviderTest a mocked context which takes a ++ * SmsProvider and attaches it to the ContentResolver with telephony authority. ++ * The mocked context also gives WRITE_APN_SETTINGS permissions ++ */ ++ mContentResolver = new MockContentResolver() { ++ @Override ++ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork, ++ int userHandle) { ++ notifyChangeCount++; ++ } ++ }; ++ when(mContext.getContentResolver()).thenReturn(mContentResolver); ++ ++ // Add authority="mms" to given mmsProvider ++ ProviderInfo providerInfo = new ProviderInfo(); ++ providerInfo.authority = "mms"; ++ ++ // Add context to given mmsProvider ++ mMmsProviderTestable.attachInfoForTesting(mContext, providerInfo); ++ Log.d(TAG, "MockContextWithProvider: mmsProvider.getContext(): " ++ + mMmsProviderTestable.getContext()); ++ ++ // Add given MmsProvider to mResolver with authority="mms" so that ++ // mResolver can send queries to mMmsProvider ++ mContentResolver.addProvider("mms", mMmsProviderTestable); ++ Log.d(TAG, "MockContextWithProvider: Add MmsProvider to mResolver"); ++ notifyChangeCount = 0; ++ } ++ ++ @Override ++ protected void tearDown() throws Exception { ++ super.tearDown(); ++ mMmsProviderTestable.closeDatabase(); ++ } ++ ++ @Test ++ public void testInsertMms() { ++ final ContentValues values = new ContentValues(); ++ values.put(Telephony.Mms.READ, 1); ++ values.put(Telephony.Mms.SEEN, 1); ++ values.put(Telephony.Mms.SUBSCRIPTION_ID, 1); ++ values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_ALL); ++ values.put(Telephony.Mms.TEXT_ONLY, 1); ++ values.put(Telephony.Mms.THREAD_ID, 1); ++ ++ Uri expected = Uri.parse("content://mms/1"); ++ Uri actual = mContentResolver.insert(Telephony.Mms.CONTENT_URI, values); ++ ++ assertEquals(expected, actual); ++ assertEquals(1, notifyChangeCount); ++ } ++ ++ @Test ++ public void testInsertUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try { ++ assertNull(mContentResolver.insert(Telephony.Mms.CONTENT_URI, null)); ++ } catch (Exception e) { ++ Log.d(TAG, "Error inserting mms: " + e); ++ } ++ } ++ ++ @Test ++ public void testQueryUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try (Cursor cursor = mContentResolver.query(Telephony.Mms.CONTENT_URI, ++ null, null, null, null)) { ++ assertEquals(0, cursor.getCount()); ++ } catch (Exception e) { ++ Log.d(TAG, "Exception in getting count: " + e); ++ } ++ } ++ ++ @Test ++ public void testUpdateUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try { ++ assertEquals(0, mContentResolver.update(Telephony.Mms.CONTENT_URI, null, null, null)); ++ } catch (Exception e) { ++ Log.d(TAG, "Exception in updating mms: " + e); ++ } ++ } ++ ++ @Test ++ public void testDeleteUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try { ++ assertEquals(0, mContentResolver.delete(Telephony.Mms.CONTENT_URI, null, null)); ++ } catch (Exception e) { ++ Log.d(TAG, "Exception in deleting mms: " + e); ++ } ++ } ++} +diff --git a/tests/src/com/android/providers/telephony/MmsProviderTestable.java b/tests/src/com/android/providers/telephony/MmsProviderTestable.java +new file mode 100644 +index 00000000..cea411be +--- /dev/null ++++ b/tests/src/com/android/providers/telephony/MmsProviderTestable.java +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 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. ++ */ ++ ++package com.android.providers.telephony; ++ ++import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_ADDR_TABLE_STR; ++import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_DRM_TABLE_STR; ++import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_PART_TABLE_STR; ++import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_PDU_TABLE_STR; ++import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_RATE_TABLE_STR; ++ ++import android.database.sqlite.SQLiteDatabase; ++import android.database.sqlite.SQLiteOpenHelper; ++import android.util.Log; ++ ++/** ++ * A subclass of MmsProvider used for testing on an in-memory database ++ */ ++public class MmsProviderTestable extends MmsProvider { ++ private static final String TAG = "MmsProviderTestable"; ++ ++ @Override ++ public boolean onCreate() { ++ Log.d(TAG, "onCreate called: mDbHelper = new InMemoryMmsProviderDbHelper()"); ++ mOpenHelper = new InMemoryMmsProviderDbHelper(); ++ return true; ++ } ++ ++ // close mDbHelper database object ++ protected void closeDatabase() { ++ mOpenHelper.close(); ++ } ++ ++ /** ++ * An in memory DB for MmsProviderTestable to use ++ */ ++ public static class InMemoryMmsProviderDbHelper extends SQLiteOpenHelper { ++ ++ ++ public InMemoryMmsProviderDbHelper() { ++ super(null, // no context is needed for in-memory db ++ null, // db file name is null for in-memory db ++ null, // CursorFactory is null by default ++ 1); // db version is no-op for tests ++ Log.d(TAG, "InMemoryMmsProviderDbHelper creating in-memory database"); ++ } ++ ++ @Override ++ public void onCreate(SQLiteDatabase db) { ++ // Set up the mms tables ++ Log.d(TAG, "InMemoryMmsProviderDbHelper onCreate creating the mms tables"); ++ db.execSQL(CREATE_PDU_TABLE_STR); ++ db.execSQL(CREATE_ADDR_TABLE_STR); ++ db.execSQL(CREATE_PART_TABLE_STR); ++ db.execSQL(CREATE_RATE_TABLE_STR); ++ db.execSQL(CREATE_DRM_TABLE_STR); ++ } ++ ++ @Override ++ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { ++ Log.d(TAG, "InMemorySmsProviderDbHelper onUpgrade doing nothing"); ++ } ++ } ++} +diff --git a/tests/src/com/android/providers/telephony/SmsProviderTest.java b/tests/src/com/android/providers/telephony/SmsProviderTest.java +index ba632039..13d9ae98 100644 +--- a/tests/src/com/android/providers/telephony/SmsProviderTest.java ++++ b/tests/src/com/android/providers/telephony/SmsProviderTest.java +@@ -16,6 +16,10 @@ + + package com.android.providers.telephony; + ++ ++import static org.mockito.ArgumentMatchers.anyInt; ++import static org.mockito.Mockito.when; ++ + import android.app.AppOpsManager; + import android.content.ContentResolver; + import android.content.ContentValues; +@@ -26,6 +30,7 @@ import android.content.res.Resources; + import android.database.ContentObserver; + import android.database.Cursor; + import android.net.Uri; ++import android.os.UserManager; + import android.provider.Telephony; + import android.telephony.TelephonyManager; + import android.test.mock.MockContentResolver; +@@ -57,6 +62,7 @@ public class SmsProviderTest extends TestCase { + private MockContextWithProvider mContext; + private MockContentResolver mContentResolver; + private SmsProviderTestable mSmsProviderTestable; ++ private UserManager mUserManager; + + private int notifyChangeCount; + +@@ -115,6 +121,8 @@ public class SmsProviderTest extends TestCase { + return Mockito.mock(AppOpsManager.class); + case Context.TELEPHONY_SERVICE: + return Mockito.mock(TelephonyManager.class); ++ case Context.USER_SERVICE: ++ return mUserManager; + default: + return null; + } +@@ -148,6 +156,8 @@ public class SmsProviderTest extends TestCase { + mSmsProviderTestable = new SmsProviderTestable(); + mContext = new MockContextWithProvider(mSmsProviderTestable); + mContentResolver = mContext.getContentResolver(); ++ mUserManager = Mockito.mock(UserManager.class); ++ + notifyChangeCount = 0; + } + +@@ -254,6 +264,51 @@ public class SmsProviderTest extends TestCase { + cursor.close(); + } + ++ @Test ++ public void testInsertUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try { ++ assertNull(mContentResolver.insert(Telephony.Sms.CONTENT_URI, null)); ++ } catch (Exception e) { ++ Log.d(TAG, "Error inserting sms: " + e); ++ } ++ } ++ ++ @Test ++ public void testQueryUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try (Cursor cursor = mContentResolver.query(Telephony.Sms.CONTENT_URI, ++ null, null, null, null)) { ++ assertEquals(0, cursor.getCount()); ++ } catch (Exception e) { ++ Log.d(TAG, "Exception in getting count: " + e); ++ } ++ } ++ ++ @Test ++ public void testUpdateUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try { ++ assertEquals(0, mContentResolver.update(Telephony.Sms.CONTENT_URI, null, null, null)); ++ } catch (Exception e) { ++ Log.d(TAG, "Exception in updating sms: " + e); ++ } ++ } ++ ++ @Test ++ public void testDeleteUsingManagedProfile() { ++ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true); ++ ++ try { ++ assertEquals(0, mContentResolver.delete(Telephony.Sms.CONTENT_URI, null, null)); ++ } catch (Exception e) { ++ Log.d(TAG, "Exception in deleting sms: " + e); ++ } ++ } ++ + private ContentValues getFakeRawValue() { + ContentValues values = new ContentValues(); + values.put("pdu", mFakePdu); diff --git a/Scripts/LineageOS-15.1/Patch.sh b/Scripts/LineageOS-15.1/Patch.sh index 747a268b..a1844979 100644 --- a/Scripts/LineageOS-15.1/Patch.sh +++ b/Scripts/LineageOS-15.1/Patch.sh @@ -339,7 +339,7 @@ fi; if enterAndClear "packages/apps/Messaging"; then applyPatch "$DOS_PATCHES_COMMON/android_packages_apps_Messaging/0001-null-fix.patch"; #Handle null case (GrapheneOS) -applyPatch "$DOS_PATCHES_COMMON/android_packages_apps_Messaging/0002-missing-channels.patch"; #Add notification channels where missing (LineageOS) +#applyPatch "$DOS_PATCHES_COMMON/android_packages_apps_Messaging/0002-missing-channels.patch"; #Add notification channels where missing (LineageOS) fi; if enterAndClear "packages/apps/PackageInstaller"; then diff --git a/Scripts/LineageOS-16.0/Patch.sh b/Scripts/LineageOS-16.0/Patch.sh index 0e5a7015..2af46cc3 100644 --- a/Scripts/LineageOS-16.0/Patch.sh +++ b/Scripts/LineageOS-16.0/Patch.sh @@ -99,7 +99,7 @@ applyPatch "$DOS_PATCHES_COMMON/android_build/0001-verity-openssl3.patch"; #Fix sed -i '74i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aapt2.mk; #Enable auto-add-overlay for packages, this allows the vendor overlay to easily work across all branches. sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 17/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS) awk -i inplace '!/Email/' target/product/core.mk; #Remove Email -sed -i 's/2022-01-05/2023-10-05/' core/version_defaults.mk; #Bump Security String #P_asb_2023-10 #XXX +sed -i 's/2022-01-05/2023-11-05/' core/version_defaults.mk; #Bump Security String #P_asb_2023-11 #XXX fi; if enterAndClear "build/soong"; then @@ -149,6 +149,10 @@ if enterAndClear "external/libvpx"; then applyPatch "$DOS_PATCHES_COMMON/android_external_libvpx/CVE-2023-5217.patch"; #VP8: disallow thread count changes fi; +if enterAndClear "external/webp"; then +applyPatch "$DOS_PATCHES_COMMON/android_external_webp/373948.patch"; #R_asb_2023-11 Update to v1.1.0-8-g50f60add +fi; + if enterAndClear "external/libxml2"; then applyPatch "$DOS_PATCHES/android_external_libxml2/368053.patch"; #R_asb_2023-10 malloc-fail: Fix OOB read after xmlRegGetCounter fi; @@ -161,6 +165,8 @@ awk -i inplace '!/deletePackage/' pico/src/com/svox/pico/LangPackUninstaller.jav fi; if enterAndClear "frameworks/av"; then +applyPatch "$DOS_PATCHES/android_frameworks_av/373949.patch"; #R_asb_2023-11 Fix for heap buffer overflow issue flagged by fuzzer test. +#applyPatch "$DOS_PATCHES/android_frameworks_av/373950.patch"; #R_asb_2023-11 Fix heap-use-after-free issue flagged by fuzzer test. #XXX: error: use of class template 'std::unique_lock' requires template arguments if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_frameworks_av/0001-HM-No_RLIMIT_AS.patch"; fi; #(GrapheneOS) fi; @@ -172,6 +178,9 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/368061.patch"; #R_asb_2023-10 F applyPatch "$DOS_PATCHES/android_frameworks_base/368062-backport.patch"; #R_asb_2023-10 Disallow loading icon from content URI to PipMenu applyPatch "$DOS_PATCHES/android_frameworks_base/368063.patch"; #R_asb_2023-10 Fixing DatabaseUtils to detect malformed UTF-16 strings applyPatch "$DOS_PATCHES/android_frameworks_base/368067-backport.patch"; #R_asb_2023-10 Revert "DO NOT MERGE Dismiss keyguard when simpin auth'd and..." +applyPatch "$DOS_PATCHES/android_frameworks_base/373951-backport.patch"; #R_asb_2023-11 Fix BAL via notification.publicVersion +applyPatch "$DOS_PATCHES/android_frameworks_base/373953.patch"; #R_asb_2023-11 Use type safe API of readParcelableArray +applyPatch "$DOS_PATCHES/android_frameworks_base/373955.patch"; #R_asb_2023-11 [SettingsProvider] verify ringtone URI before setting applyPatch "$DOS_PATCHES/android_frameworks_base/0007-Always_Restict_Serial.patch"; #Always restrict access to Build.SERIAL (GrapheneOS) applyPatch "$DOS_PATCHES/android_frameworks_base/0008-Browser_No_Location.patch"; #Don't grant location permission to system browsers (GrapheneOS) applyPatch "$DOS_PATCHES/android_frameworks_base/0009-SystemUI_No_Permission_Review.patch"; #Allow SystemUI to directly manage Bluetooth/WiFi (GrapheneOS) @@ -307,7 +316,7 @@ fi; if enterAndClear "packages/apps/Messaging"; then applyPatch "$DOS_PATCHES_COMMON/android_packages_apps_Messaging/0001-null-fix.patch"; #Handle null case (GrapheneOS) -applyPatch "$DOS_PATCHES_COMMON/android_packages_apps_Messaging/0002-missing-channels.patch"; #Add notification channels where missing (LineageOS) +#applyPatch "$DOS_PATCHES_COMMON/android_packages_apps_Messaging/0002-missing-channels.patch"; #Add notification channels where missing (LineageOS) fi; if enterAndClear "packages/apps/Nfc"; then @@ -360,9 +369,10 @@ if enterAndClear "packages/providers/DownloadProvider"; then applyPatch "$DOS_PATCHES/android_packages_providers_DownloadProvider/0001-Network_Permission.patch"; #Expose the NETWORK permission (GrapheneOS) fi; -#if enterAndClear "packages/providers/TelephonyProvider"; then +if enterAndClear "packages/providers/TelephonyProvider"; then +applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/373957-backport.patch"; #R_asb_2023-11 Block access to sms/mms db from work profile. #cp $DOS_PATCHES_COMMON/android_packages_providers_TelephonyProvider/carrier_list.* assets/; -#fi; +fi; if enterAndClear "packages/services/Telephony"; then git revert --no-edit 99564aaf0417c9ddf7d6aeb10d326e5b24fa8f55;