diff --git a/Patches/LineageOS-14.1/android_external_aac/364027-backport.patch b/Patches/LineageOS-14.1/android_external_aac/364027-backport.patch new file mode 100644 index 00000000..587612e0 --- /dev/null +++ b/Patches/LineageOS-14.1/android_external_aac/364027-backport.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fraunhofer IIS FDK +Date: Tue, 30 May 2023 16:39:32 +0200 +Subject: [PATCH] Increase patchParam array size by one and fix out-of-bounce + write in resetLppTransposer(). + +Bug: 279766766 +Test: see POC +(cherry picked from commit f682b8787eb312b9f8997dac4c2c18bb779cf0df) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:451762ca48e7fb30a0ce77a8962813a3419ec420) +Merged-In: I206973e0bb21140865efffd930e39f920f477359 +Change-Id: I206973e0bb21140865efffd930e39f920f477359 +--- + libSBRdec/src/lpp_tran.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libSBRdec/src/lpp_tran.h b/libSBRdec/src/lpp_tran.h +index 003a547..c363880 100644 +--- a/libSBRdec/src/lpp_tran.h ++++ b/libSBRdec/src/lpp_tran.h +@@ -2,7 +2,7 @@ + /* ----------------------------------------------------------------------------------------------------------- + Software License for The Fraunhofer FDK AAC Codec Library for Android + +-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. ++© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +@@ -175,7 +175,7 @@ typedef struct { + UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/ + UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different inverse filtering levels */ + +- PATCH_PARAM patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ ++ PATCH_PARAM patchParam[MAX_NUM_PATCHES + 1]; /*!< new parameter set for patching */ + WHITENING_FACTORS whFactors; /*!< the pole moving factors for certain whitening levels as indicated + in the bitstream depending on the crossover frequency */ + UCHAR overlap; /*!< Overlap size */ diff --git a/Patches/LineageOS-14.1/android_frameworks_base/248599.patch b/Patches/LineageOS-14.1/android_frameworks_base/248599.patch index ea5d9d3d..a64be83a 100644 --- a/Patches/LineageOS-14.1/android_frameworks_base/248599.patch +++ b/Patches/LineageOS-14.1/android_frameworks_base/248599.patch @@ -14,10 +14,10 @@ Change-Id: Id0e16499a00e1f5cfb5bd4d9fb421f93bb283ee1 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml -index 0f224dae3337..f6026a82ad72 100644 +index ef6ce2503061..ebf2a890152a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml -@@ -1822,12 +1822,12 @@ +@@ -1826,12 +1826,12 @@ android:protectionLevel="signature|privileged" /> + 0 && UserHandle.getAppId(callingUid) < Process.FIRST_APPLICATION_UID) ++ || (proc != null && proc.info.isSystemApp()); ++ ++ userId = mUserController.handleIncomingUser(callingPid, callingUid, + userId, true, ALLOW_FULL_ONLY, "killBackgroundProcesses", null); + long callingId = Binder.clearCallingIdentity(); + try { +@@ -5832,7 +5845,7 @@ public final class ActivityManagerService extends ActivityManagerNative + pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId)); + } catch (RemoteException e) { + } +- if (appId == -1) { ++ if (appId == -1 || (!hasKillAllPermission && appId != callingAppId)) { + Slog.w(TAG, "Invalid packageName: " + packageName); + return; + } +@@ -5912,6 +5925,22 @@ public final class ActivityManagerService extends ActivityManagerNative + throw new SecurityException(msg); + } + ++ final int callingUid = Binder.getCallingUid(); ++ final int callingPid = Binder.getCallingPid(); ++ ++ ProcessRecord proc; ++ synchronized (mPidsSelfLocked) { ++ proc = mPidsSelfLocked.get(callingPid); ++ } ++ if (callingUid >= FIRST_APPLICATION_UID ++ && (proc == null || !proc.info.isSystemApp())) { ++ final String msg = "Permission Denial: killAllBackgroundProcesses() from pid=" ++ + callingPid + ", uid=" + callingUid + " is not allowed"; ++ Slog.w(TAG, msg); ++ // Silently return to avoid existing apps from crashing. ++ return; ++ } ++ + final long callingId = Binder.clearCallingIdentity(); + try { + synchronized (this) { diff --git a/Patches/LineageOS-14.1/android_frameworks_base/364033-backport.patch b/Patches/LineageOS-14.1/android_frameworks_base/364033-backport.patch new file mode 100644 index 00000000..f884fe06 --- /dev/null +++ b/Patches/LineageOS-14.1/android_frameworks_base/364033-backport.patch @@ -0,0 +1,230 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Pavel Grafov +Date: Wed, 5 Apr 2023 15:15:41 +0000 +Subject: [PATCH] Ensure policy has no absurdly long strings + +The following APIs now enforce limits and throw IllegalArgumentException +when limits are violated: +* DPM.setTrustAgentConfiguration() limits agent packgage name, + component name, and strings within configuration bundle. +* DPM.setPermittedAccessibilityServices() limits package names. +* DPM.setPermittedInputMethods() limits package names. +* DPM.setAccountManagementDisabled() limits account name. +* DPM.setLockTaskPackages() limits package names. +* DPM.setAffiliationIds() limits id. +* DPM.transferOwnership() limits strings inside the bundle. + +Package names are limited at 223, because they become directory names +and it is a filesystem restriction, see FrameworkParsingPackageUtils. + +All other strings are limited at 65535, because longer ones break binary +XML serializer. + +The following APIs silently truncate strings that are long beyond reason: +* DPM.setShortSupportMessage() truncates message at 200. +* DPM.setLongSupportMessage() truncates message at 20000. +* DPM.setOrganizationName() truncates org name at 200. + +Bug: 260729089 +Test: atest com.android.server.devicepolicy +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bb7e82ceaa6d16267e7b0e14563161b506d26be8) +Merged-In: Idcf54e408722f164d16bf2f24a00cd1f5b626d23 +Change-Id: Idcf54e408722f164d16bf2f24a00cd1f5b626d23 +--- + .../app/admin/DevicePolicyManager.java | 3 +- + .../DevicePolicyManagerService.java | 87 +++++++++++++++++++ + 2 files changed, 89 insertions(+), 1 deletion(-) + +diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java +index 592026cda79b..a718b3e520dc 100644 +--- a/core/java/android/app/admin/DevicePolicyManager.java ++++ b/core/java/android/app/admin/DevicePolicyManager.java +@@ -6046,7 +6046,8 @@ public class DevicePolicyManager { + + /** + * Called by a device admin to set the long support message. This will be displayed to the user +- * in the device administators settings screen. ++ * in the device administrators settings screen. If the message is longer than 20000 characters ++ * it may be truncated. + *

+ * If the long support message needs to be localized, it is the responsibility of the + * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast +diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +index fe0ee096d303..af982a1a0724 100644 +--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java ++++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +@@ -171,12 +171,14 @@ import java.security.cert.CertificateException; + import java.security.cert.CertificateFactory; + import java.security.cert.X509Certificate; + import java.text.DateFormat; ++import java.util.ArrayDeque; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collections; + import java.util.Date; + import java.util.List; + import java.util.Map.Entry; ++import java.util.Queue; + import java.util.Set; + import java.util.concurrent.atomic.AtomicBoolean; + +@@ -214,6 +216,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + + private static final int REQUEST_EXPIRE_PASSWORD = 5571; + ++ // Binary XML serializer doesn't support longer strings ++ private static final int MAX_POLICY_STRING_LENGTH = 65535; ++ // FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE, Android packages are used in dir names. ++ private static final int MAX_PACKAGE_NAME_LENGTH = 223; ++ ++ private static final int MAX_LONG_SUPPORT_MESSAGE_LENGTH = 20000; ++ private static final int MAX_SHORT_SUPPORT_MESSAGE_LENGTH = 200; ++ private static final int MAX_ORG_NAME_LENGTH = 200; ++ + private static final long MS_PER_DAY = 86400 * 1000; + + private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms +@@ -6890,6 +6901,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + } + Preconditions.checkNotNull(admin, "admin is null"); + Preconditions.checkNotNull(agent, "agent is null"); ++ enforceMaxPackageNameLength(agent.getPackageName()); ++ final String agentAsString = agent.flattenToString(); ++ enforceMaxStringLength(agentAsString, "agent name"); ++ if (args != null) { ++ enforceMaxStringLength(args, "args"); ++ } + final int userHandle = UserHandle.getCallingUserId(); + synchronized (this) { + ActiveAdmin ap = getActiveAdminForCallerLocked(admin, +@@ -7091,6 +7108,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + Preconditions.checkNotNull(who, "ComponentName is null"); + + if (packageList != null) { ++ for (String pkg : (List) packageList) { ++ enforceMaxPackageNameLength(pkg); ++ } ++ + int userId = UserHandle.getCallingUserId(); + List enabledServices = null; + long id = mInjector.binderClearCallingIdentity(); +@@ -7272,6 +7293,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + } + + if (packageList != null) { ++ for (String pkg : (List) packageList) { ++ enforceMaxPackageNameLength(pkg); ++ } ++ + // InputMethodManager fetches input methods for current user. + // So this can only be set when calling user is the current user + // or parent is current user in case of managed profiles. +@@ -7820,6 +7845,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + return; + } + Preconditions.checkNotNull(who, "ComponentName is null"); ++ enforceMaxStringLength(accountType, "account type"); + synchronized (this) { + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); +@@ -8089,6 +8115,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + public void setLockTaskPackages(ComponentName who, String[] packages) + throws SecurityException { + Preconditions.checkNotNull(who, "ComponentName is null"); ++ for (String pkg : packages) { ++ enforceMaxPackageNameLength(pkg); ++ } ++ + synchronized (this) { + ActiveAdmin deviceOwner = getActiveAdminWithPolicyForUidLocked( + who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER, mInjector.binderGetCallingUid()); +@@ -8956,6 +8986,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + if (!mHasFeature) { + return; + } ++ ++ message = truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH); ++ + Preconditions.checkNotNull(who, "ComponentName is null"); + final int userHandle = mInjector.userHandleGetCallingUserId(); + synchronized (this) { +@@ -8987,6 +9020,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + return; + } + Preconditions.checkNotNull(who, "ComponentName is null"); ++ message = truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH); ++ + final int userHandle = mInjector.userHandleGetCallingUserId(); + synchronized (this) { + ActiveAdmin admin = getActiveAdminForUidLocked(who, +@@ -9004,6 +9039,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + return null; + } + Preconditions.checkNotNull(who, "ComponentName is null"); ++ + synchronized (this) { + ActiveAdmin admin = getActiveAdminForUidLocked(who, + mInjector.binderGetCallingUid()); +@@ -9114,6 +9150,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + } + Preconditions.checkNotNull(who, "ComponentName is null"); + final int userHandle = mInjector.userHandleGetCallingUserId(); ++ ++ text = truncateIfLonger(text, MAX_ORG_NAME_LENGTH); ++ + enforceManagedProfile(userHandle, "set organization name"); + synchronized (this) { + ActiveAdmin admin = getActiveAdminForCallerLocked(who, +@@ -9697,4 +9736,52 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + mInjector.getNotificationManager().notify(NETWORK_LOGGING_NOTIFICATION_ID, notification); + saveSettingsLocked(mOwners.getDeviceOwnerUserId()); + } ++ ++ ++ /** ++ * Truncates char sequence to maximum length, nulls are ignored. ++ */ ++ private static CharSequence truncateIfLonger(CharSequence input, int maxLength) { ++ return input == null || input.length() <= maxLength ++ ? input ++ : input.subSequence(0, maxLength); ++ } ++ ++ /** ++ * Throw if string argument is too long to be serialized. ++ */ ++ private static void enforceMaxStringLength(String str, String argName) { ++ Preconditions.checkArgument( ++ str.length() <= MAX_POLICY_STRING_LENGTH, argName + " loo long"); ++ } ++ ++ private static void enforceMaxPackageNameLength(String pkg) { ++ Preconditions.checkArgument( ++ pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long"); ++ } ++ ++ /** ++ * Throw if persistable bundle contains any string that we can't serialize. ++ */ ++ private static void enforceMaxStringLength(PersistableBundle bundle, String argName) { ++ // Persistable bundles can have other persistable bundles as values, traverse with a queue. ++ Queue queue = new ArrayDeque<>(); ++ queue.add(bundle); ++ while (!queue.isEmpty()) { ++ PersistableBundle current = queue.remove(); ++ for (String key : current.keySet()) { ++ enforceMaxStringLength(key, "key in " + argName); ++ Object value = current.get(key); ++ if (value instanceof String) { ++ enforceMaxStringLength((String) value, "string value in " + argName); ++ } else if (value instanceof String[]) { ++ for (String str : (String[]) value) { ++ enforceMaxStringLength(str, "string value in " + argName); ++ } ++ } else if (value instanceof PersistableBundle) { ++ queue.add((PersistableBundle) value); ++ } ++ } ++ } ++ } + } diff --git a/Patches/LineageOS-14.1/android_frameworks_base/364036-backport.patch b/Patches/LineageOS-14.1/android_frameworks_base/364036-backport.patch new file mode 100644 index 00000000..0a714cff --- /dev/null +++ b/Patches/LineageOS-14.1/android_frameworks_base/364036-backport.patch @@ -0,0 +1,141 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Mikhail +Date: Fri, 28 Apr 2023 16:17:16 +0000 +Subject: [PATCH] Verify URI permissions in MediaMetadata + +Add a check for URI permission to make sure that user can access the URI +set in MediaMetadata. If permission is denied, clear the URI string set +in metadata. + +Bug: 271851153 +Test: atest MediaSessionTest +Test: Verified by POC app attached in bug, image of second user is not +the UMO background of the first user. +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f95b7fc61d6b3bf49420ded0357bec031f8cbdcf) +Merged-In: I384f8e230c909d8fc8e5f147e2fd3558fec44626 +Change-Id: I384f8e230c909d8fc8e5f147e2fd3558fec44626 +--- + .../server/media/MediaSessionRecord.java | 63 ++++++++++++++++--- + 1 file changed, 54 insertions(+), 9 deletions(-) + +diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java +index b65e74d219cb..1c68b95517f1 100644 +--- a/services/core/java/com/android/server/media/MediaSessionRecord.java ++++ b/services/core/java/com/android/server/media/MediaSessionRecord.java +@@ -16,7 +16,12 @@ + + package com.android.server.media; + ++import android.app.ActivityManager; ++import android.app.ActivityManagerNative; ++import android.app.IActivityManager; + import android.app.PendingIntent; ++import android.content.ContentProvider; ++import android.content.ContentResolver; + import android.content.Context; + import android.content.Intent; + import android.content.pm.ParceledListSlice; +@@ -48,6 +53,7 @@ import android.os.Message; + import android.os.RemoteException; + import android.os.ResultReceiver; + import android.os.SystemClock; ++import android.text.TextUtils; + import android.util.Log; + import android.util.Slog; + import android.view.KeyEvent; +@@ -63,6 +69,10 @@ import java.util.ArrayList; + */ + public class MediaSessionRecord implements IBinder.DeathRecipient { + private static final String TAG = "MediaSessionRecord"; ++ private static final String[] ART_URIS = new String[] { ++ MediaMetadata.METADATA_KEY_ALBUM_ART_URI, ++ MediaMetadata.METADATA_KEY_ART_URI, ++ MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI}; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + /** +@@ -90,6 +100,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { + private final SessionStub mSession; + private final SessionCb mSessionCb; + private final MediaSessionService mService; ++ final IActivityManager mAm; + + private final Object mLock = new Object(); + private final ArrayList mControllerCallbacks = +@@ -145,6 +156,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { + mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE); + mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); + mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(); ++ mAm = ActivityManagerNative.getDefault(); + } + + /** +@@ -211,6 +223,15 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { + return (mFlags & flag) != 0; + } + ++ /** ++ * Get the UID this session was created for. ++ * ++ * @return The UID for this session. ++ */ ++ public int getUid() { ++ return mOwnerUid; ++ } ++ + /** + * Get the user id this session was created for. + * +@@ -856,19 +877,43 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { + @Override + public void setMetadata(MediaMetadata metadata) { + synchronized (mLock) { +- MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata) +- .build(); +- // This is to guarantee that the underlying bundle is unparceled +- // before we set it to prevent concurrent reads from throwing an +- // exception +- if (temp != null) { +- temp.size(); +- } +- mMetadata = temp; ++ mMetadata = sanitizeMediaMetadata(metadata); + } + mHandler.post(MessageHandler.MSG_UPDATE_METADATA); + } + ++ private MediaMetadata sanitizeMediaMetadata(MediaMetadata metadata) { ++ if (metadata == null) { ++ return null; ++ } ++ MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder(metadata); ++ for (String key: ART_URIS) { ++ String uriString = metadata.getString(key); ++ if (TextUtils.isEmpty(uriString)) { ++ continue; ++ } ++ Uri uri = Uri.parse(uriString); ++ if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { ++ continue; ++ } ++ try { ++ mAm.checkGrantUriPermission(getUid(), ++ getPackageName(), ++ ContentProvider.getUriWithoutUserId(uri), ++ Intent.FLAG_GRANT_READ_URI_PERMISSION, ++ ContentProvider.getUserIdFromUri(uri, getUserId())); ++ } catch (RemoteException | SecurityException e) { ++ metadataBuilder.putString(key, null); ++ } ++ } ++ MediaMetadata sanitizedMetadata = metadataBuilder.build(); ++ // sanitizedMetadata.size() guarantees that the underlying bundle is unparceled ++ // before we set it to prevent concurrent reads from throwing an ++ // exception ++ sanitizedMetadata.size(); ++ return sanitizedMetadata; ++ } ++ + @Override + public void setPlaybackState(PlaybackState state) { + int oldState = mPlaybackState == null ? 0 : mPlaybackState.getState(); diff --git a/Patches/LineageOS-14.1/android_frameworks_base/364037.patch b/Patches/LineageOS-14.1/android_frameworks_base/364037.patch new file mode 100644 index 00000000..457e2e8a --- /dev/null +++ b/Patches/LineageOS-14.1/android_frameworks_base/364037.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Chandru S +Date: Tue, 16 May 2023 10:41:07 -0700 +Subject: [PATCH] Use Settings.System.getIntForUser instead of getInt to make + sure user specific settings are used + +Bug: 265431505 +Test: atest KeyguardViewMediatorTest +(cherry picked from commit 625e009fc195ba5d658ca2d78ebb23d2770cc6c4) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ce6510deba06bcb72a0e468294b483fc4ac4be17) +Merged-In: I66a660c091c90a957a0fd1e144c013840db3f47e +Change-Id: I66a660c091c90a957a0fd1e144c013840db3f47e +--- + .../systemui/keyguard/KeyguardViewMediator.java | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +index 45bc0ea0e2b8..2c6e1003df9e 100755 +--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java ++++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +@@ -854,9 +854,9 @@ public class KeyguardViewMediator extends SystemUI { + final ContentResolver cr = mContext.getContentResolver(); + + // From SecuritySettings +- final long lockAfterTimeout = Settings.Secure.getInt(cr, ++ final long lockAfterTimeout = Settings.Secure.getIntForUser(cr, + Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, +- KEYGUARD_LOCK_AFTER_DELAY_DEFAULT); ++ KEYGUARD_LOCK_AFTER_DELAY_DEFAULT, userId); + + // From DevicePolicyAdmin + final long policyTimeout = mLockPatternUtils.getDevicePolicyManager() +@@ -868,8 +868,8 @@ public class KeyguardViewMediator extends SystemUI { + timeout = lockAfterTimeout; + } else { + // From DisplaySettings +- long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT, +- KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT); ++ long displayTimeout = Settings.System.getIntForUser(cr, SCREEN_OFF_TIMEOUT, ++ KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT, userId); + + // policy in effect. Make sure we don't go beyond policy limit. + displayTimeout = Math.max(displayTimeout, 0); // ignore negative values +@@ -1654,7 +1654,10 @@ public class KeyguardViewMediator extends SystemUI { + private void playSound(int soundId) { + if (soundId == 0) return; + final ContentResolver cr = mContext.getContentResolver(); +- if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) { ++ int lockscreenSoundsEnabled = Settings.System.getIntForUser(cr, ++ Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1, ++ KeyguardUpdateMonitor.getCurrentUser()); ++ if (lockscreenSoundsEnabled == 1) { + + mLockSounds.stop(mLockSoundStreamId); + // Init mAudioManager diff --git a/Patches/LineageOS-14.1/android_frameworks_base/364038-backport.patch b/Patches/LineageOS-14.1/android_frameworks_base/364038-backport.patch new file mode 100644 index 00000000..3119d33f --- /dev/null +++ b/Patches/LineageOS-14.1/android_frameworks_base/364038-backport.patch @@ -0,0 +1,126 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Pranav Madapurmath +Date: Thu, 25 May 2023 21:58:19 +0000 +Subject: [PATCH] Resolve StatusHints image exploit across user. + +Because of the INTERACT_ACROSS_USERS permission, an app that implements +a ConnectionService can upload an image icon belonging to another user +by setting it in the StatusHints. Validating the construction of the +StatusHints on the calling user would prevent a malicious app from +registering a connection service with the embedded image icon from a +different user. + +From additional feedback, this CL also addresses potential +vulnerabilities in an app being able to directly invoke the binder for a +means to manipulate the contents of the bundle that are passed with it. +The targeted points of entry are in ConnectionServiceWrapper for the +following APIs: handleCreateConnectionComplete, setStatusHints, +addConferenceCall, and addExistingConnection. + +Fixes: 280797684 +Test: Manual (verified that original exploit is no longer an issue). +Test: Unit test for validating image in StatusHints constructor. +Test: Unit tests to address vulnerabilities via the binder. +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:48223d6034907349c6a3fab3018c1b37d86367af) +Merged-In: I6e70e238b3a5ace1cab41ec5796a6bb4d79769f2 +Change-Id: I6e70e238b3a5ace1cab41ec5796a6bb4d79769f2 +--- + .../java/android/telecom/StatusHints.java | 53 ++++++++++++++++++- + 1 file changed, 51 insertions(+), 2 deletions(-) + +diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java +index 453f408bedba..c75bd2781f9f 100644 +--- a/telecomm/java/android/telecom/StatusHints.java ++++ b/telecomm/java/android/telecom/StatusHints.java +@@ -16,14 +16,19 @@ + + package android.telecom; + ++import android.annotation.Nullable; + import android.annotation.SystemApi; + import android.content.ComponentName; + import android.content.Context; + import android.graphics.drawable.Drawable; + import android.graphics.drawable.Icon; ++import android.os.Binder; + import android.os.Bundle; + import android.os.Parcel; + import android.os.Parcelable; ++import android.os.UserHandle; ++ ++import com.android.internal.annotations.VisibleForTesting; + + import java.util.Objects; + +@@ -33,7 +38,7 @@ import java.util.Objects; + public final class StatusHints implements Parcelable { + + private final CharSequence mLabel; +- private final Icon mIcon; ++ private Icon mIcon; + private final Bundle mExtras; + + /** +@@ -48,10 +53,30 @@ public final class StatusHints implements Parcelable { + + public StatusHints(CharSequence label, Icon icon, Bundle extras) { + mLabel = label; +- mIcon = icon; ++ mIcon = validateAccountIconUserBoundary(icon, Binder.getCallingUserHandle()); + mExtras = extras; + } + ++ /** ++ * @param icon ++ * @hide ++ */ ++ @VisibleForTesting ++ public StatusHints(@Nullable Icon icon) { ++ mLabel = null; ++ mExtras = null; ++ mIcon = icon; ++ } ++ ++ /** ++ * ++ * @param icon ++ * @hide ++ */ ++ public void setIcon(@Nullable Icon icon) { ++ mIcon = icon; ++ } ++ + /** + * @return A package used to load the icon. + * +@@ -112,6 +137,30 @@ public final class StatusHints implements Parcelable { + return 0; + } + ++ /** ++ * Validates the StatusHints image icon to see if it's not in the calling user space. ++ * Invalidates the icon if so, otherwise returns back the original icon. ++ * ++ * @param icon ++ * @return icon (validated) ++ * @hide ++ */ ++ public static Icon validateAccountIconUserBoundary(Icon icon, UserHandle callingUserHandle) { ++ // Refer to Icon#getUriString for context. The URI string is invalid for icons of ++ // incompatible types. ++ if (icon != null && (icon.getType() == Icon.TYPE_URI ++ /*|| icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP*/)) { ++ String encodedUser = icon.getUri().getEncodedUserInfo(); ++ // If there is no encoded user, the URI is calling into the calling user space ++ if (encodedUser != null) { ++ int userId = Integer.parseInt(encodedUser); ++ // Do not try to save the icon if the user id isn't in the calling user space. ++ if (userId != callingUserHandle.getIdentifier()) return null; ++ } ++ } ++ return icon; ++ } ++ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeCharSequence(mLabel); diff --git a/Patches/LineageOS-14.1/android_packages_providers_TelephonyProvider/364040-backport.patch b/Patches/LineageOS-14.1/android_packages_providers_TelephonyProvider/364040-backport.patch new file mode 100644 index 00000000..818bc1cb --- /dev/null +++ b/Patches/LineageOS-14.1/android_packages_providers_TelephonyProvider/364040-backport.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aishwarya Mallampati +Date: Wed, 10 May 2023 21:54:43 +0000 +Subject: [PATCH] Update file permissions using canonical path + +Bug: 264880895 +Bug: 264880689 +Test: atest android.telephonyprovider.cts.MmsPartTest + atest CtsTelephonyTestCases + Sanity check - sending and receiving sms and mms manually +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6743638a096c32627f398efd2ea78f08b8a2db8c) +Merged-In: I8dd888ea31ec07c9f0de38eb8e8170d3ed255686 +Change-Id: I8dd888ea31ec07c9f0de38eb8e8170d3ed255686 +--- + src/com/android/providers/telephony/MmsProvider.java | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java +index 88f8f376..ba057828 100755 +--- a/src/com/android/providers/telephony/MmsProvider.java ++++ b/src/com/android/providers/telephony/MmsProvider.java +@@ -1005,15 +1005,16 @@ public class MmsProvider extends ContentProvider { + String path = getContext().getDir(PARTS_DIR_NAME, 0).getPath() + '/' + + uri.getPathSegments().get(1); + try { ++ File canonicalFile = new File(path).getCanonicalFile(); + String partsDirPath = getContext().getDir(PARTS_DIR_NAME, 0).getCanonicalPath(); +- if (!new File(path).getCanonicalPath().startsWith(partsDirPath)) { ++ if (!canonicalFile.getPath().startsWith(partsDirPath + '/')) { + EventLog.writeEvent(0x534e4554, "240685104", + Binder.getCallingUid(), (TAG + " update: path " + path + + " does not start with " + partsDirPath)); + return 0; + } + // Reset the file permission back to read for everyone but me. +- Os.chmod(path, 0644); ++ Os.chmod(canonicalFile.getPath(), 0644); + if (LOCAL_LOGV) { + Log.d(TAG, "MmsProvider.update chmod is successful for path: " + path); + } diff --git a/Patches/LineageOS-14.1/android_packages_services_Telecomm/364041-backport.patch b/Patches/LineageOS-14.1/android_packages_services_Telecomm/364041-backport.patch new file mode 100644 index 00000000..b4264a7a --- /dev/null +++ b/Patches/LineageOS-14.1/android_packages_services_Telecomm/364041-backport.patch @@ -0,0 +1,638 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Pranav Madapurmath +Date: Thu, 25 May 2023 20:49:21 +0000 +Subject: [PATCH] Resolve StatusHints image exploit across user. + +Because of the INTERACT_ACROSS_USERS permission, an app that implements +a ConnectionService can upload an image icon belonging to another user +by setting it in the StatusHints. Validating the construction of the +StatusHints on the calling user would prevent a malicious app from +registering a connection service with the embedded image icon from a +different user. + +From additional feedback, this CL also addresses potential +vulnerabilities in an app being able to directly invoke the binder for a +means to manipulate the contents of the bundle that are passed with it. +The targeted points of entry are in ConnectionServiceWrapper for the +following APIs: handleCreateConnectionComplete, setStatusHints, +addConferenceCall, and addExistingConnection. + +Fixes: 280797684 +Test: Manual (verified that original exploit is no longer an issue). +Test: Unit test for validating image in StatusHints constructor. +Test: Unit tests to address vulnerabilities via the binder. +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:49d19dd265bee669b230efa29bf98c83650efea6) +Merged-In: Ie1f6a8866d31d5f1099dd0630cf8e9ee782d389c +Change-Id: Ie1f6a8866d31d5f1099dd0630cf8e9ee782d389c +--- + .../telecom/ConnectionServiceWrapper.java | 32 ++++ + .../server/telecom/tests/BasicCallTests.java | 161 +++++++++++++++++- + .../server/telecom/tests/CallExtrasTest.java | 6 +- + .../tests/ConnectionServiceFixture.java | 21 ++- + .../telecom/tests/TelecomSystemTest.java | 63 ++++--- + .../server/telecom/tests/VideoCallTests.java | 6 +- + 6 files changed, 257 insertions(+), 32 deletions(-) + +diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java +index f0401340b..400abe46b 100644 +--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java ++++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java +@@ -19,6 +19,7 @@ package com.android.server.telecom; + import android.app.AppOpsManager; + import android.content.ComponentName; + import android.content.Context; ++import android.graphics.drawable.Icon; + import android.net.Uri; + import android.os.Binder; + import android.os.Bundle; +@@ -69,10 +70,17 @@ public class ConnectionServiceWrapper extends ServiceBinder { + public void handleCreateConnectionComplete(String callId, ConnectionRequest request, + ParcelableConnection connection) { + Log.startSession(Log.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE); ++ UserHandle callingUserHandle = Binder.getCallingUserHandle(); + long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + logIncoming("handleCreateConnectionComplete %s", callId); ++ // Check status hints image for cross user access ++ if (connection.getStatusHints() != null) { ++ Icon icon = connection.getStatusHints().getIcon(); ++ connection.getStatusHints().setIcon(StatusHints. ++ validateAccountIconUserBoundary(icon, callingUserHandle)); ++ } + ConnectionServiceWrapper.this + .handleCreateConnectionComplete(callId, request, connection); + } +@@ -357,6 +365,15 @@ public class ConnectionServiceWrapper extends ServiceBinder { + @Override + public void addConferenceCall(String callId, ParcelableConference parcelableConference) { + Log.startSession(Log.Sessions.CSW_ADD_CONFERENCE_CALL); ++ ++ UserHandle callingUserHandle = Binder.getCallingUserHandle(); ++ // Check status hints image for cross user access ++ if (parcelableConference.getStatusHints() != null) { ++ Icon icon = parcelableConference.getStatusHints().getIcon(); ++ parcelableConference.getStatusHints().setIcon(StatusHints. ++ validateAccountIconUserBoundary(icon, callingUserHandle)); ++ } ++ + long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { +@@ -537,10 +554,17 @@ public class ConnectionServiceWrapper extends ServiceBinder { + @Override + public void setStatusHints(String callId, StatusHints statusHints) { + Log.startSession("CSW.sSH"); ++ UserHandle callingUserHandle = Binder.getCallingUserHandle(); + long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + logIncoming("setStatusHints %s %s", callId, statusHints); ++ // Check status hints image for cross user access ++ if (statusHints != null) { ++ Icon icon = statusHints.getIcon(); ++ statusHints.setIcon(StatusHints.validateAccountIconUserBoundary( ++ icon, callingUserHandle)); ++ } + Call call = mCallIdMapper.getCall(callId); + if (call != null) { + call.setStatusHints(statusHints); +@@ -706,6 +730,14 @@ public class ConnectionServiceWrapper extends ServiceBinder { + } else { + connectIdToCheck = callId; + } ++ ++ // Check status hints image for cross user access ++ if (connection.getStatusHints() != null) { ++ Icon icon = connection.getStatusHints().getIcon(); ++ connection.getStatusHints().setIcon(StatusHints. ++ validateAccountIconUserBoundary(icon, userHandle)); ++ } ++ + // Check to see if this Connection has already been added. + Call alreadyAddedConnection = mCallsManager + .getAlreadyAddedConnection(connectIdToCheck); +diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java +index 6688ca0e9..10481a35a 100644 +--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java ++++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java +@@ -16,6 +16,8 @@ + + package com.android.server.telecom.tests; + ++import static com.android.server.telecom.tests.ConnectionServiceFixture.STATUS_HINTS_EXTRA; ++ + import static org.mockito.Matchers.any; + import static org.mockito.Matchers.anyInt; + import static org.mockito.Matchers.anyString; +@@ -29,6 +31,8 @@ import static org.mockito.Mockito.when; + + import android.content.Context; + import android.content.IContentProvider; ++import android.content.Intent; ++import android.graphics.drawable.Icon; + import android.media.AudioManager; + import android.net.Uri; + import android.os.Bundle; +@@ -44,11 +48,14 @@ import android.telecom.DisconnectCause; + import android.telecom.ParcelableCall; + import android.telecom.PhoneAccount; + import android.telecom.PhoneAccountHandle; ++import android.telecom.StatusHints; + import android.telecom.TelecomManager; + import android.telecom.VideoProfile; + import android.test.suitebuilder.annotation.LargeTest; + import android.test.suitebuilder.annotation.MediumTest; + ++import androidx.test.filters.SmallTest; ++ + import com.android.internal.telecom.IInCallAdapter; + import com.android.internal.telephony.CallerInfo; + import com.android.server.telecom.Log; +@@ -137,7 +144,7 @@ public class BasicCallTests extends TelecomSystemTest { + @LargeTest + public void testTelecomManagerAcceptRingingVideoCall() throws Exception { + IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), +- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); ++ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null); + + assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); + assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); +@@ -165,7 +172,7 @@ public class BasicCallTests extends TelecomSystemTest { + @LargeTest + public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception { + IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), +- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); ++ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null); + + assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); + assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); +@@ -192,7 +199,7 @@ public class BasicCallTests extends TelecomSystemTest { + @LargeTest + public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception { + IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), +- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); ++ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null); + + assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); + assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); +@@ -543,12 +550,12 @@ public class BasicCallTests extends TelecomSystemTest { + + @MediumTest + public void testBasicConferenceCall() throws Exception { +- makeConferenceCall(); ++ makeConferenceCall(null, null); + } + + @MediumTest + public void testAddCallToConference1() throws Exception { +- ParcelableCall conferenceCall = makeConferenceCall(); ++ ParcelableCall conferenceCall = makeConferenceCall(null, null); + IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", + mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); + // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference +@@ -565,7 +572,7 @@ public class BasicCallTests extends TelecomSystemTest { + + @MediumTest + public void testAddCallToConference2() throws Exception { +- ParcelableCall conferenceCall = makeConferenceCall(); ++ ParcelableCall conferenceCall = makeConferenceCall(null, null); + IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", + mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); + mInCallServiceFixtureX.getInCallAdapter() +@@ -843,4 +850,146 @@ public class BasicCallTests extends TelecomSystemTest { + assertEquals(mInCallServiceFixtureX.getCall(ids.mCallId).getAccountHandle(), + mPhoneAccountE1.getAccountHandle()); + } ++ ++ ++ /** ++ * Verifies that StatusHints image is validated in ConnectionServiceWrapper#addConferenceCall ++ * when the image doesn't belong to the calling user. Simulates a scenario where an app ++ * could manipulate the contents of the bundle and send it via the binder to upload an image ++ * from another user. ++ * ++ * @throws Exception ++ */ ++ @SmallTest ++ @Test ++ public void testValidateStatusHintsImage_addConferenceCall() throws Exception { ++ Intent callIntent1 = new Intent(); ++ // Stub intent for call2 ++ Intent callIntent2 = new Intent(); ++ Bundle callExtras1 = new Bundle(); ++ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); ++ // Load StatusHints extra into TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS to be processed ++ // as the call extras. This will be leveraged in ConnectionServiceFixture to set the ++ // StatusHints for the given connection. ++ StatusHints statusHints = new StatusHints(icon); ++ assertNotNull(statusHints.getIcon()); ++ callExtras1.putParcelable(STATUS_HINTS_EXTRA, statusHints); ++ callIntent1.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras1); ++ ++ // Start conference call to invoke ConnectionServiceWrapper#addConferenceCall. ++ // Note that the calling user would be User 0. ++ ParcelableCall conferenceCall = makeConferenceCall(callIntent1, callIntent2); ++ ++ // Ensure that StatusHints was set. ++ assertNotNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId) ++ .getStatusHints()); ++ // Ensure that the StatusHints image icon was disregarded. ++ assertNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId) ++ .getStatusHints().getIcon()); ++ } ++ ++ /** ++ * Verifies that StatusHints image is validated in ++ * ConnectionServiceWrapper#handleCreateConnectionComplete when the image doesn't belong to the ++ * calling user. Simulates a scenario where an app could manipulate the contents of the ++ * bundle and send it via the binder to upload an image from another user. ++ * ++ * @throws Exception ++ */ ++ @SmallTest ++ @Test ++ public void testValidateStatusHintsImage_handleCreateConnectionComplete() throws Exception { ++ Bundle extras = new Bundle(); ++ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); ++ // Load the bundle with the test extra in order to simulate an app directly invoking the ++ // binder on ConnectionServiceWrapper#handleCreateConnectionComplete. ++ StatusHints statusHints = new StatusHints(icon); ++ assertNotNull(statusHints.getIcon()); ++ extras.putParcelable(STATUS_HINTS_EXTRA, statusHints); ++ ++ // Start incoming call with StatusHints extras ++ // Note that the calling user in ConnectionServiceWrapper#handleCreateConnectionComplete ++ // would be User 0. ++ IdPair ids = startIncomingPhoneCallWithExtras("650-555-1212", ++ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, extras); ++ ++ // Ensure that StatusHints was set. ++ assertNotNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints()); ++ // Ensure that the StatusHints image icon was disregarded. ++ assertNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints().getIcon()); ++ } ++ ++ /** ++ * Verifies that StatusHints image is validated in ConnectionServiceWrapper#setStatusHints ++ * when the image doesn't belong to the calling user. Simulates a scenario where an app ++ * could manipulate the contents of the bundle and send it via the binder to upload an image ++ * from another user. ++ * ++ * @throws Exception ++ */ ++ @SmallTest ++ @Test ++ public void testValidateStatusHintsImage_setStatusHints() throws Exception { ++ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214", ++ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); ++ ++ // Modify existing connection with StatusHints image exploit ++ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); ++ StatusHints statusHints = new StatusHints(icon); ++ assertNotNull(statusHints.getIcon()); ++ ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA ++ .mConnectionById.get(outgoing.mConnectionId); ++ connectionInfo.statusHints = statusHints; ++ ++ // Invoke ConnectionServiceWrapper#setStatusHints. ++ // Note that the calling user would be User 0. ++ mConnectionServiceFixtureA.sendSetStatusHints(outgoing.mConnectionId); ++ waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), ++ TEST_TIMEOUT); ++ ++ // Ensure that StatusHints was set. ++ assertNotNull(mInCallServiceFixtureX.getCall(outgoing.mCallId).getStatusHints()); ++ // Ensure that the StatusHints image icon was disregarded. ++ assertNull(mInCallServiceFixtureX.getCall(outgoing.mCallId) ++ .getStatusHints().getIcon()); ++ } ++ ++ /** ++ * Verifies that StatusHints image is validated in ++ * ConnectionServiceWrapper#addExistingConnection when the image doesn't belong to the calling ++ * user. Simulates a scenario where an app could manipulate the contents of the bundle and ++ * send it via the binder to upload an image from another user. ++ * ++ * @throws Exception ++ */ ++ @SmallTest ++ @Test ++ public void testValidateStatusHintsImage_addExistingConnection() throws Exception { ++ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214", ++ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); ++ Connection existingConnection = mConnectionServiceFixtureA.mLatestConnection; ++ ++ // Modify existing connection with StatusHints image exploit ++ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); ++ StatusHints modifiedStatusHints = new StatusHints(icon); ++ assertNotNull(modifiedStatusHints.getIcon()); ++ ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA ++ .mConnectionById.get(outgoing.mConnectionId); ++ connectionInfo.statusHints = modifiedStatusHints; ++ ++ // Invoke ConnectionServiceWrapper#addExistingConnection. ++ // Note that the calling user would be User 0. ++ mConnectionServiceFixtureA.sendAddExistingConnection(outgoing.mConnectionId); ++ waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), ++ TEST_TIMEOUT); ++ ++ // Ensure that StatusHints was set. Due to test setup, the ParcelableConnection object that ++ // is passed into sendAddExistingConnection is instantiated on invocation. The call's ++ // StatusHints are not updated at the time of completion, so instead, we can verify that ++ // the ParcelableConnection object was modified. ++ assertNotNull(mConnectionServiceFixtureA.mLatestParcelableConnection.getStatusHints()); ++ // Ensure that the StatusHints image icon was disregarded. ++ assertNull(mConnectionServiceFixtureA.mLatestParcelableConnection ++ .getStatusHints().getIcon()); ++ } + } +diff --git a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java +index e9cd73376..c82df24a6 100644 +--- a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java ++++ b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java +@@ -323,7 +323,7 @@ public class CallExtrasTest extends TelecomSystemTest { + */ + @LargeTest + public void testConferenceSetExtras() throws Exception { +- ParcelableCall call = makeConferenceCall(); ++ ParcelableCall call = makeConferenceCall(null, null); + String conferenceId = call.getId(); + + Conference conference = mConnectionServiceFixtureA.mLatestConference; +@@ -365,7 +365,7 @@ public class CallExtrasTest extends TelecomSystemTest { + */ + @LargeTest + public void testConferenceExtraOperations() throws Exception { +- ParcelableCall call = makeConferenceCall(); ++ ParcelableCall call = makeConferenceCall(null, null); + String conferenceId = call.getId(); + Conference conference = mConnectionServiceFixtureA.mLatestConference; + assertNotNull(conference); +@@ -400,7 +400,7 @@ public class CallExtrasTest extends TelecomSystemTest { + */ + @LargeTest + public void testConferenceICS() throws Exception { +- ParcelableCall call = makeConferenceCall(); +++ ParcelableCall call = makeConferenceCall(null, null); + String conferenceId = call.getId(); + Conference conference = mConnectionServiceFixtureA.mLatestConference; + +diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java +index 698da2667..c4ca7f6c0 100644 +--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java ++++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java +@@ -65,6 +65,7 @@ public class ConnectionServiceFixture implements TestFixture + static int INVALID_VIDEO_STATE = -1; + public CountDownLatch mExtrasLock = new CountDownLatch(1); + static int NOT_SPECIFIED = 0; ++ public static final String STATUS_HINTS_EXTRA = "updateStatusHints"; + + /** + * Implementation of ConnectionService that performs no-ops for tasks normally meant for +@@ -95,6 +96,11 @@ public class ConnectionServiceFixture implements TestFixture + if (mProperties != NOT_SPECIFIED) { + fakeConnection.setConnectionProperties(mProperties); + } ++ // Testing for StatusHints image icon cross user access ++ if (request.getExtras() != null) { ++ fakeConnection.setStatusHints( ++ request.getExtras().getParcelable(STATUS_HINTS_EXTRA)); ++ } + + return fakeConnection; + } +@@ -111,6 +117,11 @@ public class ConnectionServiceFixture implements TestFixture + if (mProperties != NOT_SPECIFIED) { + fakeConnection.setConnectionProperties(mProperties); + } ++ // Testing for StatusHints image icon cross user access ++ if (request.getExtras() != null) { ++ fakeConnection.setStatusHints( ++ request.getExtras().getParcelable(STATUS_HINTS_EXTRA)); ++ } + return fakeConnection; + } + +@@ -123,6 +134,12 @@ public class ConnectionServiceFixture implements TestFixture + Conference fakeConference = new FakeConference(); + fakeConference.addConnection(cxn1); + fakeConference.addConnection(cxn2); ++ if (cxn1.getStatusHints() != null || cxn2.getStatusHints() != null) { ++ // For testing purposes, pick one of the status hints that isn't null. ++ StatusHints statusHints = cxn1.getStatusHints() != null ++ ? cxn1.getStatusHints() : cxn2.getStatusHints(); ++ fakeConference.setStatusHints(statusHints); ++ } + mLatestConference = fakeConference; + addConference(fakeConference); + } else { +@@ -367,6 +384,7 @@ public class ConnectionServiceFixture implements TestFixture + + public String mLatestConnectionId; + public Connection mLatestConnection; ++ public ParcelableConnection mLatestParcelableConnection; + public Conference mLatestConference; + public final Set mConnectionServiceAdapters = new HashSet<>(); + public final Map mConnectionById = new HashMap<>(); +@@ -593,7 +611,7 @@ public class ConnectionServiceFixture implements TestFixture + } + + private ParcelableConnection parcelable(ConnectionInfo c) { +- return new ParcelableConnection( ++ mLatestParcelableConnection = new ParcelableConnection( + c.request.getAccountHandle(), + c.state, + c.capabilities, +@@ -612,5 +630,6 @@ public class ConnectionServiceFixture implements TestFixture + c.disconnectCause, + c.conferenceableConnectionIds, + c.extras); ++ return mLatestParcelableConnection; + } + } +diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java +index cf17b5c19..4dc6b962d 100644 +--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java ++++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java +@@ -336,12 +336,13 @@ public class TelecomSystemTest extends TelecomTestCase { + super.tearDown(); + } + +- protected ParcelableCall makeConferenceCall() throws Exception { +- IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212", +- mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); ++ protected ParcelableCall makeConferenceCall( ++ Intent callIntentExtras1, Intent callIntentExtras2) throws Exception { ++ IdPair callId1 = startAndMakeActiveOutgoingCallWithExtras("650-555-1212", ++ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras1); + +- IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213", +- mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); ++ IdPair callId2 = startAndMakeActiveOutgoingCallWithExtras("650-555-1213", ++ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras2); + + IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter(); + inCallAdapter.conference(callId1.mCallId, callId2.mCallId); +@@ -530,17 +531,17 @@ public class TelecomSystemTest extends TelecomTestCase { + throws Exception { + + return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture, +- initiatingUser, VideoProfile.STATE_AUDIO_ONLY); ++ initiatingUser, VideoProfile.STATE_AUDIO_ONLY, null); + } + + protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle, + ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, +- int videoState) throws Exception { ++ int videoState, Intent callIntentExtras) throws Exception { + int startingNumConnections = connectionServiceFixture.mConnectionById.size(); + int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); + + startOutgoingPhoneCallPendingCreateConnection(number, phoneAccountHandle, +- connectionServiceFixture, initiatingUser, videoState); ++ connectionServiceFixture, initiatingUser, videoState, callIntentExtras); + + return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls, + phoneAccountHandle, connectionServiceFixture); +@@ -576,7 +577,7 @@ public class TelecomSystemTest extends TelecomTestCase { + mIsEmergencyCall = true; + // Call will not use the ordered broadcaster, since it is an Emergency Call + startOutgoingPhoneCallWaitForBroadcaster(number, phoneAccountHandle, +- connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/); ++ connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/, null); + + return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls, + phoneAccountHandle, connectionServiceFixture); +@@ -585,7 +586,7 @@ public class TelecomSystemTest extends TelecomTestCase { + protected void startOutgoingPhoneCallWaitForBroadcaster(String number, + PhoneAccountHandle phoneAccountHandle, + ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, +- int videoState, boolean isEmergency) throws Exception { ++ int videoState, boolean isEmergency, Intent actionCallIntent) throws Exception { + reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(), + mInCallServiceFixtureY.getTestDouble()); + +@@ -598,7 +599,9 @@ public class TelecomSystemTest extends TelecomTestCase { + + boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null; + +- Intent actionCallIntent = new Intent(); ++ if (actionCallIntent == null) { ++ actionCallIntent = new Intent(); ++ } + actionCallIntent.setData(Uri.parse("tel:" + number)); + actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number); + if(isEmergency) { +@@ -638,9 +641,9 @@ public class TelecomSystemTest extends TelecomTestCase { + protected String startOutgoingPhoneCallPendingCreateConnection(String number, + PhoneAccountHandle phoneAccountHandle, + ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, +- int videoState) throws Exception { ++ int videoState, Intent callIntentExtras) throws Exception { + startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle, +- connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/); ++ connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/, callIntentExtras); + + ArgumentCaptor newOutgoingCallIntent = + ArgumentCaptor.forClass(Intent.class); +@@ -724,14 +727,24 @@ public class TelecomSystemTest extends TelecomTestCase { + PhoneAccountHandle phoneAccountHandle, + final ConnectionServiceFixture connectionServiceFixture) throws Exception { + return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY, +- connectionServiceFixture); ++ connectionServiceFixture, null); ++ } ++ ++ protected IdPair startIncomingPhoneCallWithExtras( ++ String number, ++ PhoneAccountHandle phoneAccountHandle, ++ final ConnectionServiceFixture connectionServiceFixture, ++ Bundle extras) throws Exception { ++ return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY, ++ connectionServiceFixture, extras); + } + + protected IdPair startIncomingPhoneCall( + String number, + PhoneAccountHandle phoneAccountHandle, + int videoState, +- final ConnectionServiceFixture connectionServiceFixture) throws Exception { ++ final ConnectionServiceFixture connectionServiceFixture, ++ Bundle extras) throws Exception { + reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(), + mInCallServiceFixtureY.getTestDouble()); + +@@ -744,7 +757,9 @@ public class TelecomSystemTest extends TelecomTestCase { + boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null; + connectionServiceFixture.mConnectionServiceDelegate.mVideoState = videoState; + +- Bundle extras = new Bundle(); ++ if (extras == null) { ++ extras = new Bundle(); ++ } + extras.putParcelable( + TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, + Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null)); +@@ -834,7 +849,16 @@ public class TelecomSystemTest extends TelecomTestCase { + PhoneAccountHandle phoneAccountHandle, + ConnectionServiceFixture connectionServiceFixture) throws Exception { + return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture, +- VideoProfile.STATE_AUDIO_ONLY); ++ VideoProfile.STATE_AUDIO_ONLY, null); ++ } ++ ++ protected IdPair startAndMakeActiveOutgoingCallWithExtras( ++ String number, ++ PhoneAccountHandle phoneAccountHandle, ++ ConnectionServiceFixture connectionServiceFixture, ++ Intent callIntentExtras) throws Exception { ++ return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture, ++ VideoProfile.STATE_AUDIO_ONLY, callIntentExtras); + } + + // A simple outgoing call, verifying that the appropriate connection service is contacted, +@@ -842,9 +866,10 @@ public class TelecomSystemTest extends TelecomTestCase { + protected IdPair startAndMakeActiveOutgoingCall( + String number, + PhoneAccountHandle phoneAccountHandle, +- ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception { ++ ConnectionServiceFixture connectionServiceFixture, int videoState, ++ Intent callIntentExtras) throws Exception { + IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture, +- Process.myUserHandle(), videoState); ++ Process.myUserHandle(), videoState, callIntentExtras); + + connectionServiceFixture.sendSetDialing(ids.mConnectionId); + assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); +diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java +index 0319e81fa..6e2b70f25 100644 +--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java ++++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java +@@ -78,7 +78,7 @@ public class VideoCallTests extends TelecomSystemTest { + // Start an incoming video call. + IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", + mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, +- VideoProfile.STATE_BIDIRECTIONAL); ++ VideoProfile.STATE_BIDIRECTIONAL, null); + + verifyAudioRoute(CallAudioState.ROUTE_SPEAKER); + } +@@ -93,7 +93,7 @@ public class VideoCallTests extends TelecomSystemTest { + // Start an incoming video call. + IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", + mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, +- VideoProfile.STATE_TX_ENABLED); ++ VideoProfile.STATE_TX_ENABLED, null); + + verifyAudioRoute(CallAudioState.ROUTE_SPEAKER); + } +@@ -108,7 +108,7 @@ public class VideoCallTests extends TelecomSystemTest { + // Start an incoming video call. + IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", + mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, +- VideoProfile.STATE_AUDIO_ONLY); ++ VideoProfile.STATE_AUDIO_ONLY, null); + + verifyAudioRoute(CallAudioState.ROUTE_EARPIECE); + } diff --git a/Scripts/LineageOS-14.1/Patch.sh b/Scripts/LineageOS-14.1/Patch.sh index 1d7bec98..503bbec1 100644 --- a/Scripts/LineageOS-14.1/Patch.sh +++ b/Scripts/LineageOS-14.1/Patch.sh @@ -76,7 +76,7 @@ sed -i '50i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aap sed -i '296iLOCAL_AAPT_FLAGS += --auto-add-overlay' core/package_internal.mk; awk -i inplace '!/Email/' target/product/core.mk; #Remove Email awk -i inplace '!/Exchange2/' target/product/core.mk; -sed -i 's/2021-06-05/2023-07-05/' core/version_defaults.mk; #Bump Security String #n-asb-2023-07 #XXX +sed -i 's/2021-06-05/2023-08-05/' core/version_defaults.mk; #Bump Security String #n-asb-2023-08 #XXX fi; if enterAndClear "device/qcom/sepolicy"; then @@ -84,6 +84,10 @@ applyPatch "$DOS_PATCHES/android_device_qcom_sepolicy/248649.patch"; #msm_irqbal applyPatch "$DOS_PATCHES/android_device_qcom_sepolicy/0001-Camera_Fix.patch"; #Fix camera on user builds XXX: REMOVE THIS TRASH (DivestOS) fi; +if enterAndClear "external/aac"; then +applyPatch "$DOS_PATCHES/android_external_aac/364027-backport.patch"; #R_asb_2023-08 Increase patchParam array size by one and fix out-of-bounce write in resetLppTransposer(). +fi; + if enterAndClear "external/apache-http"; then applyPatch "$DOS_PATCHES/android_external_apache-http/0001-Fix.patch"; #Fix compile failure (AOSP) fi; @@ -207,6 +211,11 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/358734.patch"; #n-asb-2023-06 H applyPatch "$DOS_PATCHES/android_frameworks_base/360893.patch"; #n-asb-2023-07 Sanitize VPN label to prevent HTML injection applyPatch "$DOS_PATCHES/android_frameworks_base/360894.patch"; #n-asb-2023-07 Limit the number of supported v1 and v2 signers applyPatch "$DOS_PATCHES/android_frameworks_base/360895.patch"; #n-asb-2023-07 Truncate ShortcutInfo Id +applyPatch "$DOS_PATCHES/android_frameworks_base/364029-backport.patch"; #R_asb_2023-08 ActivityManager#killBackgroundProcesses can kill caller's own app only +applyPatch "$DOS_PATCHES/android_frameworks_base/364033-backport.patch"; #R_asb_2023-08 Ensure policy has no absurdly long strings +applyPatch "$DOS_PATCHES/android_frameworks_base/364036-backport.patch"; #R_asb_2023-08 Verify URI permissions in MediaMetadata +applyPatch "$DOS_PATCHES/android_frameworks_base/364037.patch"; #R_asb_2023-08 Use Settings.System.getIntForUser instead of getInt to make sure user specific settings are used +applyPatch "$DOS_PATCHES/android_frameworks_base/364038-backport.patch"; #R_asb_2023-08 Resolve StatusHints image exploit across user. git revert --no-edit 0326bb5e41219cf502727c3aa44ebf2daa19a5b3; #Re-enable doze on devices without gms applyPatch "$DOS_PATCHES/android_frameworks_base/248599.patch"; #Make SET_TIME_ZONE permission match SET_TIME (AOSP) applyPatch "$DOS_PATCHES/android_frameworks_base/0001-Reduced_Resolution.patch"; #Allow reducing resolution to save power TODO: Add 800x480 (DivestOS) @@ -420,6 +429,7 @@ if enterAndClear "packages/services/Telecomm"; then applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/332456.patch"; #n-asb-2022-06 limit TelecomManager#registerPhoneAccount to 10 applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/343953.patch"; #n-asb-2022-11 Switch TelecomManager List getters to ParceledListSlice applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/345526.patch"; #n-asb-2022-12 Hide overlay windows when showing phone account enable/disable screen. +applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/364041-backport.patch"; #R_asb_2023-08 Resolve StatusHints image exploit across user. fi; if enterAndClear "packages/services/Telephony"; then @@ -438,6 +448,7 @@ fi; if enterAndClear "packages/providers/TelephonyProvider"; then applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/343954.patch"; #n-asb-2022-11 Check dir path before updating permissions. +applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/364040-backport.patch"; #R_asb_2023-08 Update file permissions using canonical path fi; if enterAndClear "system/bt"; then