diff --git a/aosp_diff/preliminary/build/make/0004-Update-security_patch_level-string.patch b/aosp_diff/preliminary/build/make/0004-Update-security_patch_level-string.patch index ccd6a44c1e..d071b358d0 100644 --- a/aosp_diff/preliminary/build/make/0004-Update-security_patch_level-string.patch +++ b/aosp_diff/preliminary/build/make/0004-Update-security_patch_level-string.patch @@ -20,7 +20,7 @@ index 419ff1aadc..fbbe777754 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 := 2023-05-05 -+ PLATFORM_SECURITY_PATCH := 2025-02-01 ++ PLATFORM_SECURITY_PATCH := 2025-03-01 endif include $(BUILD_SYSTEM)/version_util.mk diff --git a/aosp_diff/preliminary/external/dng_sdk/0001-Catch-null-HuffmanTables-when-decoding-jpeg.bulletin.patch b/aosp_diff/preliminary/external/dng_sdk/0001-Catch-null-HuffmanTables-when-decoding-jpeg.bulletin.patch new file mode 100644 index 0000000000..78e73fd46a --- /dev/null +++ b/aosp_diff/preliminary/external/dng_sdk/0001-Catch-null-HuffmanTables-when-decoding-jpeg.bulletin.patch @@ -0,0 +1,33 @@ +From ee3f2ff4c3e1d737b409c87866decc29a321d7c7 Mon Sep 17 00:00:00 2001 +From: Nick Chusid +Date: Tue, 10 Dec 2024 22:46:28 +0000 +Subject: [PATCH] Catch null HuffmanTables when decoding jpeg + +Bug: 347735428 +Test: TreeHugger +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a22d1f0f07d998a53dd49a941d3a588f55b36399) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c506235a45be1c7c9f1a836495417d78f8718028) +Merged-In: Iaf36c076467d18e4e31d8436a6d199c3276a8786 +Change-Id: Iaf36c076467d18e4e31d8436a6d199c3276a8786 +--- + source/dng_lossless_jpeg.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/source/dng_lossless_jpeg.cpp b/source/dng_lossless_jpeg.cpp +index 9d0d01a..8802f32 100644 +--- a/source/dng_lossless_jpeg.cpp ++++ b/source/dng_lossless_jpeg.cpp +@@ -1616,6 +1616,10 @@ inline int32 dng_lossless_decoder::get_bit () + inline int32 dng_lossless_decoder::HuffDecode (HuffmanTable *htbl) + { + ++ if (htbl == nullptr) { ++ ThrowBadFormat (); ++ } ++ + // If the huffman code is less than 8 bits, we can use the fast + // table lookup to get its value. It's more than 8 bits about + // 3-4% of the time. +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0236-DO-NOT-MERGE-Hide-Android-data-obb-sanbox-on-shared-.patch b/aosp_diff/preliminary/frameworks/base/99_0236-DO-NOT-MERGE-Hide-Android-data-obb-sanbox-on-shared-.patch new file mode 100644 index 0000000000..94ed2b061a --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0236-DO-NOT-MERGE-Hide-Android-data-obb-sanbox-on-shared-.patch @@ -0,0 +1,106 @@ +From cec67a1f90d6f7cdb120743e408c7c7ee34ce66d Mon Sep 17 00:00:00 2001 +From: Sergey Nikolaienkov +Date: Sat, 1 Jul 2023 16:03:56 +0200 +Subject: [PATCH] DO NOT MERGE: "Hide" /Android/data|obb|sanbox/ on shared + storage + +Implement shouldHideDocument() in the ExternalStorageProvider so that it +resitcts access to 'Android/data/', 'Android/obb/' and 'Android/sandbox' +on the integrated shared storage along with all their content and +subdirectories. + +Clean up the abstract FileSystemProvider, specifically all variants of +queryChildDocuments(). + +Bug: 200034476 +Bug: 220066255 +Bug: 283962634 +Test: make & flash systemimage, run manually +Test: atest ExternalStorageProviderTests +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:131e73e1b3839111463aae26bae1b3db6782eb38) +Merged-In: I48c2ce7ff2d7fc067961ea2af0ea63818316f086 +Change-Id: I48c2ce7ff2d7fc067961ea2af0ea63818316f086 +--- + .../ExternalStorageProvider.java | 28 +++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +index defbc1142adb..b34ce0a18325 100644 +--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java ++++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +@@ -16,6 +16,8 @@ + + package com.android.externalstorage; + ++import static java.util.regex.Pattern.CASE_INSENSITIVE; ++ + import android.annotation.NonNull; + import android.annotation.Nullable; + import android.app.usage.StorageStatsManager; +@@ -67,6 +69,7 @@ import java.util.List; + import java.util.Locale; + import java.util.Objects; + import java.util.UUID; ++import java.util.regex.Pattern; + import java.util.stream.Collectors; + + /** +@@ -94,6 +97,13 @@ public class ExternalStorageProvider extends FileSystemProvider { + + private static final String STORAGE_PATH = "/storage/"; + ++ /** ++ * Regex for detecting {@code /Android/data/}, {@code /Android/obb/} and ++ * {@code /Android/sandbox/} along with all their subdirectories and content. ++ */ ++ private static final Pattern PATTERN_RESTRICTED_ANDROID_SUBTREES = ++ Pattern.compile("^Android/(?:data|obb|sandbox)(?:/.+)?", CASE_INSENSITIVE); ++ + private static final String[] DEFAULT_ROOT_PROJECTION = new String[] { + Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE, + Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES, Root.COLUMN_QUERY_ARGS +@@ -307,13 +317,16 @@ public class ExternalStorageProvider extends FileSystemProvider { + return false; + } + +- try { ++ final String path = getPathFromDocId(documentId); ++ return PATTERN_RESTRICTED_ANDROID_SUBTREES.matcher(path).matches(); ++ ++ /* try { + final RootInfo root = getRootFromDocId(documentId); + final String canonicalPath = getPathFromDocId(documentId); + return isRestrictedPath(root.rootId, canonicalPath); + } catch (Exception e) { + return true; +- } ++ }*/ + } + + /** +@@ -634,6 +647,13 @@ public class ExternalStorageProvider extends FileSystemProvider { + return result; + } + ++ /** ++ * Print the state into the given stream. ++ * Gets invoked when you run: ++ *
++     * adb shell dumpsys activity provider com.android.externalstorage/.ExternalStorageProvider
++     * 
++ */ + @Override + public Path findDocumentPath(@Nullable String parentDocId, String childDocId) + throws FileNotFoundException { +@@ -835,4 +855,8 @@ public class ExternalStorageProvider extends FileSystemProvider { + private static boolean equalIgnoringCase(@NonNull String a, @NonNull String b) { + return TextUtils.equals(a.toLowerCase(Locale.ROOT), b.toLowerCase(Locale.ROOT)); + } ++ ++ private static boolean equalIgnoringCase(@NonNull String a, @NonNull String b) { ++ return TextUtils.equals(a.toLowerCase(Locale.ROOT), b.toLowerCase(Locale.ROOT)); ++ } + } +-- +2.34.1 + diff --git a/aosp_diff/preliminary/frameworks/base/99_0237-Restrict-access-to-directories.patch b/aosp_diff/preliminary/frameworks/base/99_0237-Restrict-access-to-directories.patch new file mode 100644 index 0000000000..10a5c40cee --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0237-Restrict-access-to-directories.patch @@ -0,0 +1,78 @@ +From bbfb5f279aa5c0986cbd51f6ab217bb56f0a49d5 Mon Sep 17 00:00:00 2001 +From: Dipankar Bhardwaj +Date: Wed, 21 Aug 2024 14:26:50 +0000 +Subject: [PATCH] Restrict access to directories + +Restricted access to Android/data, Android/obb and Android/sandbox +directories and its sub-directories. Replacing path's pattern match +check with file equality check. + +Test: atest DocumentsClientTest +Bug: 341680936 +Flag: EXEMPT bug fix +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:18a5a8395f301b77474ee377e38fd1aa4996036d) +Merged-In: I8879900e57e1702d11797b81e86d0cc3f55bac22 +Change-Id: I8879900e57e1702d11797b81e86d0cc3f55bac22 +--- + .../ExternalStorageProvider.java | 19 +++++-------------- + 1 file changed, 5 insertions(+), 14 deletions(-) + +diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +index b34ce0a18325..64a4eb2f858f 100644 +--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java ++++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +@@ -16,8 +16,6 @@ + + package com.android.externalstorage; + +-import static java.util.regex.Pattern.CASE_INSENSITIVE; +- + import android.annotation.NonNull; + import android.annotation.Nullable; + import android.app.usage.StorageStatsManager; +@@ -69,7 +67,6 @@ import java.util.List; + import java.util.Locale; + import java.util.Objects; + import java.util.UUID; +-import java.util.regex.Pattern; + import java.util.stream.Collectors; + + /** +@@ -97,12 +94,9 @@ public class ExternalStorageProvider extends FileSystemProvider { + + private static final String STORAGE_PATH = "/storage/"; + +- /** +- * Regex for detecting {@code /Android/data/}, {@code /Android/obb/} and +- * {@code /Android/sandbox/} along with all their subdirectories and content. +- */ +- private static final Pattern PATTERN_RESTRICTED_ANDROID_SUBTREES = +- Pattern.compile("^Android/(?:data|obb|sandbox)(?:/.+)?", CASE_INSENSITIVE); ++ private static final String PRIMARY_EMULATED_STORAGE_PATH = "/storage/emulated/"; ++ ++ private static final String STORAGE_PATH = "/storage/"; + + private static final String[] DEFAULT_ROOT_PROJECTION = new String[] { + Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE, +@@ -317,16 +311,13 @@ public class ExternalStorageProvider extends FileSystemProvider { + return false; + } + +- final String path = getPathFromDocId(documentId); +- return PATTERN_RESTRICTED_ANDROID_SUBTREES.matcher(path).matches(); +- +- /* try { ++ try { + final RootInfo root = getRootFromDocId(documentId); + final String canonicalPath = getPathFromDocId(documentId); + return isRestrictedPath(root.rootId, canonicalPath); + } catch (Exception e) { + return true; +- }*/ ++ } + } + + /** +-- +2.34.1 + diff --git a/aosp_diff/preliminary/frameworks/base/99_0238-Resolve-cross-account-user-icon-validation-.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0238-Resolve-cross-account-user-icon-validation-.bulletin.patch new file mode 100644 index 0000000000..e3a0cdeed5 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0238-Resolve-cross-account-user-icon-validation-.bulletin.patch @@ -0,0 +1,88 @@ +From 71a03fd10e222b6ed5f540f8cc5272a73bd85a57 Mon Sep 17 00:00:00 2001 +From: Pranav Madapurmath +Date: Thu, 2 Jan 2025 14:58:50 -0800 +Subject: [PATCH] Resolve cross account user icon validation. + +Resolves a vulnerability found with the cross account user icon +validation in StatusHint and TelecomServiceImpl (when registering a +phone account). The reporter found that an uri formatted as `userId%` +isn't parsed properly with the existing reference to Uri.encodedUserInfo. + +Bug: 376461551 +Bug: 376259166 +Flag: EXEMPT bugfix +Test: atest TelecomServiceImplTest +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:81c9a17787743df280adac58ab5f74c084d058e1) +Merged-In: I25614ead889501f4553ed2b42b366e09a47b0c9f +Change-Id: I25614ead889501f4553ed2b42b366e09a47b0c9f +--- + .../java/android/telecom/StatusHints.java | 34 +++++++++++++++---- + 1 file changed, 28 insertions(+), 6 deletions(-) + +diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java +index 5f0c8d729e74..31b84ff04b85 100644 +--- a/telecomm/java/android/telecom/StatusHints.java ++++ b/telecomm/java/android/telecom/StatusHints.java +@@ -27,6 +27,7 @@ import android.os.Bundle; + import android.os.Parcel; + import android.os.Parcelable; + import android.os.UserHandle; ++import android.util.Log; + + import com.android.internal.annotations.VisibleForTesting; + +@@ -40,6 +41,7 @@ public final class StatusHints implements Parcelable { + private final CharSequence mLabel; + private Icon mIcon; + private final Bundle mExtras; ++ private static final String TAG = StatusHints.class.getSimpleName(); + + /** + * @hide +@@ -150,17 +152,37 @@ public final class StatusHints implements Parcelable { + // 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); +- // Do not try to save the icon if the user id isn't in the calling user space. +- if (userId != callingUserHandle.getIdentifier()) return null; ++ int callingUserId = callingUserHandle.getIdentifier(); ++ int requestingUserId = getUserIdFromAuthority( ++ icon.getUri().getAuthority(), callingUserId); ++ if (callingUserId != requestingUserId) { ++ return null; + } ++ + } + return icon; + } + ++ /** ++ * Derives the user id from the authority or the default user id if none could be found. ++ * @param auth ++ * @param defaultUserId ++ * @return The user id from the given authority. ++ * @hide ++ */ ++ public static int getUserIdFromAuthority(String auth, int defaultUserId) { ++ if (auth == null) return defaultUserId; ++ int end = auth.lastIndexOf('@'); ++ if (end == -1) return defaultUserId; ++ String userIdString = auth.substring(0, end); ++ try { ++ return Integer.parseInt(userIdString); ++ } catch (NumberFormatException e) { ++ Log.w(TAG, "Error parsing userId." + e); ++ return UserHandle.USER_NULL; ++ } ++ } ++ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeCharSequence(mLabel); +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0239-Check-account-type-returned-by-AbstractAccountAuthenticator-.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0239-Check-account-type-returned-by-AbstractAccountAuthenticator-.bulletin.patch new file mode 100644 index 0000000000..ce0b610684 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0239-Check-account-type-returned-by-AbstractAccountAuthenticator-.bulletin.patch @@ -0,0 +1,41 @@ +From 5f3837ea2375add2320ae10f940363b8262db9df Mon Sep 17 00:00:00 2001 +From: Dmitry Dementyev +Date: Thu, 19 Dec 2024 11:02:42 -0800 +Subject: [PATCH] Check account type returned by AbstractAccountAuthenticator. + +AccountManagerService already knows which account is used during +AbstractAccountAuthenticator.getAuthToken. + +KEY_ACCOUNT_NAME and KEY_ACCOUNT_TYPE in the response look unnecessary, +but we can't change API at this moment. + +Bug: 364269936 +Test: manual +Flag: EXEMPT bugfix +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1ab5ce4282ba251bd7e6904c4a7fae1f7a209990) +Merged-In: Ifc62866f4feaca43abc32bc542b97f3741953f56 +Change-Id: Ifc62866f4feaca43abc32bc542b97f3741953f56 +--- + .../com/android/server/accounts/AccountManagerService.java | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java +index 70f66cae50f0..847806a0b4f9 100644 +--- a/services/core/java/com/android/server/accounts/AccountManagerService.java ++++ b/services/core/java/com/android/server/accounts/AccountManagerService.java +@@ -3073,6 +3073,12 @@ public class AccountManagerService + "the type and name should not be empty"); + return; + } ++ if (!type.equals(mAccountType)) { ++ onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, ++ "incorrect account type"); ++ return; ++ } ++ + Account resultAccount = new Account(name, type); + if (!customTokens) { + saveAuthTokenToDatabase( +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/frameworks/base/99_0240-RESTRICT-AUTOMERGE-PM-Fix-the-profile-issue-in-UninstallerActi.bulletin.patch b/aosp_diff/preliminary/frameworks/base/99_0240-RESTRICT-AUTOMERGE-PM-Fix-the-profile-issue-in-UninstallerActi.bulletin.patch new file mode 100644 index 0000000000..6e51fa3cdb --- /dev/null +++ b/aosp_diff/preliminary/frameworks/base/99_0240-RESTRICT-AUTOMERGE-PM-Fix-the-profile-issue-in-UninstallerActi.bulletin.patch @@ -0,0 +1,71 @@ +From 33fb7e48e4ea3ed3193ee796c91a51f8d52ce95e Mon Sep 17 00:00:00 2001 +From: Ivan Chiang +Date: Tue, 24 Dec 2024 08:22:39 +0000 +Subject: [PATCH] RESTRICT AUTOMERGE [PM] Fix the profile issue in + UninstallerActivity + +Only the parent profile can uninstall the app that is in the child +profiles. + +Flag: EXEMPT security bug fix +Bug: 333681693 +Test: atest CtsPackageInstallerCUJMultiUsersTestCases +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:585d5d6835dd2ddd65316fbbabd714c140da20fa) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ed9c714e6533aabc00f26ed9bb31d7ce90f3e367) +Merged-In: Id4eb5484563fdec530d5fc89a2c5973c351fdab8 +Change-Id: Id4eb5484563fdec530d5fc89a2c5973c351fdab8 +--- + .../packageinstaller/UninstallerActivity.java | 20 ++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + mode change 100755 => 100644 packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java + +diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java +old mode 100755 +new mode 100644 +index 0198168f9fda..f487bfbd28c7 +--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java ++++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java +@@ -51,6 +51,7 @@ import android.net.Uri; + import android.os.Build; + import android.os.Bundle; + import android.os.IBinder; ++import android.os.Process; + import android.os.RemoteException; + import android.os.ServiceManager; + import android.os.UserHandle; +@@ -63,8 +64,6 @@ import com.android.packageinstaller.television.ErrorFragment; + import com.android.packageinstaller.television.UninstallAlertFragment; + import com.android.packageinstaller.television.UninstallAppProgress; + +-import java.util.List; +- + /* + * This activity presents UI to uninstall an application. Usually launched with intent + * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute +@@ -172,13 +171,16 @@ public class UninstallerActivity extends Activity { + if (mDialogInfo.user == null) { + mDialogInfo.user = android.os.Process.myUserHandle(); + } else { +- UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); +- List profiles = userManager.getUserProfiles(); +- if (!profiles.contains(mDialogInfo.user)) { +- Log.e(TAG, "User " + android.os.Process.myUserHandle() + " can't request uninstall " +- + "for user " + mDialogInfo.user); +- showUserIsNotAllowed(); +- return; ++ if (!mDialogInfo.user.equals(Process.myUserHandle())) { ++ UserManager userManager = getBaseContext().getSystemService(UserManager.class); ++ final boolean isCurrentUserProfileOwner = Process.myUserHandle().equals( ++ userManager.getProfileParent(mDialogInfo.user)); ++ if (!isCurrentUserProfileOwner) { ++ Log.e(TAG, "User " + Process.myUserHandle() + " can't request uninstall " ++ + "for user " + mDialogInfo.user); ++ showUserIsNotAllowed(); ++ return; ++ } + } + } + +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/frameworks/native/14_0014-servicemanager-set-consistent-flags-for-self-reg.bulletin.patch b/aosp_diff/preliminary/frameworks/native/14_0014-servicemanager-set-consistent-flags-for-self-reg.bulletin.patch new file mode 100644 index 0000000000..4234085926 --- /dev/null +++ b/aosp_diff/preliminary/frameworks/native/14_0014-servicemanager-set-consistent-flags-for-self-reg.bulletin.patch @@ -0,0 +1,32 @@ +From 2ea642624389265e96c0fb8bf6fd84c93f0f9691 Mon Sep 17 00:00:00 2001 +From: Steven Moreland +Date: Fri, 6 Dec 2024 23:55:35 +0000 +Subject: [PATCH] servicemanager: set consistent flags for self-reg + +SM has special flags set to become a context object, but +these were not set when it registers as itself. + +Bug: 382775095 +Test: boot w/ harsher checks +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0712dc9870ace727ee09dc67bec84d4d3cf41e6d) +Merged-In: I0fb567cbcca67a2fc6c088f652c8af570b8d7e53 +Change-Id: I0fb567cbcca67a2fc6c088f652c8af570b8d7e53 +--- + cmds/servicemanager/main.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp +index 2fb9c2bc9a..dac6d96347 100644 +--- a/cmds/servicemanager/main.cpp ++++ b/cmds/servicemanager/main.cpp +@@ -126,6 +126,7 @@ int main(int argc, char** argv) { + ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY); + + sp manager = sp::make(std::make_unique()); ++ manager->setRequestingSid(true); + if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) { + LOG(ERROR) << "Could not self register servicemanager"; + } +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/packages/modules/Bluetooth/69_0069-RESTRICT-AUTOMERGE-backport-opp-validate-that-conten.patch b/aosp_diff/preliminary/packages/modules/Bluetooth/69_0069-RESTRICT-AUTOMERGE-backport-opp-validate-that-conten.patch new file mode 100644 index 0000000000..286ea130df --- /dev/null +++ b/aosp_diff/preliminary/packages/modules/Bluetooth/69_0069-RESTRICT-AUTOMERGE-backport-opp-validate-that-conten.patch @@ -0,0 +1,75 @@ +From a5da2151fc4c7a9980f09c2bfbb56429c7ca2989 Mon Sep 17 00:00:00 2001 +From: Billy Huang +Date: Wed, 2 Oct 2024 14:45:37 -0700 +Subject: [PATCH] RESTRICT AUTOMERGE backport "opp: validate that content uri + belongs to current user" + +Bug: 296915500 +Flag: EXEMPT trivial fix with complete testing coverage +Test: atest GoogleBluetoothInstrumentationTests:BluetoothOppSendFileInfoTest +Ignore-AOSP-First: fix for undisclosed vulnerability +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5bcfd347823f1d3893d843db2286f2013923fad8) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d2e609af40232d899621465e5cd7eeb670476240) +Merged-In: Ibff36089bfde4b5bb28d797aeae1423b668943a2 +Change-Id: Ibff36089bfde4b5bb28d797aeae1423b668943a2 +--- + .../bluetooth/opp/BluetoothOppSendFileInfo.java | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java +index 2adb8e5f44..7ce134341a 100644 +--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java ++++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java +@@ -32,6 +32,8 @@ + + package com.android.bluetooth.opp; + ++import static android.os.UserHandle.myUserId; ++ + import android.content.ContentResolver; + import android.content.Context; + import android.content.res.AssetFileDescriptor; +@@ -39,6 +41,7 @@ import android.database.Cursor; + import android.database.sqlite.SQLiteException; + import android.net.Uri; + import android.provider.OpenableColumns; ++import android.text.TextUtils; + import android.util.EventLog; + import android.util.Log; + +@@ -49,6 +52,7 @@ import java.io.File; + import java.io.FileInputStream; + import java.io.FileNotFoundException; + import java.io.IOException; ++import java.util.Objects; + + /** + * This class stores information about a single sending file It will only be +@@ -117,6 +121,11 @@ public class BluetoothOppSendFileInfo { + return SEND_FILE_INFO_ERROR; + } + ++ if (isContentUriForOtherUser(uri)) { ++ Log.e(TAG, "Uri: " + uri + " is invalid for user " + myUserId()); ++ return SEND_FILE_INFO_ERROR; ++ } ++ + contentType = contentResolver.getType(uri); + Cursor metadataCursor; + try { +@@ -253,6 +262,12 @@ public class BluetoothOppSendFileInfo { + return new BluetoothOppSendFileInfo(fileName, contentType, length, is, 0); + } + ++ private static boolean isContentUriForOtherUser(Uri uri) { ++ String uriUserId = uri.getUserInfo(); ++ return !TextUtils.isEmpty(uriUserId) ++ && !Objects.equals(uriUserId, String.valueOf(myUserId())); ++ } ++ + private static long getStreamSize(FileInputStream is) throws IOException { + long length = 0; + byte[] unused = new byte[4096]; +-- +2.34.1 + diff --git a/aosp_diff/preliminary/packages/modules/Bluetooth/70_0070-Reset-permissions-for-not-bonded-device.bulletin.patch b/aosp_diff/preliminary/packages/modules/Bluetooth/70_0070-Reset-permissions-for-not-bonded-device.bulletin.patch new file mode 100644 index 0000000000..7dda9f33dd --- /dev/null +++ b/aosp_diff/preliminary/packages/modules/Bluetooth/70_0070-Reset-permissions-for-not-bonded-device.bulletin.patch @@ -0,0 +1,51 @@ +From d159e671f0eae43322f36cb14a4d6d67459cf33f Mon Sep 17 00:00:00 2001 +From: Brian Delwiche +Date: Thu, 14 Nov 2024 00:35:48 +0000 +Subject: [PATCH] Reset permissions for not bonded device + +According to the PBAP specification, +The PSE user shall have to confirm at least the first Phone Book Access +Profile connection from each new PCE. + +According to the MAP specification, +The MCE and MSE shall be bonded before setting up a Message Access Profile +connection. + +Let's remove the permissions when the device is unbonded. + +This is a backport of change ag/30386015 but requires minor changes to +logic. + +Flag: EXEMPT, security fix +Bug: 289375038 +Bug: 289811388 +Test: atest BluetoothInstrumentationTests +Ignore-AOSP-First: security fix +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8507ce69bb6e4e508a82cfc41dce56be1450a62e) +Merged-In: I8b9b29310db2d14e5dfaddc81a682366fbef42d3 +Change-Id: I8b9b29310db2d14e5dfaddc81a682366fbef42d3 +--- + .../com/android/bluetooth/btservice/BondStateMachine.java | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java +index d62d7ba06d..1a1c912f3f 100644 +--- a/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java ++++ b/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java +@@ -439,6 +439,13 @@ final class BondStateMachine extends StateMachine { + } + } + ++ if (newState == BluetoothDevice.BOND_NONE) { ++ // Remove the permissions for unbonded devices ++ mAdapterService.setMessageAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); ++ mAdapterService.setPhonebookAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); ++ mAdapterService.setSimAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN); ++ } ++ + Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, newState); +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/packages/modules/Bluetooth/71_0071-Use-encrypted-link-for-avdtp-and-avctp-channels.bulletin.patch b/aosp_diff/preliminary/packages/modules/Bluetooth/71_0071-Use-encrypted-link-for-avdtp-and-avctp-channels.bulletin.patch new file mode 100644 index 0000000000..98f3d4c227 --- /dev/null +++ b/aosp_diff/preliminary/packages/modules/Bluetooth/71_0071-Use-encrypted-link-for-avdtp-and-avctp-channels.bulletin.patch @@ -0,0 +1,111 @@ +From abcf06b00640b5fe7d45318c601796660751879b Mon Sep 17 00:00:00 2001 +From: Brian Delwiche +Date: Mon, 23 Sep 2024 18:22:36 +0000 +Subject: [PATCH] Use encrypted link for avdtp and avctp channels + +This is a backport of the AOSP changes for b/345258562. + +Test: mmm packages/modules/Bluetooth +Bug: 345258562 +Ignore-AOSP-First: security +Tag: #security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d26e79ab057057cbfcafc5eaeaaf1581afebd007) +Merged-In: I4ef23f9dec4aaae6a526c11a7c2489159bd7fdf8 +Change-Id: I4ef23f9dec4aaae6a526c11a7c2489159bd7fdf8 +--- + system/stack/avct/avct_api.cc | 6 ++++-- + system/stack/avct/avct_bcb_act.cc | 5 +++-- + system/stack/avct/avct_lcb_act.cc | 3 ++- + system/stack/avdt/avdt_ad.cc | 3 ++- + system/stack/avdt/avdt_api.cc | 3 ++- + 5 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc +index b52e1afdf4..3254264092 100644 +--- a/system/stack/avct/avct_api.cc ++++ b/system/stack/avct/avct_api.cc +@@ -63,9 +63,11 @@ void AVCT_Register() { + /* initialize AVCTP data structures */ + memset(&avct_cb, 0, sizeof(tAVCT_CB)); + ++ uint16_t sec = BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT; ++ + /* register PSM with L2CAP */ + L2CA_Register2(AVCT_PSM, avct_l2c_appl, true /* enable_snoop */, nullptr, +- kAvrcMtu, 0, BTA_SEC_AUTHENTICATE); ++ kAvrcMtu, 0, sec); + + /* Include the browsing channel which uses eFCR */ + tL2CAP_ERTM_INFO ertm_info; +@@ -73,7 +75,7 @@ void AVCT_Register() { + + L2CA_Register2(AVCT_BR_PSM, avct_l2c_br_appl, true /*enable_snoop*/, + &ertm_info, kAvrcBrMtu, AVCT_MIN_BROWSE_MTU, +- BTA_SEC_AUTHENTICATE); ++ sec); + + avct_cb.trace_level = avct_trace_level; + } +diff --git a/system/stack/avct/avct_bcb_act.cc b/system/stack/avct/avct_bcb_act.cc +index c278f48a83..5ba20397a0 100644 +--- a/system/stack/avct/avct_bcb_act.cc ++++ b/system/stack/avct/avct_bcb_act.cc +@@ -115,8 +115,9 @@ void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { + + /* call l2cap connect req */ + p_bcb->ch_state = AVCT_CH_CONN; +- p_bcb->ch_lcid = +- L2CA_ConnectReq2(AVCT_BR_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE); ++ p_bcb->ch_lcid = L2CA_ConnectReq2(AVCT_BR_PSM, p_lcb->peer_addr, ++ BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); ++ + if (p_bcb->ch_lcid == 0) { + /* if connect req failed, send ourselves close event */ + tAVCT_LCB_EVT avct_lcb_evt; +diff --git a/system/stack/avct/avct_lcb_act.cc b/system/stack/avct/avct_lcb_act.cc +index 58f40b8e8f..d7a8f1283d 100644 +--- a/system/stack/avct/avct_lcb_act.cc ++++ b/system/stack/avct/avct_lcb_act.cc +@@ -190,7 +190,8 @@ void avct_lcb_chnl_open(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) { + + p_lcb->ch_state = AVCT_CH_CONN; + p_lcb->ch_lcid = +- L2CA_ConnectReq2(AVCT_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE); ++ L2CA_ConnectReq2(AVCT_PSM, p_lcb->peer_addr, ++ BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); + if (p_lcb->ch_lcid == 0) { + /* if connect req failed, send ourselves close event */ + tAVCT_LCB_EVT avct_lcb_evt; +diff --git a/system/stack/avdt/avdt_ad.cc b/system/stack/avdt/avdt_ad.cc +index ccfb12945c..9d2d6779ca 100644 +--- a/system/stack/avdt/avdt_ad.cc ++++ b/system/stack/avdt/avdt_ad.cc +@@ -548,7 +548,8 @@ void avdt_ad_open_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb, + + /* call l2cap connect req */ + lcid = +- L2CA_ConnectReq2(AVDT_PSM, p_ccb->peer_addr, BTM_SEC_OUT_AUTHENTICATE); ++ L2CA_ConnectReq2(AVDT_PSM, p_ccb->peer_addr, ++ BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT); + if (lcid != 0) { + /* if connect req ok, store tcid in lcid table */ + avdtp_cb.ad.lcid_tbl[lcid] = avdt_ad_tc_tbl_to_idx(p_tbl); +diff --git a/system/stack/avdt/avdt_api.cc b/system/stack/avdt/avdt_api.cc +index a5f53885e8..ea4d2acd00 100644 +--- a/system/stack/avdt/avdt_api.cc ++++ b/system/stack/avdt/avdt_api.cc +@@ -95,9 +95,10 @@ void avdt_scb_transport_channel_timer_timeout(void* data) { + * + ******************************************************************************/ + void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback) { ++ uint16_t sec = BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT; + /* register PSM with L2CAP */ + L2CA_Register2(AVDT_PSM, avdt_l2c_appl, true /* enable_snoop */, nullptr, +- kAvdtpMtu, 0, BTA_SEC_AUTHENTICATE); ++ kAvdtpMtu, 0, sec); + + /* initialize AVDTP data structures */ + avdt_scb_init(); +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/packages/modules/Bluetooth/72_0072-Fix-UAF-in-sdp_discovery-cc.bulletin.patch b/aosp_diff/preliminary/packages/modules/Bluetooth/72_0072-Fix-UAF-in-sdp_discovery-cc.bulletin.patch new file mode 100644 index 0000000000..93cf125078 --- /dev/null +++ b/aosp_diff/preliminary/packages/modules/Bluetooth/72_0072-Fix-UAF-in-sdp_discovery-cc.bulletin.patch @@ -0,0 +1,77 @@ +From b2739368e7160de3a5c5fc33a0dfb10220226997 Mon Sep 17 00:00:00 2001 +From: Brian Delwiche +Date: Wed, 9 Oct 2024 20:55:36 +0000 +Subject: [PATCH] Fix UAF in sdp_discovery.cc + +It is possible with modifications to a client to open two connections +against the same SDP discovery database. If this happens, it becomes +possible to reference a freed instance of the discovery database in the +second connection once the first one is closed. + +To guard against this, check during discovery if a database has already +been allocated, and abort iff it has. + +Also, add a null check to process_service_search_attr_rsp to guard +against unchecked calls to the SDP discovery database. + +Bug: 291281168 +Bug: 356201480 +Flag: com.android.bluetooth.flags.btsec_check_valid_discovery_database +Test: atest bluetooth_test_gd_unit, net_test_stack_sdp +Tag: #security +Ignore-AOSP-First: Security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2c3b80e41630d9a252e63a3e30cc2997488fc3e4) +Merged-In: I754bf8292e1e0d8e90e78fa87889284e26aa5818 +Change-Id: I754bf8292e1e0d8e90e78fa87889284e26aa5818 +--- + system/bta/hf_client/bta_hf_client_sdp.cc | 13 +++++++++++++ + system/stack/sdp/sdp_discovery.cc | 9 +++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/system/bta/hf_client/bta_hf_client_sdp.cc b/system/bta/hf_client/bta_hf_client_sdp.cc +index 96b7a6d14b..72e0a441b0 100755 +--- a/system/bta/hf_client/bta_hf_client_sdp.cc ++++ b/system/bta/hf_client/bta_hf_client_sdp.cc +@@ -320,6 +320,19 @@ void bta_hf_client_do_disc(tBTA_HF_CLIENT_CB* client_cb) { + uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE); + } + ++ /* If we already have a non-null discovery database at this point, we can get ++ * into a race condition leading to UAF once this connection is closed. ++ * This should only happen with malicious modifications to a client. */ ++ if (client_cb->p_disc_db != NULL) { ++ APPL_TRACE_ERROR( ++ "Tried to set up a HF client with a preexisting discovery database."); ++ client_cb->p_disc_db = NULL; ++ // We manually set the state here because it's possible to call this from an ++ // OPEN state, in which case the discovery fail event will be ignored. ++ client_cb->state = 0; // BTA_HF_CLIENT_INIT_ST ++ return; ++ } ++ + /* allocate buffer for sdp database */ + client_cb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE); + +diff --git a/system/stack/sdp/sdp_discovery.cc b/system/stack/sdp/sdp_discovery.cc +index 38db6350b2..85d3dd3c24 100644 +--- a/system/stack/sdp/sdp_discovery.cc ++++ b/system/stack/sdp/sdp_discovery.cc +@@ -604,6 +604,15 @@ static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, + uint8_t* p; + uint16_t bytes_left = SDP_DATA_BUF_SIZE; + ++ /* If we don't have a valid discovery database, we can't do anything. */ ++ if (p_ccb->p_db == NULL) { ++ SDP_TRACE_WARNING( ++ "Attempted continuation or first time request with invalid discovery " ++ "database"); ++ sdp_disconnect(p_ccb, tSDP_STATUS::SDP_INVALID_CONT_STATE); ++ return; ++ } ++ + p_msg->offset = L2CAP_MIN_OFFSET; + p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; + +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/packages/providers/DownloadProvider/0002-Ensure-ownership-validation-in-downloadprovider-insert-method.bulletin.patch b/aosp_diff/preliminary/packages/providers/DownloadProvider/0002-Ensure-ownership-validation-in-downloadprovider-insert-method.bulletin.patch new file mode 100644 index 0000000000..dbe0ccf19d --- /dev/null +++ b/aosp_diff/preliminary/packages/providers/DownloadProvider/0002-Ensure-ownership-validation-in-downloadprovider-insert-method.bulletin.patch @@ -0,0 +1,82 @@ +From 0af26e2e36995b96f05f081f7cda8afe3ee37be1 Mon Sep 17 00:00:00 2001 +From: Himanshu Arora +Date: Wed, 18 Dec 2024 12:40:54 +0000 +Subject: [PATCH] Ensure ownership validation in downloadprovider insert method + +Earlier, apps could access any file in Downloads by invoking the insert method in Downloadprovider. Now, it includes a check to ensure no existing record is present in Mediaprovider. If a record exists, the method validates the ownerPackageName before proceeding with the insert operation + +Bug: 304497167 +Test: manual +Flag: EXEMPT, fix only +(cherry picked from commit bf66a79ddcd8d93f502bf908621469893f513780) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4ce5f76e26a4095a32d760bdabfe65d074389394) +Merged-In: I8b2d24974cdf3ae8a9e5680c22cf422bce396940 +Change-Id: I8b2d24974cdf3ae8a9e5680c22cf422bce396940 +--- + .../providers/downloads/DownloadProvider.java | 41 +++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java +index 1afa0901..70650d70 100644 +--- a/src/com/android/providers/downloads/DownloadProvider.java ++++ b/src/com/android/providers/downloads/DownloadProvider.java +@@ -84,6 +84,7 @@ import java.io.FileDescriptor; + import java.io.FileNotFoundException; + import java.io.IOException; + import java.io.PrintWriter; ++import java.util.Arrays; + import java.util.Iterator; + import java.util.Map; + +@@ -1103,8 +1104,48 @@ public final class DownloadProvider extends ContentProvider { + Helpers.checkDestinationFilePathRestrictions(file, getCallingPackage(), getContext(), + mAppOpsManager, getCallingAttributionTag(), isLegacyMode, + /* allowDownloadsDirOnly */ true); ++ // check whether record already exists in MP or getCallingPackage owns this file ++ checkWhetherCallingAppHasAccess(file.getPath(), Binder.getCallingUid()); + } + ++ private void checkWhetherCallingAppHasAccess(String filePath, int uid) { ++ try (ContentProviderClient client = getContext().getContentResolver() ++ .acquireContentProviderClient(MediaStore.AUTHORITY)) { ++ if (client == null) { ++ Log.w(Constants.TAG, "Failed to acquire ContentProviderClient for MediaStore"); ++ return; ++ } ++ ++ Uri filesUri = MediaStore.setIncludePending( ++ Helpers.getContentUriForPath(getContext(), filePath)); ++ ++ try (Cursor cursor = client.query(filesUri, ++ new String[]{MediaStore.Files.FileColumns._ID, ++ MediaStore.Files.FileColumns.OWNER_PACKAGE_NAME}, ++ MediaStore.Files.FileColumns.DATA + "=?", new String[]{filePath}, ++ null)) { ++ if (cursor != null && cursor.moveToFirst()) { ++ String fetchedOwnerPackageName = cursor.getString( ++ cursor.getColumnIndexOrThrow( ++ MediaStore.Files.FileColumns.OWNER_PACKAGE_NAME)); ++ String[] packageNames = getContext().getPackageManager().getPackagesForUid(uid); ++ ++ if (fetchedOwnerPackageName != null && packageNames != null) { ++ boolean isCallerAuthorized = Arrays.asList(packageNames) ++ .contains(fetchedOwnerPackageName); ++ if (!isCallerAuthorized) { ++ throw new SecurityException("Caller does not have access to this path"); ++ } ++ } ++ } ++ } ++ } catch (RemoteException e) { ++ Log.w(Constants.TAG, "Failed to query MediaStore: " + e.getMessage()); ++ } ++ } ++ ++ ++ + /** + * Apps with the ACCESS_DOWNLOAD_MANAGER permission can access this provider freely, subject to + * constraints in the rest of the code. Apps without that may still access this provider through +-- +2.48.1.262.g85cc9f2d1e-goog + diff --git a/aosp_diff/preliminary/packages/services/Telecomm/0014-Resolve-cross-account-user-icon-validation-.bulletin.patch b/aosp_diff/preliminary/packages/services/Telecomm/0014-Resolve-cross-account-user-icon-validation-.bulletin.patch new file mode 100644 index 0000000000..1a6e7c38a2 --- /dev/null +++ b/aosp_diff/preliminary/packages/services/Telecomm/0014-Resolve-cross-account-user-icon-validation-.bulletin.patch @@ -0,0 +1,85 @@ +From 30bd9435b2c3ab4de4a733700384cf1bbb020cc6 Mon Sep 17 00:00:00 2001 +From: Pranav Madapurmath +Date: Thu, 2 Jan 2025 15:04:45 -0800 +Subject: [PATCH] Resolve cross account user icon validation. + +Resolves a vulnerability found with the cross account user icon +validation in StatusHint and TelecomServiceImpl (when registering a +phone account). The reporter found that an uri formatted as `userId%` +isn't parsed properly with the existing reference to Uri.encodedUserInfo. + +Bug: 376461551 +Bug: 376259166 +Flag: EXEMPT bugfix +Test: atest TelecomServiceImplTest +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:089dc975fc9dce402ec8c6c84e76fa100c9adcf5) +Merged-In: I7a5f64ae01eaf6a133ea04c51bd00dbe1653b74f +Change-Id: I7a5f64ae01eaf6a133ea04c51bd00dbe1653b74f +--- + .../server/telecom/TelecomServiceImpl.java | 17 ++++++++--------- + .../telecom/tests/TelecomServiceImplTest.java | 14 ++++++++++++++ + 2 files changed, 22 insertions(+), 9 deletions(-) + +diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java +index 37e9d3390..df174c2e6 100644 +--- a/src/com/android/server/telecom/TelecomServiceImpl.java ++++ b/src/com/android/server/telecom/TelecomServiceImpl.java +@@ -55,6 +55,7 @@ import android.provider.Settings; + import android.telecom.Log; + import android.telecom.PhoneAccount; + import android.telecom.PhoneAccountHandle; ++import android.telecom.StatusHints; + import android.telecom.TelecomAnalytics; + import android.telecom.TelecomManager; + import android.telecom.VideoProfile; +@@ -2764,15 +2765,13 @@ public class TelecomServiceImpl { + // 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."); +- } ++ int callingUserId = UserHandle.getCallingUserId(); ++ int requestingUserId = StatusHints.getUserIdFromAuthority( ++ icon.getUri().getAuthority(), callingUserId); ++ if(callingUserId != requestingUserId) { ++ // 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 572c975fe..f539bd02f 100644 +--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java ++++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java +@@ -632,6 +632,20 @@ public class TelecomServiceImplTest extends TelecomTestCase { + // This should fail; security exception will be thrown. + registerPhoneAccountTestHelper(phoneAccount, false); + ++ icon = Icon.createWithContentUri( ++ new Uri.Builder().scheme("content") ++ .encodedAuthority("10%40media") ++ .path("external/images/media/${mediaId.text}".trim()) ++ .build()); ++ phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build(); ++ // This should fail; security exception will be thrown ++ registerPhoneAccountTestHelper(phoneAccount, false); ++ ++ icon = Icon.createWithContentUri( Uri.parse("content://10%40play.ground")); ++ phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build(); ++ // 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. +-- +2.48.1.262.g85cc9f2d1e-goog +