mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
18.1: September 2024 ASB work
Signed-off-by: Tavi <tavi@divested.dev>
This commit is contained in:
parent
a4f9a76fb9
commit
5c166d2039
@ -135,7 +135,7 @@ external/cblas d82c5f4ae14b2a5468303985070f7dadc15d4094
|
||||
external/cbor-java f81e576298790c97498311e99a0b0b34653c3dd8
|
||||
external/chromium-libpac 169c93e00a00605346a68d39d3f4713735bdb61e
|
||||
external/chromium-trace e524766cad26d677a9a1ec8c00c512d4cac2cf5e
|
||||
external/chromium-webview b270aa98312408d5893ee72fcd62b4d89937ceb2
|
||||
external/chromium-webview 8400ae9b819741cd4d436cce372496426ec85fc9
|
||||
external/clang 0a1c53a5d295109bd4702ad13c0f2a5510ca1b26
|
||||
external/cldr 38850463abd624d5b2293be75fddc43cf6b55ae2
|
||||
external/cn-cbor 696530332036f5518681d3c450cdbc3ee412004a
|
||||
|
@ -9,10 +9,10 @@ Reported by TaiYou
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
|
||||
index 381f3ef..97440d8 100644
|
||||
index c84b5ed..02f71c4 100644
|
||||
--- a/lib/xmlparse.c
|
||||
+++ b/lib/xmlparse.c
|
||||
@@ -1883,6 +1883,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
|
||||
@@ -1874,6 +1874,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
|
||||
|
||||
if (parser == NULL)
|
||||
return XML_STATUS_ERROR;
|
||||
|
@ -9,10 +9,10 @@ Reported by TaiYou
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
|
||||
index 97440d8..9bd93b0 100644
|
||||
index 02f71c4..18fcad0 100644
|
||||
--- a/lib/xmlparse.c
|
||||
+++ b/lib/xmlparse.c
|
||||
@@ -6377,6 +6377,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
@@ -6358,6 +6358,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
if (! newE)
|
||||
return 0;
|
||||
if (oldE->nDefaultAtts) {
|
||||
|
@ -9,10 +9,10 @@ Reported by TaiYou
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
|
||||
index 9bd93b0..e6f334a 100644
|
||||
index 18fcad0..b08cae9 100644
|
||||
--- a/lib/xmlparse.c
|
||||
+++ b/lib/xmlparse.c
|
||||
@@ -6929,6 +6929,15 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
@@ -6910,6 +6910,15 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
int next;
|
||||
|
||||
if (! dtd->scaffIndex) {
|
||||
|
@ -11,10 +11,10 @@ Subject: [PATCH] lib: Stop leaking opening tag bindings after closing tag
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
|
||||
index e6f334a..602fa33 100644
|
||||
index b08cae9..f2c245d 100644
|
||||
--- a/lib/xmlparse.c
|
||||
+++ b/lib/xmlparse.c
|
||||
@@ -2847,9 +2847,6 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
@@ -2828,9 +2828,6 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
int len;
|
||||
const char *rawName;
|
||||
TAG *tag = parser->m_tagStack;
|
||||
@ -24,7 +24,7 @@ index e6f334a..602fa33 100644
|
||||
rawName = s + enc->minBytesPerChar * 2;
|
||||
len = XmlNameLength(enc, rawName);
|
||||
if (len != tag->rawNameLength
|
||||
@@ -2857,6 +2854,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
@@ -2838,6 +2835,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
*eventPP = rawName;
|
||||
return XML_ERROR_TAG_MISMATCH;
|
||||
}
|
||||
|
34
Patches/LineageOS-18.1/android_frameworks_av/401372.patch
Normal file
34
Patches/LineageOS-18.1/android_frameworks_av/401372.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Wonsik Kim <wonsik@google.com>
|
||||
Date: Fri, 28 Jun 2024 00:33:51 +0000
|
||||
Subject: [PATCH] omx: check HDR10+ info param size
|
||||
|
||||
Bug: 329641908
|
||||
Test: presubmit
|
||||
Flag: EXEMPT security fix
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:53298956ba6bb8f147a632d7aaed8566dfc203ee)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f816148a719d2a3bbf432f11da98b3d5fa7de74f)
|
||||
Merged-In: I72523e1de61e5f947174272b732e170e1c2964df
|
||||
Change-Id: I72523e1de61e5f947174272b732e170e1c2964df
|
||||
---
|
||||
media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
|
||||
index 418302389d..4ab5d10609 100644
|
||||
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
|
||||
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
|
||||
@@ -619,6 +619,13 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig(
|
||||
if (!isValidOMXParam(outParams)) {
|
||||
return OMX_ErrorBadParameter;
|
||||
}
|
||||
+ if (offsetof(DescribeHDR10PlusInfoParams, nValue) + outParams->nParamSize >
|
||||
+ outParams->nSize) {
|
||||
+ ALOGE("b/329641908: too large param size; nParamSize=%u nSize=%u",
|
||||
+ outParams->nParamSize, outParams->nSize);
|
||||
+ android_errorWriteLog(0x534e4554, "329641908");
|
||||
+ return OMX_ErrorBadParameter;
|
||||
+ }
|
||||
|
||||
outParams->nParamSizeUsed = info->size();
|
||||
|
66
Patches/LineageOS-18.1/android_frameworks_base/401373.patch
Normal file
66
Patches/LineageOS-18.1/android_frameworks_base/401373.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kiran Ramachandra <kiranmr@google.com>
|
||||
Date: Wed, 5 Jun 2024 21:03:33 +0000
|
||||
Subject: [PATCH] DO NOT MERGE Ignore - Sanitized uri scheme by removing scheme
|
||||
delimiter
|
||||
|
||||
Initially considered removing unsupported characters as per IANA guidelines, but this could break applications that use custom schemes with asterisks. Instead, opted to remove only the "://" to minimize disruption
|
||||
|
||||
Bug: 261721900
|
||||
Test: atest FrameworksCoreTests:android.net.UriTest
|
||||
|
||||
No-Typo-Check: The unit test is specifically written to test few cases, string "http://https://" is not a typo
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1fd0421801c391dd619cafeeea8d379a9029074a)
|
||||
Merged-In: I88b1550a5d8b3dc0f6286e28899884025d059645
|
||||
Change-Id: I88b1550a5d8b3dc0f6286e28899884025d059645
|
||||
---
|
||||
core/java/android/net/Uri.java | 6 +++++-
|
||||
core/tests/coretests/src/android/net/UriTest.java | 11 +++++++++++
|
||||
2 files changed, 16 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
|
||||
index 84fc4f78edc4..4446f09bc874 100644
|
||||
--- a/core/java/android/net/Uri.java
|
||||
+++ b/core/java/android/net/Uri.java
|
||||
@@ -1380,7 +1380,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
|
||||
* @param scheme name or {@code null} if this is a relative Uri
|
||||
*/
|
||||
public Builder scheme(String scheme) {
|
||||
- this.scheme = scheme;
|
||||
+ if (scheme != null) {
|
||||
+ this.scheme = scheme.replace("://", "");
|
||||
+ } else {
|
||||
+ this.scheme = null;
|
||||
+ }
|
||||
return this;
|
||||
}
|
||||
|
||||
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
|
||||
index 670aefd21d36..17a37831afdb 100644
|
||||
--- a/core/tests/coretests/src/android/net/UriTest.java
|
||||
+++ b/core/tests/coretests/src/android/net/UriTest.java
|
||||
@@ -18,6 +18,7 @@ package android.net;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.os.Parcel;
|
||||
+import android.platform.test.annotations.AsbSecurityTest;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -88,6 +89,16 @@ public class UriTest extends TestCase {
|
||||
assertNull(u.getHost());
|
||||
}
|
||||
|
||||
+ @AsbSecurityTest(cveBugId = 261721900)
|
||||
+ @SmallTest
|
||||
+ public void testSchemeSanitization() {
|
||||
+ Uri uri = new Uri.Builder()
|
||||
+ .scheme("http://https://evil.com:/te:st/")
|
||||
+ .authority("google.com").path("one/way").build();
|
||||
+ assertEquals("httphttpsevil.com:/te:st/", uri.getScheme());
|
||||
+ assertEquals("httphttpsevil.com:/te:st/://google.com/one/way", uri.toString());
|
||||
+ }
|
||||
+
|
||||
@SmallTest
|
||||
public void testStringUri() {
|
||||
assertEquals("bob lee",
|
@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chaohui Wang <chaohuiw@google.com>
|
||||
Date: Thu, 2 Nov 2023 11:43:00 +0800
|
||||
Subject: [PATCH] Limit wifi item edit content's max length to 500
|
||||
|
||||
Bug: 293199910
|
||||
Test: manual - on "Add network"
|
||||
|
||||
(cherry picked from commit 855053ca4124f2d515b21c469096f8c18bd4829d)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:092668676af741719d50ac0f121a8f8461aa21ad)
|
||||
Merged-In: I303b8c6e0f3c3a1174a047ba98f302042e5db9ae
|
||||
Change-Id: I303b8c6e0f3c3a1174a047ba98f302042e5db9ae
|
||||
---
|
||||
res/values/styles.xml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/res/values/styles.xml b/res/values/styles.xml
|
||||
index 88760723883..2ce29040f0d 100644
|
||||
--- a/res/values/styles.xml
|
||||
+++ b/res/values/styles.xml
|
||||
@@ -147,6 +147,7 @@
|
||||
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
|
||||
<item name="android:textColorHint">?android:attr/textColorSecondary</item>
|
||||
<item name="android:minHeight">@dimen/min_tap_target_size</item>
|
||||
+ <item name="android:maxLength">500</item>
|
||||
</style>
|
||||
|
||||
<style name="wifi_section">
|
@ -1,3 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Chiu <chiujason@google.com>
|
||||
Date: Wed, 31 Jan 2024 16:29:01 +0800
|
||||
Subject: [PATCH] Replace getCallingActivity() with getLaunchedFromPackage()
|
||||
|
||||
getLaunchedFromPackage() reports who launched this Activity or built
|
||||
PendingIntent used to launch it, whereas getCallingActivity() reports
|
||||
who will get result of Activity.
|
||||
|
||||
Bug: 316891059
|
||||
Test: robotest, manual
|
||||
(cherry picked from commit ddc11bc03ab48e885f652b89df5f92ff283bcd4a)
|
||||
(cherry picked from commit 8bdbb580da847d82f16fb57883a01a5e65ffa696)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c7a8127d3bb6010617e507c03f7207dd50082953)
|
||||
Merged-In: If97018c2741caef622f0596bbfeaa42ef1788b78
|
||||
Change-Id: If97018c2741caef622f0596bbfeaa42ef1788b78
|
||||
---
|
||||
.../search/SearchFeatureProvider.java | 2 +-
|
||||
.../search/SearchFeatureProviderImpl.java | 20 +++++++++----------
|
||||
.../search/SearchResultTrampoline.java | 2 +-
|
||||
.../search/SearchFeatureProviderImplTest.java | 15 +++++++-------
|
||||
4 files changed, 19 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
|
||||
index 20d4e7c16bd..d6950eb06aa 100644
|
||||
--- a/src/com/android/settings/search/SearchFeatureProvider.java
|
||||
@ -12,7 +35,7 @@ index 20d4e7c16bd..d6950eb06aa 100644
|
||||
|
||||
/**
|
||||
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
|
||||
index 63bf420c027..eaadbc2af50 100644
|
||||
index 63bf420c027..423779fbabf 100644
|
||||
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
|
||||
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
|
||||
@@ -17,13 +17,14 @@
|
@ -0,0 +1,111 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Antol <cantol@google.com>
|
||||
Date: Tue, 4 Jun 2024 17:00:46 +0000
|
||||
Subject: [PATCH] Ignore fragment attr from ext authenticator resource
|
||||
|
||||
Bug: 341886134
|
||||
Test: Unit Test
|
||||
Test: Manual - see ticket for steps
|
||||
Flag: EXEMPT <security>
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2cb9b10ed97b1b9b29661115789605a762f3c2ef)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7e0b376b11318e1e79b31bac6aafc0c923868bc4)
|
||||
Merged-In: Id91c2b3b6d16ba3702ee2cd6723365a4db52863b
|
||||
Change-Id: Id91c2b3b6d16ba3702ee2cd6723365a4db52863b
|
||||
---
|
||||
.../accounts/AccountTypePreferenceLoader.java | 55 +++++++++++++++++++
|
||||
1 file changed, 55 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/settings/accounts/AccountTypePreferenceLoader.java b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
|
||||
index c639d1df2eb..84386a38f08 100644
|
||||
--- a/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
|
||||
+++ b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
|
||||
@@ -32,6 +32,10 @@ import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
+import androidx.annotation.NonNull;
|
||||
+import androidx.annotation.Nullable;
|
||||
+import androidx.annotation.VisibleForTesting;
|
||||
+import androidx.collection.ArraySet;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.Preference.OnPreferenceClickListener;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
@@ -45,6 +49,8 @@ import com.android.settings.utils.LocalClassLoaderContextThemeWrapper;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
|
||||
+import java.util.Set;
|
||||
+
|
||||
/**
|
||||
* Class to load the preference screen to be added to the settings page for the specific account
|
||||
* type as specified in the account-authenticator.
|
||||
@@ -83,6 +89,7 @@ public class AccountTypePreferenceLoader {
|
||||
try {
|
||||
desc = mAuthenticatorHelper.getAccountTypeDescription(accountType);
|
||||
if (desc != null && desc.accountPreferencesId != 0) {
|
||||
+ Set<String> fragmentAllowList = generateFragmentAllowlist(parent);
|
||||
// Load the context of the target package, then apply the
|
||||
// base Settings theme (no references to local resources)
|
||||
// and create a context theme wrapper so that we get the
|
||||
@@ -98,6 +105,12 @@ public class AccountTypePreferenceLoader {
|
||||
themedCtx.getTheme().setTo(baseTheme);
|
||||
prefs = mFragment.getPreferenceManager().inflateFromResource(themedCtx,
|
||||
desc.accountPreferencesId, parent);
|
||||
+ // Ignore Fragments provided dynamically, as these are coming from external
|
||||
+ // applications which must not have access to internal Settings' fragments.
|
||||
+ // These preferences are rendered into Settings, so they also won't have access
|
||||
+ // to their own Fragments, meaning there is no acceptable usage of
|
||||
+ // android:fragment here.
|
||||
+ filterBlockedFragments(prefs, fragmentAllowList);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
|
||||
@@ -182,6 +195,48 @@ public class AccountTypePreferenceLoader {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Build allowlist from existing Fragments in PreferenceGroup
|
||||
+ @VisibleForTesting
|
||||
+ Set<String> generateFragmentAllowlist(@Nullable PreferenceGroup prefs) {
|
||||
+ Set<String> fragmentAllowList = new ArraySet<>();
|
||||
+ if (prefs == null) {
|
||||
+ return fragmentAllowList;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < prefs.getPreferenceCount(); i++) {
|
||||
+ Preference pref = prefs.getPreference(i);
|
||||
+ if (pref instanceof PreferenceGroup) {
|
||||
+ fragmentAllowList.addAll(generateFragmentAllowlist((PreferenceGroup) pref));
|
||||
+ }
|
||||
+
|
||||
+ String fragmentName = pref.getFragment();
|
||||
+ if (!TextUtils.isEmpty(fragmentName)) {
|
||||
+ fragmentAllowList.add(fragmentName);
|
||||
+ }
|
||||
+ }
|
||||
+ return fragmentAllowList;
|
||||
+ }
|
||||
+
|
||||
+ // Block clicks on any Preference with android:fragment that is not contained in the allowlist
|
||||
+ @VisibleForTesting
|
||||
+ void filterBlockedFragments(@Nullable PreferenceGroup prefs,
|
||||
+ @NonNull Set<String> allowedFragments) {
|
||||
+ if (prefs == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ for (int i = 0; i < prefs.getPreferenceCount(); i++) {
|
||||
+ Preference pref = prefs.getPreference(i);
|
||||
+ if (pref instanceof PreferenceGroup) {
|
||||
+ filterBlockedFragments((PreferenceGroup) pref, allowedFragments);
|
||||
+ }
|
||||
+
|
||||
+ String fragmentName = pref.getFragment();
|
||||
+ if (fragmentName != null && !allowedFragments.contains(fragmentName)) {
|
||||
+ pref.setOnPreferenceClickListener(preference -> true);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Determines if the supplied Intent is safe. A safe intent is one that is
|
||||
* will launch a exported=true activity or owned by the same uid as the
|
@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Antol <cantol@google.com>
|
||||
Date: Mon, 25 Mar 2024 23:49:35 +0000
|
||||
Subject: [PATCH] RESTRICT AUTOMERGE Restrict Settings Homepage prior to
|
||||
provisioning
|
||||
|
||||
Bug: 327749022
|
||||
Test: manual test
|
||||
1. factory reset + launch Settings via ADB during Setup -> verify app closes
|
||||
2. factory reset + bypass Setup + tap Settings icon in launcher -> verify app closes
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:70a5a0fd353cc6203d2926627de93786155ae5bc)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7f1c4df02d153cb380a6147e86194bec2a564ab7)
|
||||
Merged-In: I8cbe38109ebf88a0f68f3917e95468a81c6463c1
|
||||
Change-Id: I8cbe38109ebf88a0f68f3917e95468a81c6463c1
|
||||
---
|
||||
.../settings/homepage/SettingsHomepageActivity.java | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
|
||||
index a8426437f57..d9f3c31ed22 100644
|
||||
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
|
||||
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
|
||||
@@ -43,6 +43,16 @@ public class SettingsHomepageActivity extends FragmentActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
+ // Ensure device is provisioned in order to access Settings home
|
||||
+ // TODO(b/331254029): This should later be replaced in favor of an allowlist
|
||||
+ boolean unprovisioned = android.provider.Settings.Global.getInt(getContentResolver(),
|
||||
+ android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 0;
|
||||
+ if (unprovisioned) {
|
||||
+ Log.e("SettingsHomepageActivity", "Device is not provisioned, exiting Settings");
|
||||
+ finish();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
setContentView(R.layout.settings_homepage_container);
|
||||
final View root = findViewById(R.id.settings_homepage_container);
|
||||
root.setSystemUiVisibility(
|
@ -0,0 +1,702 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Grant Menke <grantmenke@google.com>
|
||||
Date: Thu, 25 Apr 2024 10:43:43 -0700
|
||||
Subject: [PATCH] DO NOT MERGE Unbind CS if connection is not created within 15
|
||||
seconds.
|
||||
|
||||
This CL adds a check to ensure that connection creation occurs within 15 seconds after binding to that ConnectionService. If the connection/conference is not created in that timespan, this CL adds logic to manually unbind the ConnectionService at that point in time. This prevents malicious apps from keeping a declared permission in forever even in the background.
|
||||
|
||||
Bug: 293458004
|
||||
Test: manually using the provided apk + atest CallsManagerTest
|
||||
Flag: EXEMPT Security High/Critical Severity CVE
|
||||
(cherry picked from commit 7aa55ffca65d6166145fd9660e0f7340c07053bf)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:286781dfcb78d8b5c1a77f2390f5251f01943add)
|
||||
Merged-In: I30caed1481dff5af2223a8ff589846597cee8229
|
||||
Change-Id: I30caed1481dff5af2223a8ff589846597cee8229
|
||||
---
|
||||
src/com/android/server/telecom/Call.java | 26 ++
|
||||
.../telecom/ConnectionServiceWrapper.java | 74 ++++-
|
||||
src/com/android/server/telecom/LogUtils.java | 2 +
|
||||
.../server/telecom/tests/BasicCallTests.java | 2 +
|
||||
.../telecom/tests/CallsManagerTest.java | 54 ++++
|
||||
.../tests/ComponentContextFixture.java | 14 +
|
||||
.../tests/TestScheduledExecutorService.java | 283 ++++++++++++++++++
|
||||
7 files changed, 453 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java
|
||||
|
||||
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
|
||||
index cd236d2f4..e8c5a47ac 100755
|
||||
--- a/src/com/android/server/telecom/Call.java
|
||||
+++ b/src/com/android/server/telecom/Call.java
|
||||
@@ -329,6 +329,17 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
|
||||
/** The state of the call. */
|
||||
private int mState;
|
||||
|
||||
+ /**
|
||||
+ * Determines whether the {@link ConnectionService} has responded to the initial request to
|
||||
+ * create the connection.
|
||||
+ *
|
||||
+ * {@code false} indicates the {@link Call} has been added to Telecom, but the
|
||||
+ * {@link Connection} has not yet been returned by the associated {@link ConnectionService}.
|
||||
+ * {@code true} indicates the {@link Call} has an associated {@link Connection} reported by the
|
||||
+ * {@link ConnectionService}.
|
||||
+ */
|
||||
+ private boolean mIsCreateConnectionComplete = false;
|
||||
+
|
||||
/** The handle with which to establish this call. */
|
||||
private Uri mHandle;
|
||||
|
||||
@@ -958,6 +969,19 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
|
||||
return mConnectionService;
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * @return {@code true} if the connection has been created by the underlying
|
||||
+ * {@link ConnectionService}, {@code false} otherwise.
|
||||
+ */
|
||||
+ public boolean isCreateConnectionComplete() {
|
||||
+ return mIsCreateConnectionComplete;
|
||||
+ }
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ public void setIsCreateConnectionComplete(boolean isCreateConnectionComplete) {
|
||||
+ mIsCreateConnectionComplete = isCreateConnectionComplete;
|
||||
+ }
|
||||
+
|
||||
@VisibleForTesting
|
||||
public int getState() {
|
||||
return mState;
|
||||
@@ -2043,6 +2067,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
|
||||
CallIdMapper idMapper,
|
||||
ParcelableConference conference) {
|
||||
Log.v(this, "handleCreateConferenceSuccessful %s", conference);
|
||||
+ mIsCreateConnectionComplete = true;
|
||||
setTargetPhoneAccount(conference.getPhoneAccount());
|
||||
setHandle(conference.getHandle(), conference.getHandlePresentation());
|
||||
|
||||
@@ -2076,6 +2101,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
|
||||
CallIdMapper idMapper,
|
||||
ParcelableConnection connection) {
|
||||
Log.v(this, "handleCreateConnectionSuccessful %s", connection);
|
||||
+ mIsCreateConnectionComplete = true;
|
||||
setTargetPhoneAccount(connection.getPhoneAccount());
|
||||
setHandle(connection.getHandle(), connection.getHandlePresentation());
|
||||
setCallerDisplayName(
|
||||
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
|
||||
index 64fdd8833..6ca74fba3 100644
|
||||
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
|
||||
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
|
||||
@@ -37,6 +37,7 @@ import android.telecom.ConnectionService;
|
||||
import android.telecom.DisconnectCause;
|
||||
import android.telecom.GatewayInfo;
|
||||
import android.telecom.Log;
|
||||
+import android.telecom.Logging.Runnable;
|
||||
import android.telecom.Logging.Session;
|
||||
import android.telecom.ParcelableConference;
|
||||
import android.telecom.ParcelableConnection;
|
||||
@@ -59,6 +60,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
+import java.util.concurrent.ExecutorService;
|
||||
+import java.util.concurrent.Executors;
|
||||
+import java.util.concurrent.ScheduledExecutorService;
|
||||
+import java.util.concurrent.ScheduledFuture;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Wrapper for {@link IConnectionService}s, handles binding to {@link IConnectionService} and keeps
|
||||
@@ -72,6 +78,11 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
|
||||
private static final String TELECOM_ABBREVIATION = "cast";
|
||||
|
||||
+ private static final long SERVICE_BINDING_TIMEOUT = 15000L;
|
||||
+ private ScheduledExecutorService mScheduledExecutor =
|
||||
+ Executors.newSingleThreadScheduledExecutor();
|
||||
+ // Pre-allocate space for 2 calls; realistically thats all we should ever need (tm)
|
||||
+ private final Map<Call, ScheduledFuture<?>> mScheduledFutureMap = new ConcurrentHashMap<>(2);
|
||||
private final class Adapter extends IConnectionServiceAdapter.Stub {
|
||||
|
||||
@Override
|
||||
@@ -84,6 +95,12 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
logIncoming("handleCreateConnectionComplete %s", callId);
|
||||
+ Call call = mCallIdMapper.getCall(callId);
|
||||
+ if (mScheduledFutureMap.containsKey(call)) {
|
||||
+ ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
|
||||
+ existingTimeout.cancel(false /* cancelIfRunning */);
|
||||
+ mScheduledFutureMap.remove(call);
|
||||
+ }
|
||||
// Check status hints image for cross user access
|
||||
if (connection.getStatusHints() != null) {
|
||||
Icon icon = connection.getStatusHints().getIcon();
|
||||
@@ -120,6 +137,12 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
logIncoming("handleCreateConferenceComplete %s", callId);
|
||||
+ Call call = mCallIdMapper.getCall(callId);
|
||||
+ if (mScheduledFutureMap.containsKey(call)) {
|
||||
+ ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
|
||||
+ existingTimeout.cancel(false /* cancelIfRunning */);
|
||||
+ mScheduledFutureMap.remove(call);
|
||||
+ }
|
||||
ConnectionServiceWrapper.this
|
||||
.handleCreateConferenceComplete(callId, request, conference);
|
||||
|
||||
@@ -1183,7 +1206,8 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
* @param context The context.
|
||||
* @param userHandle The {@link UserHandle} to use when binding.
|
||||
*/
|
||||
- ConnectionServiceWrapper(
|
||||
+ @VisibleForTesting
|
||||
+ public ConnectionServiceWrapper(
|
||||
ComponentName componentName,
|
||||
ConnectionServiceRepository connectionServiceRepository,
|
||||
PhoneAccountRegistrar phoneAccountRegistrar,
|
||||
@@ -1258,6 +1282,26 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
.setIsAdhocConferenceCall(call.isAdhocConferenceCall())
|
||||
.build();
|
||||
|
||||
+ Runnable r = new Runnable("CSW.cC", mLock) {
|
||||
+ @Override
|
||||
+ public void loggedRun() {
|
||||
+ if (!call.isCreateConnectionComplete()) {
|
||||
+ Log.e(this, new Exception(),
|
||||
+ "Conference %s creation timeout",
|
||||
+ getComponentName());
|
||||
+ Log.addEvent(call, LogUtils.Events.CREATE_CONFERENCE_TIMEOUT,
|
||||
+ Log.piiHandle(call.getHandle()) + " via:" +
|
||||
+ getComponentName().getPackageName());
|
||||
+ response.handleCreateConferenceFailure(
|
||||
+ new DisconnectCause(DisconnectCause.ERROR));
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+ // Post cleanup to the executor service and cache the future, so we can cancel it if
|
||||
+ // needed.
|
||||
+ ScheduledFuture<?> future = mScheduledExecutor.schedule(r.getRunnableToCancel(),
|
||||
+ SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
+ mScheduledFutureMap.put(call, future);
|
||||
try {
|
||||
mServiceInterface.createConference(
|
||||
call.getConnectionManagerPhoneAccount(),
|
||||
@@ -1347,6 +1391,26 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
.setRttPipeToInCall(call.getCsToInCallRttPipeForCs())
|
||||
.build();
|
||||
|
||||
+ Runnable r = new Runnable("CSW.cC", mLock) {
|
||||
+ @Override
|
||||
+ public void loggedRun() {
|
||||
+ if (!call.isCreateConnectionComplete()) {
|
||||
+ Log.e(this, new Exception(),
|
||||
+ "Connection %s creation timeout",
|
||||
+ getComponentName());
|
||||
+ Log.addEvent(call, LogUtils.Events.CREATE_CONNECTION_TIMEOUT,
|
||||
+ Log.piiHandle(call.getHandle()) + " via:" +
|
||||
+ getComponentName().getPackageName());
|
||||
+ response.handleCreateConnectionFailure(
|
||||
+ new DisconnectCause(DisconnectCause.ERROR));
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+ // Post cleanup to the executor service and cache the future, so we can cancel it if
|
||||
+ // needed.
|
||||
+ ScheduledFuture<?> future = mScheduledExecutor.schedule(r.getRunnableToCancel(),
|
||||
+ SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
+ mScheduledFutureMap.put(call, future);
|
||||
try {
|
||||
mServiceInterface.createConnection(
|
||||
call.getConnectionManagerPhoneAccount(),
|
||||
@@ -1727,7 +1791,8 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
}
|
||||
}
|
||||
|
||||
- void addCall(Call call) {
|
||||
+ @VisibleForTesting
|
||||
+ public void addCall(Call call) {
|
||||
if (mCallIdMapper.getCallId(call) == null) {
|
||||
mCallIdMapper.addCall(call);
|
||||
}
|
||||
@@ -2172,4 +2237,9 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ public void setScheduledExecutorService(ScheduledExecutorService service) {
|
||||
+ mScheduledExecutor = service;
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
|
||||
index 5bb14e625..1c62a5c71 100644
|
||||
--- a/src/com/android/server/telecom/LogUtils.java
|
||||
+++ b/src/com/android/server/telecom/LogUtils.java
|
||||
@@ -124,8 +124,10 @@ public class LogUtils {
|
||||
public static final String STOP_CALL_WAITING_TONE = "STOP_CALL_WAITING_TONE";
|
||||
public static final String START_CONNECTION = "START_CONNECTION";
|
||||
public static final String CREATE_CONNECTION_FAILED = "CREATE_CONNECTION_FAILED";
|
||||
+ public static final String CREATE_CONNECTION_TIMEOUT = "CREATE_CONNECTION_TIMEOUT";
|
||||
public static final String START_CONFERENCE = "START_CONFERENCE";
|
||||
public static final String CREATE_CONFERENCE_FAILED = "CREATE_CONFERENCE_FAILED";
|
||||
+ public static final String CREATE_CONFERENCE_TIMEOUT = "CREATE_CONFERENCE_TIMEOUT";
|
||||
public static final String BIND_CS = "BIND_CS";
|
||||
public static final String CS_BOUND = "CS_BOUND";
|
||||
public static final String CONFERENCE_WITH = "CONF_WITH";
|
||||
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
|
||||
index 382e0b710..6ac8e1c62 100644
|
||||
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
|
||||
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
|
||||
@@ -963,6 +963,7 @@ public class BasicCallTests extends TelecomSystemTest {
|
||||
call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle());
|
||||
assert(call.isVideoCallingSupportedByPhoneAccount());
|
||||
assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
|
||||
+ call.setIsCreateConnectionComplete(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -986,6 +987,7 @@ public class BasicCallTests extends TelecomSystemTest {
|
||||
call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle());
|
||||
assert(!call.isVideoCallingSupportedByPhoneAccount());
|
||||
assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState());
|
||||
+ call.setIsCreateConnectionComplete(true);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
|
||||
index d16430298..912b56cf3 100644
|
||||
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
|
||||
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
|
||||
@@ -40,11 +40,13 @@ import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
+import static java.lang.Thread.sleep;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
+import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
@@ -62,6 +64,7 @@ import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.widget.Toast;
|
||||
|
||||
+import com.android.internal.telecom.IConnectionService;
|
||||
import com.android.server.telecom.AsyncRingtonePlayer;
|
||||
import com.android.server.telecom.Call;
|
||||
import com.android.server.telecom.CallAudioManager;
|
||||
@@ -74,6 +77,7 @@ import com.android.server.telecom.CallsManagerListenerBase;
|
||||
import com.android.server.telecom.ClockProxy;
|
||||
import com.android.server.telecom.ConnectionServiceFocusManager;
|
||||
import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
|
||||
+import com.android.server.telecom.CreateConnectionResponse;
|
||||
import com.android.server.telecom.DefaultDialerCache;
|
||||
import com.android.server.telecom.EmergencyCallHelper;
|
||||
import com.android.server.telecom.HeadsetMediaButton;
|
||||
@@ -207,6 +211,7 @@ public class CallsManagerTest extends TelecomTestCase {
|
||||
@Mock private IncomingCallFilter mIncomingCallFilter;
|
||||
@Mock private ToastFactory mToastFactory;
|
||||
@Mock private Toast mToast;
|
||||
+ @Mock private IConnectionService mIConnectionService;
|
||||
|
||||
private CallsManager mCallsManager;
|
||||
|
||||
@@ -274,11 +279,19 @@ public class CallsManagerTest extends TelecomTestCase {
|
||||
eq(SIM_2_HANDLE), any())).thenReturn(SIM_2_ACCOUNT);
|
||||
when(mToastFactory.makeText(any(), anyInt(), anyInt())).thenReturn(mToast);
|
||||
when(mToastFactory.makeText(any(), any(), anyInt())).thenReturn(mToast);
|
||||
+ when(mIConnectionService.asBinder()).thenReturn(mock(IBinder.class));
|
||||
+
|
||||
+ mComponentContextFixture.addConnectionService(new ComponentName(mContext.getPackageName(),
|
||||
+ mContext.getPackageName().getClass().getName()), mIConnectionService);
|
||||
}
|
||||
|
||||
@Override
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
+ mComponentContextFixture.removeConnectionService(
|
||||
+ new ComponentName(mContext.getPackageName(),
|
||||
+ mContext.getPackageName().getClass().getName()),
|
||||
+ mock(IConnectionService.class));
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@@ -1456,6 +1469,32 @@ public class CallsManagerTest extends TelecomTestCase {
|
||||
assertTrue(argumentCaptor.getValue().contains("Unavailable phoneAccountHandle"));
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testConnectionServiceCreateConnectionTimeout() throws Exception {
|
||||
+ ConnectionServiceWrapper service = new ConnectionServiceWrapper(new ComponentName(
|
||||
+ mContext.getPackageName(), mContext.getPackageName().getClass().getName()), null,
|
||||
+ mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null);
|
||||
+ TestScheduledExecutorService scheduledExecutorService = new TestScheduledExecutorService();
|
||||
+ service.setScheduledExecutorService(scheduledExecutorService);
|
||||
+ Call call = addSpyCall();
|
||||
+ service.addCall(call);
|
||||
+ when(call.isCreateConnectionComplete()).thenReturn(false);
|
||||
+ CreateConnectionResponse response = mock(CreateConnectionResponse.class);
|
||||
+
|
||||
+ service.createConnection(call, response);
|
||||
+ waitUntilConditionIsTrueOrTimeout(new Condition() {
|
||||
+ @Override
|
||||
+ public Object expected() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Object actual() {
|
||||
+ return scheduledExecutorService.isRunnableScheduledAtTime(15000L);
|
||||
+ }
|
||||
+ }, 5000L, "Expected job failed to schedule");
|
||||
+ }
|
||||
+
|
||||
private Call addSpyCall() {
|
||||
return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
|
||||
}
|
||||
@@ -1549,4 +1588,19 @@ public class CallsManagerTest extends TelecomTestCase {
|
||||
when(mPhoneAccountRegistrar.getSimPhoneAccountsOfCurrentUser()).thenReturn(
|
||||
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
|
||||
}
|
||||
+
|
||||
+ private void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout,
|
||||
+ String description) throws InterruptedException {
|
||||
+ final long start = System.currentTimeMillis();
|
||||
+ while (!condition.expected().equals(condition.actual())
|
||||
+ && System.currentTimeMillis() - start < timeout) {
|
||||
+ sleep(50);
|
||||
+ }
|
||||
+ assertEquals(description, condition.expected(), condition.actual());
|
||||
+ }
|
||||
+
|
||||
+ protected interface Condition {
|
||||
+ Object expected();
|
||||
+ Object actual();
|
||||
+ }
|
||||
}
|
||||
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
|
||||
index af062d77f..0768970b1 100644
|
||||
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
|
||||
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
|
||||
@@ -589,6 +589,14 @@ public class ComponentContextFixture implements TestFixture<Context> {
|
||||
mServiceInfoByComponentName.put(componentName, serviceInfo);
|
||||
}
|
||||
|
||||
+ public void removeConnectionService(
|
||||
+ ComponentName componentName,
|
||||
+ IConnectionService service)
|
||||
+ throws Exception {
|
||||
+ removeService(ConnectionService.SERVICE_INTERFACE, componentName, service);
|
||||
+ mServiceInfoByComponentName.remove(componentName);
|
||||
+ }
|
||||
+
|
||||
public void addInCallService(
|
||||
ComponentName componentName,
|
||||
IInCallService service,
|
||||
@@ -658,6 +666,12 @@ public class ComponentContextFixture implements TestFixture<Context> {
|
||||
mComponentNameByService.put(service, name);
|
||||
}
|
||||
|
||||
+ private void removeService(String action, ComponentName name, IInterface service) {
|
||||
+ mComponentNamesByAction.remove(action, name);
|
||||
+ mServiceByComponentName.remove(name);
|
||||
+ mComponentNameByService.remove(service);
|
||||
+ }
|
||||
+
|
||||
private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) {
|
||||
List<ResolveInfo> result = new ArrayList<>();
|
||||
for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) {
|
||||
diff --git a/tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java b/tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java
|
||||
new file mode 100644
|
||||
index 000000000..8ddf42b9b
|
||||
--- /dev/null
|
||||
+++ b/tests/src/com/android/server/telecom/tests/TestScheduledExecutorService.java
|
||||
@@ -0,0 +1,283 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2022 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.server.telecom.tests;
|
||||
+
|
||||
+import android.util.Log;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collection;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.Optional;
|
||||
+import java.util.concurrent.Callable;
|
||||
+import java.util.concurrent.Delayed;
|
||||
+import java.util.concurrent.ExecutionException;
|
||||
+import java.util.concurrent.Executors;
|
||||
+import java.util.concurrent.Future;
|
||||
+import java.util.concurrent.ScheduledExecutorService;
|
||||
+import java.util.concurrent.ScheduledFuture;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+import java.util.concurrent.TimeoutException;
|
||||
+
|
||||
+/**
|
||||
+ * A test implementation of a scheduled executor service.
|
||||
+ */
|
||||
+public class TestScheduledExecutorService implements ScheduledExecutorService {
|
||||
+ private static final String TAG = "TestScheduledExecutorService";
|
||||
+
|
||||
+ private class CompletedFuture<T> implements Future<T>, ScheduledFuture<T> {
|
||||
+
|
||||
+ private final Callable<T> mTask;
|
||||
+ private final long mDelayMs;
|
||||
+ private Runnable mRunnable;
|
||||
+
|
||||
+ CompletedFuture(Callable<T> task) {
|
||||
+ mTask = task;
|
||||
+ mDelayMs = 0;
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unused")
|
||||
+ CompletedFuture(Callable<T> task, long delayMs) {
|
||||
+ mTask = task;
|
||||
+ mDelayMs = delayMs;
|
||||
+ }
|
||||
+
|
||||
+ CompletedFuture(Runnable task, long delayMs) {
|
||||
+ mRunnable = task;
|
||||
+ mTask = (Callable<T>) Executors.callable(task);
|
||||
+ mDelayMs = delayMs;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
+ cancelRunnable(mRunnable);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isDone() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public T get() throws InterruptedException, ExecutionException {
|
||||
+ try {
|
||||
+ return mTask.call();
|
||||
+ } catch (Exception e) {
|
||||
+ throw new ExecutionException(e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public T get(long timeout, TimeUnit unit)
|
||||
+ throws InterruptedException, ExecutionException, TimeoutException {
|
||||
+ try {
|
||||
+ return mTask.call();
|
||||
+ } catch (Exception e) {
|
||||
+ throw new ExecutionException(e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public long getDelay(TimeUnit unit) {
|
||||
+ if (unit == TimeUnit.MILLISECONDS) {
|
||||
+ return mDelayMs;
|
||||
+ } else {
|
||||
+ // not implemented
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int compareTo(Delayed o) {
|
||||
+ if (o == null) return 1;
|
||||
+ if (o.getDelay(TimeUnit.MILLISECONDS) > mDelayMs) return -1;
|
||||
+ if (o.getDelay(TimeUnit.MILLISECONDS) < mDelayMs) return 1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private long mClock = 0;
|
||||
+ private Map<Long, Runnable> mScheduledRunnables = new HashMap<>();
|
||||
+ private Map<Runnable, Long> mRepeatDuration = new HashMap<>();
|
||||
+
|
||||
+ @Override
|
||||
+ public void shutdown() {
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<Runnable> shutdownNow() {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isShutdown() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isTerminated() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean awaitTermination(long timeout, TimeUnit unit) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> Future<T> submit(Callable<T> task) {
|
||||
+ return new TestScheduledExecutorService.CompletedFuture<>(task);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> Future<T> submit(Runnable task, T result) {
|
||||
+ throw new UnsupportedOperationException("Not implemented");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Future<?> submit(Runnable task) {
|
||||
+ task.run();
|
||||
+ return new TestScheduledExecutorService.CompletedFuture<>(() -> null);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
|
||||
+ throw new UnsupportedOperationException("Not implemented");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout,
|
||||
+ TimeUnit unit) {
|
||||
+ throw new UnsupportedOperationException("Not implemented");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks) {
|
||||
+ throw new UnsupportedOperationException("Not implemented");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) {
|
||||
+ throw new UnsupportedOperationException("Not implemented");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||
+ // Schedule the runnable for execution at the specified time.
|
||||
+ long scheduledTime = getNextExecutionTime(delay, unit);
|
||||
+ mScheduledRunnables.put(scheduledTime, command);
|
||||
+
|
||||
+ Log.i(TAG, "schedule: runnable=" + System.identityHashCode(command) + ", time="
|
||||
+ + scheduledTime);
|
||||
+
|
||||
+ return new TestScheduledExecutorService.CompletedFuture<Runnable>(command, delay);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
|
||||
+ throw new UnsupportedOperationException("Not implemented");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period,
|
||||
+ TimeUnit unit) {
|
||||
+ return scheduleWithFixedDelay(command, initialDelay, period, unit);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
|
||||
+ long delay, TimeUnit unit) {
|
||||
+ // Schedule the runnable for execution at the specified time.
|
||||
+ long nextScheduledTime = getNextExecutionTime(delay, unit);
|
||||
+ mScheduledRunnables.put(nextScheduledTime, command);
|
||||
+ mRepeatDuration.put(command, unit.toMillis(delay));
|
||||
+
|
||||
+ return new TestScheduledExecutorService.CompletedFuture<Runnable>(command, delay);
|
||||
+ }
|
||||
+
|
||||
+ private long getNextExecutionTime(long delay, TimeUnit unit) {
|
||||
+ long delayMillis = unit.toMillis(delay);
|
||||
+ return mClock + delayMillis;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void execute(Runnable command) {
|
||||
+ command.run();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Used in unit tests, used to add a delta to the "clock" so that we can fire off scheduled
|
||||
+ * items and reschedule the repeats.
|
||||
+ * @param duration The duration (millis) to add to the clock.
|
||||
+ */
|
||||
+ public void advanceTime(long duration) {
|
||||
+ Map<Long, Runnable> nextRepeats = new HashMap<>();
|
||||
+ List<Runnable> toRun = new ArrayList<>();
|
||||
+ mClock += duration;
|
||||
+ Iterator<Map.Entry<Long, Runnable>> iterator = mScheduledRunnables.entrySet().iterator();
|
||||
+ while (iterator.hasNext()) {
|
||||
+ Map.Entry<Long, Runnable> entry = iterator.next();
|
||||
+ if (mClock >= entry.getKey()) {
|
||||
+ toRun.add(entry.getValue());
|
||||
+
|
||||
+ Runnable r = entry.getValue();
|
||||
+ Log.i(TAG, "advanceTime: runningRunnable=" + System.identityHashCode(r));
|
||||
+ // If this is a repeating scheduled item, schedule the repeat.
|
||||
+ if (mRepeatDuration.containsKey(r)) {
|
||||
+ // schedule next execution
|
||||
+ nextRepeats.put(mClock + mRepeatDuration.get(r), entry.getValue());
|
||||
+ }
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Update things at the end to avoid concurrent access.
|
||||
+ mScheduledRunnables.putAll(nextRepeats);
|
||||
+ toRun.forEach(r -> r.run());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Used from a {@link CompletedFuture} as defined above to cancel a scheduled task.
|
||||
+ * @param r The runnable to cancel.
|
||||
+ */
|
||||
+ private void cancelRunnable(Runnable r) {
|
||||
+ Optional<Map.Entry<Long, Runnable>> found = mScheduledRunnables.entrySet().stream()
|
||||
+ .filter(e -> e.getValue() == r)
|
||||
+ .findFirst();
|
||||
+ if (found.isPresent()) {
|
||||
+ mScheduledRunnables.remove(found.get().getKey());
|
||||
+ }
|
||||
+ mRepeatDuration.remove(r);
|
||||
+ Log.i(TAG, "cancelRunnable: runnable=" + System.identityHashCode(r));
|
||||
+ }
|
||||
+
|
||||
+ public int getNumberOfScheduledRunnables() {
|
||||
+ return mScheduledRunnables.size();
|
||||
+ }
|
||||
+
|
||||
+ public boolean isRunnableScheduledAtTime(long time) {
|
||||
+ return mScheduledRunnables.containsKey(time);
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Pranav Madapurmath <pmadapurmath@google.com>
|
||||
Date: Tue, 11 Jun 2024 15:51:39 +0000
|
||||
Subject: [PATCH] Unbind CallScreeningService when timeout reached.
|
||||
|
||||
In a vulnerability, the exploiter showed that an app which implements a
|
||||
service with role holding ROLE_CALL_SCREENING can be used to keep a
|
||||
service alive. The assumption is that the CallScreeningService class
|
||||
uses MSG_SCREEN_CALL to screen the call and results in the service being
|
||||
unbound for outgoing calls once screening completes. However, a vanilla
|
||||
service which holds the ROLE_CALL_SCREENING role can still be used as
|
||||
the default call screening app which keeps the service alive.
|
||||
|
||||
This CL ensures that after the timeout is reached that we try to unbind
|
||||
the service if possible.
|
||||
|
||||
Bug: 300904123
|
||||
Test: Manual test to verify that onDestroy is called for the service
|
||||
after the timeout is reached.
|
||||
|
||||
(cherry picked from commit 9d97cd5825066ac8e15bbf97f6755663c5341afb)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d57f25311acb7fb887fb0296364526345cc905bb)
|
||||
Merged-In: I30d276867c571ece113106d3b363fce99d64f441
|
||||
Change-Id: I30d276867c571ece113106d3b363fce99d64f441
|
||||
---
|
||||
.../android/server/telecom/CallScreeningServiceHelper.java | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/server/telecom/CallScreeningServiceHelper.java b/src/com/android/server/telecom/CallScreeningServiceHelper.java
|
||||
index 5e47c1f94..e9ad451c2 100644
|
||||
--- a/src/com/android/server/telecom/CallScreeningServiceHelper.java
|
||||
+++ b/src/com/android/server/telecom/CallScreeningServiceHelper.java
|
||||
@@ -191,6 +191,10 @@ public class CallScreeningServiceHelper {
|
||||
Log.w(TAG, "Cancelling call id process due to timeout");
|
||||
}
|
||||
mFuture.complete(null);
|
||||
+ mContext.unbindService(serviceConnection);
|
||||
+ } catch (IllegalArgumentException e) {
|
||||
+ Log.i(this, "Exception when unbinding service %s : %s", serviceConnection,
|
||||
+ e.getMessage());
|
||||
} finally {
|
||||
Log.endSession();
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Pranav Madapurmath <pmadapurmath@google.com>
|
||||
Date: Tue, 11 Jun 2024 22:50:08 -0700
|
||||
Subject: [PATCH] Resolve cross-user image exploit for conference status hints
|
||||
|
||||
Ensure that status hint image icon is validated for cross-user exploits.
|
||||
Currently, there is no check for this so a conference call can display
|
||||
an image from another user, exposing a vulnerability.
|
||||
|
||||
Bug: 329058967
|
||||
Test: Manual with POC
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a8e2bf9c77cd94f683979c849015b78ef0537802)
|
||||
Merged-In: Ib9d701398d25d021cdb9abacbaa5b175f62bee1d
|
||||
Change-Id: Ib9d701398d25d021cdb9abacbaa5b175f62bee1d
|
||||
---
|
||||
.../android/server/telecom/ConnectionServiceWrapper.java | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
|
||||
index 6ca74fba3..e944209a4 100644
|
||||
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
|
||||
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
|
||||
@@ -133,10 +133,17 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
|
||||
ParcelableConference conference, Session.Info sessionInfo) {
|
||||
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
|
||||
mPackageAbbreviation);
|
||||
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
logIncoming("handleCreateConferenceComplete %s", callId);
|
||||
+ // Check status hints image for cross user access
|
||||
+ if (conference.getStatusHints() != null) {
|
||||
+ Icon icon = conference.getStatusHints().getIcon();
|
||||
+ conference.getStatusHints().setIcon(StatusHints.
|
||||
+ validateAccountIconUserBoundary(icon, callingUserHandle));
|
||||
+ }
|
||||
Call call = mCallIdMapper.getCall(callId);
|
||||
if (mScheduledFutureMap.containsKey(call)) {
|
||||
ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
|
@ -93,7 +93,7 @@ applyPatch "$DOS_PATCHES_COMMON/android_build/0001-verity-openssl3.patch"; #Fix
|
||||
sed -i '75i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aapt2.mk; #Enable auto-add-overlay for packages, this allows the vendor overlay to easily work across all branches.
|
||||
awk -i inplace '!/updatable_apex.mk/' target/product/mainline_system.mk; #Disable APEX
|
||||
sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
|
||||
sed -i 's/2024-02-05/2024-08-05/' core/version_defaults.mk; #Bump Security String #R_asb_2024-08
|
||||
sed -i 's/2024-02-05/2024-09-05/' core/version_defaults.mk; #Bump Security String #R_asb_2024-09
|
||||
fi;
|
||||
|
||||
if enterAndClear "build/soong"; then
|
||||
@ -141,6 +141,7 @@ applyPatch "$DOS_PATCHES/android_frameworks_av/385529.patch"; #R_asb_2024-03 Val
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_av/385530.patch"; #R_asb_2024-03 SoftVideoDecodeOMXComponent: validate OMX params for dynamic HDR
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_av/385531.patch"; #R_asb_2024-03 Fix out of bounds read and write in onQueueFilled in outQueue
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_av/399741.patch"; #R_asb_2024-08 StagefrightRecoder: Disabling B-frame support
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_av/401372.patch"; #S_asb_2024-09 omx: check HDR10+ info param size
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/base"; then
|
||||
@ -172,6 +173,7 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/397543.patch"; #R_asb_2024-07 F
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/399738.patch"; #R_asb_2024-08 Backport preventing BAL bypass via bound service
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/399739.patch"; #R_asb_2024-08 Restrict USB poups while setup is in progress
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/399740.patch"; #R_asb_2024-08 Hide SAW subwindows
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/401373.patch"; #S_asb_2024-09 Sanitized uri scheme by removing scheme delimiter
|
||||
git revert --no-edit 438d9feacfcad73d3ee918541574132928a93644; #Reverts "Allow signature spoofing for microG Companion/Services" in favor of below patch
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/0007-Always_Restict_Serial.patch"; #Always restrict access to Build.SERIAL (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/0008-Browser_No_Location.patch"; #Don't grant location permission to system browsers (GrapheneOS)
|
||||
@ -366,7 +368,10 @@ applyPatch "$DOS_PATCHES/android_packages_apps_PermissionController/0002-Special
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/apps/Settings"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/316891059-18.patch"; #x-asb_2024-05 Replace getCallingActivity() with getLaunchedFromPackage()
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401375.patch"; #S_asb_2024-09 Limit wifi item edit content's max length to 500
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401376-backport.patch"; #S_asb_2024-09 Replace getCallingActivity() with getLaunchedFromPackage()
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401377.patch"; #S_asb_2024-09 Ignore fragment attr from ext authenticator resource
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/401378-backport.patch"; #S_asb_2024-09 Restrict Settings Homepage prior to provisioning
|
||||
#applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0001-Captive_Portal_Toggle.patch"; #Add option to disable captive portal checks (MSe1969)
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0001-Captive_Portal_Toggle-gos.patch"; #Add option to disable captive portal checks (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0003-Remove_SensorsOff_Tile.patch"; #Remove the Sensors Off development tile (DivestOS)
|
||||
@ -433,6 +438,12 @@ applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/304614.pat
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/312102.patch"; #mnc fix (Sony)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/services/Telecomm"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/401380-backport.patch"; #S_asb_2024-09 Unbind CS if connection is not created within 15 seconds.
|
||||
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/401381.patch"; #S_asb_2024-09 Unbind CallScreeningService when timeout reached.
|
||||
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/401382.patch"; #S_asb_2024-09 Resolve cross-user image exploit for conference status hints
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/services/Telephony"; then
|
||||
if [ -d "$DOS_BUILD_BASE"/vendor/divested-carriersettings ]; then applyPatch "$DOS_PATCHES/android_packages_services_Telephony/0001-CC2.patch"; fi; #Runtime control of platform carrier config package (DivestOS)
|
||||
fi;
|
||||
|
Loading…
Reference in New Issue
Block a user