Tavi 2024-05-08 11:49:25 -04:00
parent f6ad120484
commit 59bf3b75c7
No known key found for this signature in database
GPG Key ID: E599F62ECBAEAF2E
233 changed files with 24013 additions and 120 deletions

View File

@ -68,7 +68,7 @@ external/caliper 4a0d9aba0856d0aa965d5653bfa4c138f0e8a8ba
external/cblas d063db8bdddfcde61e4bad3bfe65941fd73e8094
external/chromium-libpac 0ac78251d11006d764ba1aad8cc0867827fafe5c
external/chromium-trace 8b2c0074e71a8086dee98ca8730acfdc5eddf7a1
external/chromium-webview 3ba74728e7d0280003e37090f24fcbee46222e27
external/chromium-webview 28006ae73bf1db2470308e8b4e677539e705c015
external/clang 751a76679b0fb5798ea6cab75906df07edcab315
external/cmockery 9199c7bfafefea32d1884182fa655b6e4578c1c4
external/compiler-rt 0c46c9e892a3f68420635032ef2f6152dabd197c

View File

@ -67,7 +67,7 @@ external/capstone 6788a4139092f179005f7cdbf181ba24b60b6113
external/cblas ddf5f49cb53866fbc503a6349bf44bac24a6963d
external/chromium-libpac dff5ddb8d28f6ac9a86eb28763b4313f6f72eec5
external/chromium-trace b2cf025c7d5cebd43084f38c6c7ff9cc17da428a
external/chromium-webview 3ba74728e7d0280003e37090f24fcbee46222e27
external/chromium-webview 28006ae73bf1db2470308e8b4e677539e705c015
external/clang f9d2af42fc6d74c28893af371e4647158eaba66c
external/cmockery 9199c7bfafefea32d1884182fa655b6e4578c1c4
external/cn-cbor 7fe9f01990a97be4df5e46d2decd894c06678072

View File

@ -78,7 +78,7 @@ external/catch2 bcfbb791d09e390fb545c03ca002e570f764d960
external/cblas 61ee00692011385347a5dd1ad872556899a5cf7a
external/chromium-libpac c98fc96035e6fdc5b84d953d2bd38d2dcd175467
external/chromium-trace f4e722b911fcc6f7164026432de62a02ea3460fb
external/chromium-webview 3ba74728e7d0280003e37090f24fcbee46222e27
external/chromium-webview 28006ae73bf1db2470308e8b4e677539e705c015
external/clang 8343f599c9e1dda8e6c1bb779af323a673a052f9
external/cldr 4e0bdd442c1e01f5c6147cf6032ce4f8587f4ede
external/cmockery 9199c7bfafefea32d1884182fa655b6e4578c1c4

View File

@ -135,7 +135,7 @@ external/cblas d82c5f4ae14b2a5468303985070f7dadc15d4094
external/cbor-java f81e576298790c97498311e99a0b0b34653c3dd8
external/chromium-libpac 169c93e00a00605346a68d39d3f4713735bdb61e
external/chromium-trace e524766cad26d677a9a1ec8c00c512d4cac2cf5e
external/chromium-webview 3ba74728e7d0280003e37090f24fcbee46222e27
external/chromium-webview 28006ae73bf1db2470308e8b4e677539e705c015
external/clang 0a1c53a5d295109bd4702ad13c0f2a5510ca1b26
external/cldr 38850463abd624d5b2293be75fddc43cf6b55ae2
external/cn-cbor 696530332036f5518681d3c450cdbc3ee412004a

View File

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fraunhofer IIS FDK <audio-fdk@iis.fraunhofer.de>
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 51b4395..21c4101 100644
--- a/libSBRdec/src/lpp_tran.h
+++ b/libSBRdec/src/lpp_tran.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -207,7 +207,7 @@ typedef struct {
inverse filtering levels */
PATCH_PARAM
- patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */
+ 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

View File

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Werner Lemberg <wl@gnu.org>
Date: Sat, 19 Mar 2022 06:40:17 +0100
Subject: [PATCH] DO NOT MERGE - Cherry-pick two upstream changes
This cherry picks following two changes:
0c2bdb01a2e1d24a3e592377a6d0822856e10df2
22a0cccb4d9d002f33c1ba7a4b36812c7d4f46b5
Bug: 271680254
Test: N/A
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4ffa271ab538f57b65a65d434a2df9d3f8cd2f4a)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b0f8930701bf19229075cc930ad15813ff5fb07b)
Merged-In: I42469df8e8b07221d64e3f8574c4f30110dbda7e
Change-Id: I42469df8e8b07221d64e3f8574c4f30110dbda7e
---
src/base/ftobjs.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 2b444056c..7fdf15372 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2358,6 +2358,15 @@
#endif
+ /* only use lower 31 bits together with sign bit */
+ if ( face_index > 0 )
+ face_index &= 0x7FFFFFFFL;
+ else
+ {
+ face_index &= 0x7FFFFFFFL;
+ face_index = -face_index;
+ }
+
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE3(( "FT_Open_Face: " ));
if ( face_index < 0 )
@@ -3213,6 +3222,9 @@
if ( !face )
return FT_THROW( Invalid_Face_Handle );
+ if ( !face->size )
+ return FT_THROW( Invalid_Size_Handle );
+
if ( !req || req->width < 0 || req->height < 0 ||
req->type >= FT_SIZE_REQUEST_TYPE_MAX )
return FT_THROW( Invalid_Argument );

View File

@ -0,0 +1,386 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Seigo Nonaka <nona@google.com>
Date: Tue, 2 May 2023 10:01:38 +0900
Subject: [PATCH] Cherrypick following three changes
[cherrypick 545bf3a27] [sfnt, truetype] Add `size_reset` to `MetricsVariations`.
[cherrypick daad10810] [truetype] tt_size_reset_height to take FT_Size
[cherrypick 51ad7b243] [services] FT_Size_Reset_Func to return FT_Error
Bug: 278221085
Test: TreeHugger
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:9fe9411db4b7e715a39c0ccf48d1e0328f1d8e7c)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8d63b0bfcbaba361543fd9394b8d86907f52c97d)
Merged-In: I7e839b2a36e35c27974a82cc76e853996a7c7688
Change-Id: I7e839b2a36e35c27974a82cc76e853996a7c7688
---
include/freetype/internal/services/svmetric.h | 10 ++-
include/freetype/internal/tttypes.h | 10 ++-
src/cff/cffdrivr.c | 9 ++-
src/cff/cffobjs.c | 6 +-
src/sfnt/sfobjs.c | 14 ++--
src/sfnt/ttmtx.c | 2 +-
src/truetype/ttdriver.c | 7 +-
src/truetype/ttgxvar.c | 23 +++---
src/truetype/ttobjs.c | 70 +++++++++++--------
src/truetype/ttobjs.h | 6 +-
10 files changed, 99 insertions(+), 58 deletions(-)
diff --git a/include/freetype/internal/services/svmetric.h b/include/freetype/internal/services/svmetric.h
index 91de020bc..8eea460a0 100644
--- a/include/freetype/internal/services/svmetric.h
+++ b/include/freetype/internal/services/svmetric.h
@@ -77,6 +77,9 @@ FT_BEGIN_HEADER
typedef void
(*FT_Metrics_Adjust_Func)( FT_Face face );
+ typedef FT_Error
+ (*FT_Size_Reset_Func)( FT_Size size );
+
FT_DEFINE_SERVICE( MetricsVariations )
{
@@ -90,6 +93,7 @@ FT_BEGIN_HEADER
FT_VOrg_Adjust_Func vorg_adjust;
FT_Metrics_Adjust_Func metrics_adjust;
+ FT_Size_Reset_Func size_reset;
};
@@ -101,7 +105,8 @@ FT_BEGIN_HEADER
tsb_adjust_, \
bsb_adjust_, \
vorg_adjust_, \
- metrics_adjust_ ) \
+ metrics_adjust_, \
+ size_reset_ ) \
static const FT_Service_MetricsVariationsRec class_ = \
{ \
hadvance_adjust_, \
@@ -111,7 +116,8 @@ FT_BEGIN_HEADER
tsb_adjust_, \
bsb_adjust_, \
vorg_adjust_, \
- metrics_adjust_ \
+ metrics_adjust_, \
+ size_reset_ \
};
/* */
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 4df6b298f..fd9f02821 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1650,8 +1650,14 @@ FT_BEGIN_HEADER
void* mm;
/* a typeless pointer to the FT_Service_MetricsVariationsRec table */
- /* used to handle the HVAR, VVAR, and MVAR OpenType tables */
- void* var;
+ /* used to handle the HVAR, VVAR, and MVAR OpenType tables by the */
+ /* "truetype" driver */
+ void* tt_var;
+
+ /* a typeless pointer to the FT_Service_MetricsVariationsRec table */
+ /* used to handle the HVAR, VVAR, and MVAR OpenType tables by this */
+ /* TT_Face's driver */
+ void* face_var;
#endif
/* a typeless pointer to the PostScript Aux service */
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 997a734fb..6eaad8bbd 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -940,7 +940,8 @@
FT_UInt gindex,
FT_Int *avalue )
{
- FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var;
+ FT_Service_MetricsVariations
+ var = (FT_Service_MetricsVariations)face->tt_var;
return var->hadvance_adjust( FT_FACE( face ), gindex, avalue );
@@ -950,7 +951,8 @@
static void
cff_metrics_adjust( CFF_Face face )
{
- FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var;
+ FT_Service_MetricsVariations
+ var = (FT_Service_MetricsVariations)face->tt_var;
var->metrics_adjust( FT_FACE( face ) );
@@ -969,7 +971,8 @@
(FT_BSB_Adjust_Func) NULL, /* bsb_adjust */
(FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */
- (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */
+ (FT_Metrics_Adjust_Func) cff_metrics_adjust, /* metrics_adjust */
+ (FT_Size_Reset_Func) NULL /* size_reset */
)
#endif
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index b3f0f99e3..97d8f8e9f 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -709,8 +709,10 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
{
- FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
- FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var;
+ FT_Service_MultiMasters
+ mm = (FT_Service_MultiMasters)face->mm;
+ FT_Service_MetricsVariations
+ var = (FT_Service_MetricsVariations)face->face_var;
FT_UInt instance_index = (FT_UInt)face_index >> 16;
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 9dfc20e83..764cd23e9 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -896,17 +896,23 @@
0 );
}
- if ( !face->var )
+ if ( !face->tt_var )
{
/* we want the metrics variations interface */
/* from the `truetype' module only */
FT_Module tt_module = FT_Get_Module( library, "truetype" );
- face->var = ft_module_get_service( tt_module,
- FT_SERVICE_ID_METRICS_VARIATIONS,
- 0 );
+ face->tt_var = ft_module_get_service( tt_module,
+ FT_SERVICE_ID_METRICS_VARIATIONS,
+ 0 );
}
+
+ if ( !face->face_var )
+ face->face_var = ft_module_get_service(
+ &face->root.driver->root,
+ FT_SERVICE_ID_METRICS_VARIATIONS,
+ 0 );
#endif
FT_TRACE2(( "SFNT driver\n" ));
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 8edf4e6a3..89e1fb5a5 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -240,7 +240,7 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_Service_MetricsVariations var =
- (FT_Service_MetricsVariations)face->var;
+ (FT_Service_MetricsVariations)face->tt_var;
#endif
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index eac736c4a..22e897053 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -307,7 +307,7 @@
/* use the scaled metrics, even when tt_size_reset fails */
FT_Select_Metrics( size->face, strike_index );
- tt_size_reset( ttsize, 0 ); /* ignore return value */
+ tt_size_reset( ttsize ); /* ignore return value */
}
else
{
@@ -359,7 +359,7 @@
if ( FT_IS_SCALABLE( size->face ) )
{
- error = tt_size_reset( ttsize, 0 );
+ error = tt_size_reset( ttsize );
#ifdef TT_USE_BYTECODE_INTERPRETER
/* for the `MPS' bytecode instruction we need the point size */
@@ -523,7 +523,8 @@
(FT_BSB_Adjust_Func) NULL, /* bsb_adjust */
(FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */
- (FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */
+ (FT_Metrics_Adjust_Func) tt_apply_mvar, /* metrics_adjust */
+ (FT_Size_Reset_Func) tt_size_reset_height /* size_reset */
)
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 3df50d630..f2d2ccabb 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -1300,15 +1300,14 @@
static FT_Error
- tt_size_reset_iterator( FT_ListNode node,
+ ft_size_reset_iterator( FT_ListNode node,
void* user )
{
- TT_Size size = (TT_Size)node->data;
+ FT_Size size = (FT_Size)node->data;
+ FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)user;
- FT_UNUSED( user );
-
- tt_size_reset( size, 1 );
+ var->size_reset( size );
return FT_Err_Ok;
}
@@ -1370,6 +1369,9 @@
/* adjust all derived values */
{
+ FT_Service_MetricsVariations var =
+ (FT_Service_MetricsVariations)face->face_var;
+
FT_Face root = &face->root;
@@ -1396,11 +1398,12 @@
face->postscript.underlineThickness / 2;
root->underline_thickness = face->postscript.underlineThickness;
- /* iterate over all FT_Size objects and call `tt_size_reset' */
- /* to propagate the metrics changes */
- FT_List_Iterate( &root->sizes_list,
- tt_size_reset_iterator,
- NULL );
+ /* iterate over all FT_Size objects and call `var->size_reset' */
+ /* to propagate the metrics changes */
+ if ( var && var->size_reset )
+ FT_List_Iterate( &root->sizes_list,
+ ft_size_reset_iterator,
+ (void*)var );
}
}
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index df6c72a10..e22b6c3c7 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -1269,39 +1269,29 @@
/**************************************************************************
*
* @Function:
- * tt_size_reset
+ * tt_size_reset_height
*
* @Description:
- * Reset a TrueType size when resolutions and character dimensions
- * have been changed.
+ * Recompute a TrueType size's ascender, descender, and height
+ * when resolutions and character dimensions have been changed.
+ * Used for variation fonts as an iterator function.
*
* @Input:
- * size ::
- * A handle to the target size object.
- *
- * only_height ::
- * Only recompute ascender, descender, and height;
- * this flag is used for variation fonts where
- * `tt_size_reset' is used as an iterator function.
+ * ft_size ::
+ * A handle to the target TT_Size object. This function will be called
+ * through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This
+ * function must take `FT_Size` as a result. The passed `FT_Size` is
+ * expected to point to a `TT_Size`.
*/
FT_LOCAL_DEF( FT_Error )
- tt_size_reset( TT_Size size,
- FT_Bool only_height )
+ tt_size_reset_height( FT_Size ft_size )
{
- TT_Face face;
- FT_Size_Metrics* size_metrics;
-
-
- face = (TT_Face)size->root.face;
-
- /* nothing to do for CFF2 */
- if ( face->is_cff2 )
- return FT_Err_Ok;
+ TT_Size size = (TT_Size)ft_size;
+ TT_Face face = (TT_Face)size->root.face;
+ FT_Size_Metrics* size_metrics = &size->hinted_metrics;
size->ttmetrics.valid = FALSE;
- size_metrics = &size->hinted_metrics;
-
/* copy the result from base layer */
*size_metrics = size->root.metrics;
@@ -1328,12 +1318,34 @@
size->ttmetrics.valid = TRUE;
- if ( only_height )
- {
- /* we must not recompute the scaling values here since */
- /* `tt_size_reset' was already called (with only_height = 0) */
- return FT_Err_Ok;
- }
+ return FT_Err_Ok;
+ }
+
+
+ /**************************************************************************
+ *
+ * @Function:
+ * tt_size_reset
+ *
+ * @Description:
+ * Reset a TrueType size when resolutions and character dimensions
+ * have been changed.
+ *
+ * @Input:
+ * size ::
+ * A handle to the target size object.
+ */
+ FT_LOCAL_DEF( FT_Error )
+ tt_size_reset( TT_Size size )
+ {
+ FT_Error error;
+ TT_Face face = (TT_Face)size->root.face;
+ FT_Size_Metrics* size_metrics = &size->hinted_metrics;
+
+
+ error = tt_size_reset_height( (FT_Size)size );
+ if ( error )
+ return error;
if ( face->header.Flags & 8 )
{
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index dcff3f7a0..99895794a 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -390,8 +390,10 @@ FT_BEGIN_HEADER
#endif /* TT_USE_BYTECODE_INTERPRETER */
FT_LOCAL( FT_Error )
- tt_size_reset( TT_Size size,
- FT_Bool only_height );
+ tt_size_reset_height( FT_Size size );
+
+ FT_LOCAL( FT_Error )
+ tt_size_reset( TT_Size size );
/**************************************************************************

View File

@ -0,0 +1,171 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Antony Lee <anntzer.lee@gmail.com>
Date: Sat, 6 Apr 2019 06:37:42 +0200
Subject: [PATCH] Make `glyph_name' parameter to `FT_Get_Name_Index' a `const'.
* include/freetype/freetype.h (FT_Get_Name_Index),
include/freetype/internal/ftobjs.h (FT_Face_GetGlyphNameIndexFunc),
include/freetype/internal/services/svgldict.h
(FT_GlyphDict_NameIndexFunc), src/base/ftobjs.c (FT_Get_Name_Index),
src/cff/cffdrivr.c (cff_get_name_index), src/sfnt/sfdriver.c
(sfnt_get_name_index), src/type1/t1driver.c (t1_get_name_index),
src/type42/t42drivr.c (t42_get_name_index): Add `const' to second
argument.
Change-Id: I62a3de96a2e1c7b351fb138858ba42dc6c4f073a
---
ChangeLog | 13 +++++++++++++
include/freetype/freetype.h | 4 ++--
include/freetype/internal/ftobjs.h | 4 ++--
include/freetype/internal/services/svgldict.h | 4 ++--
src/base/ftobjs.c | 4 ++--
src/cff/cffdrivr.c | 4 ++--
src/sfnt/sfdriver.c | 4 ++--
src/type1/t1driver.c | 4 ++--
src/type42/t42drivr.c | 4 ++--
9 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 79b2c354c..75cc28207 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,19 @@
* src/sfnt/pngshim.c (Load_SBit_Png): Test bitmap size earlier.
+2019-04-06 Antony Lee <anntzer.lee@gmail.com>
+
+ Make `glyph_name' parameter to `FT_Get_Name_Index' a `const'.
+
+ * include/freetype/freetype.h (FT_Get_Name_Index),
+ include/freetype/internal/ftobjs.h (FT_Face_GetGlyphNameIndexFunc),
+ include/freetype/internal/services/svgldict.h
+ (FT_GlyphDict_NameIndexFunc), src/base/ftobjs.c (FT_Get_Name_Index),
+ src/cff/cffdrivr.c (cff_get_name_index), src/sfnt/sfdriver.c
+ (sfnt_get_name_index), src/type1/t1driver.c (t1_get_name_index),
+ src/type42/t42drivr.c (t42_get_name_index): Add `const' to second
+ argument.
+
2018-08-10 Ben Wagner <bungeman@google.com>
* src/sfnt/sfobjs.c (sfnt_done_face): Fix memory leak (#54435).
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 620df4c7a..9192baf84 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -4076,8 +4076,8 @@ FT_BEGIN_HEADER
* The glyph index. 0~means `undefined character code'.
*/
FT_EXPORT( FT_UInt )
- FT_Get_Name_Index( FT_Face face,
- FT_String* glyph_name );
+ FT_Get_Name_Index( FT_Face face,
+ const FT_String* glyph_name );
/*************************************************************************
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 88ced183f..3413b7752 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -966,8 +966,8 @@ FT_BEGIN_HEADER
FT_UInt buffer_max );
typedef FT_UInt
- (*FT_Face_GetGlyphNameIndexFunc)( FT_Face face,
- FT_String* glyph_name );
+ (*FT_Face_GetGlyphNameIndexFunc)( FT_Face face,
+ const FT_String* glyph_name );
#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
diff --git a/include/freetype/internal/services/svgldict.h b/include/freetype/internal/services/svgldict.h
index 0840b584a..9cb83c983 100644
--- a/include/freetype/internal/services/svgldict.h
+++ b/include/freetype/internal/services/svgldict.h
@@ -41,8 +41,8 @@ FT_BEGIN_HEADER
FT_UInt buffer_max );
typedef FT_UInt
- (*FT_GlyphDict_NameIndexFunc)( FT_Face face,
- FT_String* glyph_name );
+ (*FT_GlyphDict_NameIndexFunc)( FT_Face face,
+ const FT_String* glyph_name );
FT_DEFINE_SERVICE( GlyphDict )
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 7fdf15372..80253ebb2 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4040,8 +4040,8 @@
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_UInt )
- FT_Get_Name_Index( FT_Face face,
- FT_String* glyph_name )
+ FT_Get_Name_Index( FT_Face face,
+ const FT_String* glyph_name )
{
FT_UInt result = 0;
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 6eaad8bbd..7a7fd6a22 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -381,8 +381,8 @@
static FT_UInt
- cff_get_name_index( CFF_Face face,
- FT_String* glyph_name )
+ cff_get_name_index( CFF_Face face,
+ const FT_String* glyph_name )
{
CFF_Font cff;
CFF_Charset charset;
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index ae6d6cdbc..876840d3e 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -182,8 +182,8 @@
static FT_UInt
- sfnt_get_name_index( FT_Face face,
- FT_String* glyph_name )
+ sfnt_get_name_index( FT_Face face,
+ const FT_String* glyph_name )
{
TT_Face ttface = (TT_Face)face;
diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c
index 4d46e3ee6..fb9b8f1c4 100644
--- a/src/type1/t1driver.c
+++ b/src/type1/t1driver.c
@@ -70,8 +70,8 @@
static FT_UInt
- t1_get_name_index( T1_Face face,
- FT_String* glyph_name )
+ t1_get_name_index( T1_Face face,
+ const FT_String* glyph_name )
{
FT_Int i;
diff --git a/src/type42/t42drivr.c b/src/type42/t42drivr.c
index 103650315..461ca4476 100644
--- a/src/type42/t42drivr.c
+++ b/src/type42/t42drivr.c
@@ -69,8 +69,8 @@
static FT_UInt
- t42_get_name_index( T42_Face face,
- FT_String* glyph_name )
+ t42_get_name_index( T42_Face face,
+ const FT_String* glyph_name )
{
FT_Int i;

View File

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sadaf Ebrahimi <sadafebrahimi@google.com>
Date: Tue, 22 Nov 2022 22:00:13 +0000
Subject: [PATCH] Fix a bug when getting a gzip header extra field with
inflate().
If the extra field was larger than the space the user provided with
inflateGetHeader(), and if multiple calls of inflate() delivered
the extra header data, then there could be a buffer overflow of the
provided space. This commit assures that provided space is not
exceeded.
Bug: http://b/242299736
Test: TreeHugger
Change-Id: I4eabb3e135c1568e06b2b9740651a3ae11b21140
(cherry picked from commit 1c4806afd7ae034aa9f86df35d4341a0b175a90a)
Merged-In: I4eabb3e135c1568e06b2b9740651a3ae11b21140
---
src/inflate.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/inflate.c b/src/inflate.c
index ac333e8..cd01857 100644
--- a/src/inflate.c
+++ b/src/inflate.c
@@ -759,8 +759,9 @@ int flush;
if (copy > have) copy = have;
if (copy) {
if (state->head != Z_NULL &&
- state->head->extra != Z_NULL) {
- len = state->head->extra_len - state->length;
+ state->head->extra != Z_NULL &&
+ (len = state->head->extra_len - state->length) <
+ state->head->extra_max) {
zmemcpy(state->head->extra + len, next,
len + copy > state->head->extra_max ?
state->head->extra_max - len : copy);

View File

@ -0,0 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ray Essick <essick@google.com>
Date: Mon, 27 Mar 2023 18:16:46 -0500
Subject: [PATCH] Fix NuMediaExtractor::readSampleData buffer Handling
readSampleData() did not initialize buffer before filling it,
leading to OOB memory references. Correct and clarify the book
keeping around output buffer management.
Bug: 275418191
Test: CtsMediaExtractorTestCases w/debug messages
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:943fc12219b21d2a98f0ddc070b9b316a6f5d412)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:84c69bca81175feb2fd97ebb22e432ee41572786)
Merged-In: Ie744f118526f100d82a312c64f7c6fcf20773b6d
Change-Id: Ie744f118526f100d82a312c64f7c6fcf20773b6d
---
media/libstagefright/NuMediaExtractor.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 680d426d96..ddab6d3923 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -595,9 +595,11 @@ status_t NuMediaExtractor::appendVorbisNumPageSamples(
numPageSamples = -1;
}
+ // insert, including accounting for the space used.
memcpy((uint8_t *)buffer->data() + mbuf->range_length(),
&numPageSamples,
sizeof(numPageSamples));
+ buffer->setRange(buffer->offset(), buffer->size() + sizeof(numPageSamples));
uint32_t type;
const void *data;
@@ -646,6 +648,8 @@ status_t NuMediaExtractor::readSampleData(const sp<ABuffer> &buffer) {
ssize_t minIndex = fetchAllTrackSamples();
+ buffer->setRange(0, 0); // start with an empty buffer
+
if (minIndex < 0) {
return ERROR_END_OF_STREAM;
}
@@ -661,25 +665,25 @@ status_t NuMediaExtractor::readSampleData(const sp<ABuffer> &buffer) {
sampleSize += sizeof(int32_t);
}
+ // capacity() is ok since we cleared out the buffer
if (buffer->capacity() < sampleSize) {
return -ENOMEM;
}
+ const size_t srclen = it->mBuffer->range_length();
const uint8_t *src =
(const uint8_t *)it->mBuffer->data()
+ it->mBuffer->range_offset();
- memcpy((uint8_t *)buffer->data(), src, it->mBuffer->range_length());
+ memcpy((uint8_t *)buffer->data(), src, srclen);
+ buffer->setRange(0, srclen);
status_t err = OK;
if (info->mTrackFlags & kIsVorbis) {
+ // adjusts range when it inserts the extra bits
err = appendVorbisNumPageSamples(it->mBuffer, buffer);
}
- if (err == OK) {
- buffer->setRange(0, sampleSize);
- }
-
return err;
}

View File

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shruti Bihani <shrutibihani@google.com>
Date: Thu, 6 Jul 2023 08:41:56 +0000
Subject: [PATCH] Fix Segv on unknown address error flagged by fuzzer test.
The error is thrown when the destructor tries to free pointer memory.
This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error.
Bug: 245135112
Test: Build mtp_host_property_fuzzer and run on the target device
(cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d44311374e41a26b28db56794c9a7890a13a6972)
Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580
Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580
---
media/mtp/MtpProperty.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
index bfd5f7f59a..1eb8874af1 100644
--- a/media/mtp/MtpProperty.h
+++ b/media/mtp/MtpProperty.h
@@ -26,6 +26,9 @@ namespace android {
class MtpDataPacket;
struct MtpPropertyValue {
+ // pointer str initialized to NULL so that free operation
+ // is not called for pre-assigned value
+ MtpPropertyValue() : str (NULL) {}
union {
int8_t i8;
uint8_t u8;

View File

@ -0,0 +1,79 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shruti Bihani <shrutibihani@google.com>
Date: Mon, 10 Jul 2023 08:53:42 +0000
Subject: [PATCH] Fix for heap buffer overflow issue flagged by fuzzer test.
OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue.
Similar checks have been added wherever applicable on other such methods of the class.
Bug: 243463593
Test: Build mtp_packet_fuzzer and run on the target device
(cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1401a723899766632363129265b30d433ac69c44)
Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b
Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b
---
media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++---------
1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index 3b298a9bf3..e4467bbfdc 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) {
}
uint16_t MtpPacket::getUInt16(int offset) const {
- return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
+ if ((unsigned long)(offset+2) <= mBufferSize) {
+ return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
+ }
+ else {
+ ALOGE("offset for buffer read is greater than buffer size!");
+ abort();
+ }
}
uint32_t MtpPacket::getUInt32(int offset) const {
- return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
- ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
+ if ((unsigned long)(offset+4) <= mBufferSize) {
+ return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
+ ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
+ }
+ else {
+ ALOGE("offset for buffer read is greater than buffer size!");
+ abort();
+ }
}
void MtpPacket::putUInt16(int offset, uint16_t value) {
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+ if ((unsigned long)(offset+2) <= mBufferSize) {
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+ }
+ else {
+ ALOGE("offset for buffer write is greater than buffer size!");
+ }
}
void MtpPacket::putUInt32(int offset, uint32_t value) {
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
+ if ((unsigned long)(offset+4) <= mBufferSize) {
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
+ }
+ else {
+ ALOGE("offset for buffer write is greater than buffer size!");
+ }
}
uint16_t MtpPacket::getContainerCode() const {

View File

@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shruti Bihani <shrutibihani@google.com>
Date: Thu, 13 Jul 2023 09:19:08 +0000
Subject: [PATCH] Fix heap-use-after-free issue flagged by fuzzer test.
A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way.
Bug: 243381410
Test: Build mtp_handle_fuzzer and run on the target device
(cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:73d89318a658ece5f337c5f9c1ec1149c52eb722)
Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411
Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411
---
media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++
media/mtp/MtpFfsHandle.h | 4 ++++
2 files changed, 18 insertions(+)
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index bd6a6c679a..09eb96a00d 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -296,6 +296,10 @@ int MtpFfsHandle::start(bool ptp) {
}
void MtpFfsHandle::close() {
+ auto timeout = std::chrono::seconds(2);
+ std::unique_lock lk(m);
+ cv.wait_for(lk, timeout ,[this]{return child_threads==0;});
+
io_destroy(mCtx);
closeEndpoints();
closeConfig();
@@ -662,6 +666,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) {
char *temp = new char[me.length];
memcpy(temp, me.data, me.length);
me.data = temp;
+
+ std::unique_lock lk(m);
+ child_threads++;
+ lk.unlock();
+
std::thread t([this, me]() { return this->doSendEvent(me); });
t.detach();
return 0;
@@ -673,6 +682,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) {
if (static_cast<unsigned>(ret) != length)
PLOG(ERROR) << "Mtp error sending event thread!";
delete[] reinterpret_cast<char*>(me.data);
+
+ std::unique_lock lk(m);
+ child_threads--;
+ lk.unlock();
+ cv.notify_one();
}
} // namespace android
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index fe343f74f6..ae78db2877 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -58,6 +58,10 @@ protected:
bool mCanceled;
+ std::mutex m;
+ std::condition_variable cv;
+ std::atomic<int> child_threads{0};
+
android::base::unique_fd mControl;
// "in" from the host's perspective => sink for mtp server
android::base::unique_fd mBulkIn;

View File

@ -0,0 +1,104 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Toni Heidenreich <tonihei@google.com>
Date: Wed, 6 Sep 2023 12:49:33 +0000
Subject: [PATCH] httplive: fix use-after-free
Implement a mutex to ensure secure multi-threaded
access to the KeyedVector in MetaDataBase.
Concurrent access by different threads can lead
to accessing the wrong memory location due to
potential changes in the vector
Bug: 298057702
Test: HTTP Live Streaming test
(cherry picked from https://partner-android-review.googlesource.com/q/commit:a2dfb31957a9d5358d0219a0eda7dcb5b0fff5fe)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:90fb4ca425444429ada6ce0de1c13d35829bc196)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3c1d9613ef64e01d2e81c4aa44c90dcd8ca958b9)
Merged-In: I46b05c85d9c39f4ce549efc160c08a0646c9fd0a
Change-Id: I46b05c85d9c39f4ce549efc160c08a0646c9fd0a
---
media/libstagefright/foundation/MetaDataBase.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp
index bfea6f1537..a3c623e354 100644
--- a/media/libstagefright/foundation/MetaDataBase.cpp
+++ b/media/libstagefright/foundation/MetaDataBase.cpp
@@ -24,6 +24,8 @@
#include <stdlib.h>
#include <string.h>
+#include <mutex>
+
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
@@ -75,6 +77,7 @@ struct MetaDataBase::Rect {
struct MetaDataBase::MetaDataInternal {
+ std::mutex mLock;
KeyedVector<uint32_t, MetaDataBase::typed_data> mItems;
};
@@ -99,10 +102,12 @@ MetaDataBase::~MetaDataBase() {
}
void MetaDataBase::clear() {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
mInternalData->mItems.clear();
}
bool MetaDataBase::remove(uint32_t key) {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -249,6 +254,7 @@ bool MetaDataBase::setData(
uint32_t key, uint32_t type, const void *data, size_t size) {
bool overwrote_existing = true;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
typed_data item;
@@ -266,6 +272,7 @@ bool MetaDataBase::setData(
bool MetaDataBase::findData(uint32_t key, uint32_t *type,
const void **data, size_t *size) const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -280,6 +287,7 @@ bool MetaDataBase::findData(uint32_t key, uint32_t *type,
}
bool MetaDataBase::hasData(uint32_t key) const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -426,6 +434,7 @@ static void MakeFourCCString(uint32_t x, char *s) {
String8 MetaDataBase::toString() const {
String8 s;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
for (int i = mInternalData->mItems.size(); --i >= 0;) {
int32_t key = mInternalData->mItems.keyAt(i);
char cc[5];
@@ -440,6 +449,7 @@ String8 MetaDataBase::toString() const {
}
void MetaDataBase::dumpToLog() const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
for (int i = mInternalData->mItems.size(); --i >= 0;) {
int32_t key = mInternalData->mItems.keyAt(i);
char cc[5];
@@ -451,6 +461,7 @@ void MetaDataBase::dumpToLog() const {
status_t MetaDataBase::writeToParcel(Parcel &parcel) {
status_t ret;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
size_t numItems = mInternalData->mItems.size();
ret = parcel.writeUint32(uint32_t(numItems));
if (ret) {

View File

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Harish Mahendrakar <harish.mahendrakar@ittiam.com>
Date: Mon, 28 Aug 2023 17:35:56 +0000
Subject: [PATCH] Codec2BufferUtils: Use cropped dimensions in RGB to YUV
conversion
Bug: 283099444
Test: poc in the bug
(cherry picked from https://partner-android-review.googlesource.com/q/commit:3875b858a347e25db94574e6362798a849bf9ebd)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4eba80f6698cb2d7aa48ea4f7728dbdf11f29fd3)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d83225b43057dd25deb5083772e6ebc2f5e5253b)
Merged-In: I42c71616c9d50f61c92f461f6a91f5addb1d724a
Change-Id: I42c71616c9d50f61c92f461f6a91f5addb1d724a
---
media/codec2/sfplugin/utils/Codec2BufferUtils.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index bf2a07ee52..9bc8eb9c4c 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -361,8 +361,8 @@ status_t ConvertRGBToPlanarYUV(
const uint8_t *pBlue = src.data()[C2PlanarLayout::PLANE_B];
#define CLIP3(x,y,z) (((z) < (x)) ? (x) : (((z) > (y)) ? (y) : (z)))
- for (size_t y = 0; y < src.height(); ++y) {
- for (size_t x = 0; x < src.width(); ++x) {
+ for (size_t y = 0; y < src.crop().height; ++y) {
+ for (size_t x = 0; x < src.crop().width; ++x) {
uint8_t red = *pRed;
uint8_t green = *pGreen;
uint8_t blue = *pBlue;

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Songyue Han <songyueh@google.com>
Date: Tue, 3 Oct 2023 22:40:14 +0000
Subject: [PATCH] Fix convertYUV420Planar16ToY410 overflow issue for
unsupported cropwidth.
Bug: 300476626
Test: color_conversion_fuzzer
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:de2ad0fad97d6d97d1e01f0e8d8309536eb268b4)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:745ab99f7343bc236b88b9d63cd7b06ab192f9e9)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:aa8298ec8eb903e1e3dd915fa24f32e1aea1f76c)
Merged-In: I8631426188af3c5f9b6c1ff6a0039254c252f733
Change-Id: I8631426188af3c5f9b6c1ff6a0039254c252f733
---
media/libstagefright/colorconversion/ColorConverter.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index d685321028..c491d8043b 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -648,7 +648,8 @@ status_t ColorConverter::convertYUV420Planar16ToY410(
uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
size_t x = 0;
- for (; x < src.cropWidth() - 3; x += 4) {
+ // x % 4 is always 0 so x + 3 will never overflow.
+ for (; x + 3 < src.cropWidth(); x += 4) {
u01 = *((uint32_t*)ptr_u); ptr_u += 2;
v01 = *((uint32_t*)ptr_v); ptr_v += 2;

View File

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ashish Kumar Gupta <kumarashishg@google.com>
Date: Tue, 21 Nov 2023 08:48:43 +0530
Subject: [PATCH] Update mtp packet buffer
Currently, the buffer size is not changed when the packet size is increased. Ideally, the buffer size should be larger than the packet size. In our case, when the packet size is increased, we must reallocate the buffer of MTP packet.
Bug: 300007708
Test: build and flash the device. Check MTP works
Test: run fuzzer locally
(cherry picked from commit e1494a2d8e7eee25d7ea5469be43740e97294c99)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5c0f99beb6fa5ff920caf5b0d06aaebc8e9eab24)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:edf60c63243903b9f27f58f4954c599470d011fd)
Merged-In: I98398a9e15962e6d5f08445ee7b17f5d61a3a528
Change-Id: I98398a9e15962e6d5f08445ee7b17f5d61a3a528
---
media/mtp/MtpPacket.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index e4467bbfdc..87c5c0495b 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -168,8 +168,10 @@ void MtpPacket::setParameter(int index, uint32_t value) {
return;
}
int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t);
- if (mPacketSize < offset + sizeof(uint32_t))
+ if (mPacketSize < offset + sizeof(uint32_t)) {
mPacketSize = offset + sizeof(uint32_t);
+ allocate(mPacketSize);
+ }
putUInt32(offset, value);
}

View File

@ -0,0 +1,105 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Haripriya Deshmukh <haripriya.deshmukh@ittiam.com>
Date: Tue, 19 Sep 2023 20:42:45 +0000
Subject: [PATCH] Validate OMX Params for VPx encoders
Bug: 273936274
Bug: 273937171
Bug: 273937136
Bug: 273936553
Bug: 273936601
Test: POC in bug descriptions
(cherry picked from https://partner-android-review.googlesource.com/q/commit:022086b76536cd2e19a44053271190bdf6e181f7)
(cherry picked from commit 0e4ca1cb5c16af8f1dfb0ae41941c16c104d38e8)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:90641b2799fd3940cdf0bf8a73b2f76839e651a6)
Merged-In: I9bb17112d9f0217b6af0343afecc9c943453b757
Change-Id: I9bb17112d9f0217b6af0343afecc9c943453b757
---
media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp | 10 ++++++++++
media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp | 10 ++++++++++
media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 9 +++++++++
3 files changed, 29 insertions(+)
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
index 04737a9ccf..9198b7c327 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
@@ -120,6 +120,11 @@ OMX_ERRORTYPE SoftVP8Encoder::internalSetParameter(OMX_INDEXTYPE index,
OMX_ERRORTYPE SoftVP8Encoder::internalGetVp8Params(
OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
+ if (!isValidOMXParam(vp8Params)) {
+ android_errorWriteLog(0x534e4554, "273936274");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp8Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
@@ -133,6 +138,11 @@ OMX_ERRORTYPE SoftVP8Encoder::internalGetVp8Params(
OMX_ERRORTYPE SoftVP8Encoder::internalSetVp8Params(
const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
+ if (!isValidOMXParam(vp8Params)) {
+ android_errorWriteLog(0x534e4554, "273937171");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp8Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
index 1ea1c85f76..f8495c2da4 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
@@ -119,6 +119,11 @@ OMX_ERRORTYPE SoftVP9Encoder::internalSetParameter(
OMX_ERRORTYPE SoftVP9Encoder::internalGetVp9Params(
OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
+ if (!isValidOMXParam(vp9Params)) {
+ android_errorWriteLog(0x534e4554, "273936553");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp9Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
@@ -133,6 +138,11 @@ OMX_ERRORTYPE SoftVP9Encoder::internalGetVp9Params(
OMX_ERRORTYPE SoftVP9Encoder::internalSetVp9Params(
const OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
+ if (!isValidOMXParam(vp9Params)) {
+ android_errorWriteLog(0x534e4554, "273937136");
+ return OMX_ErrorBadParameter;
+ }
+
if (vp9Params->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index d0cb0718c2..054413e7c0 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -485,6 +485,11 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams(
OMX_ERRORTYPE SoftVPXEncoder::internalGetAndroidVpxParams(
OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
+ if (!isValidOMXParam(vpxAndroidParams)) {
+ android_errorWriteLog(0x534e4554, "273936601");
+ return OMX_ErrorBadParameter;
+ }
+
if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
@@ -501,6 +506,10 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetAndroidVpxParams(
OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVpxParams(
const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
+ if (!isValidOMXParam(vpxAndroidParams)) {
+ android_errorWriteLog(0x534e4554, "273937551");
+ return OMX_ErrorBadParameter;
+ }
if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}

View File

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Harish Mahendrakar <harish.mahendrakar@ittiam.com>
Date: Mon, 30 Oct 2023 20:38:56 +0000
Subject: [PATCH] SoftVideoDecodeOMXComponent: validate OMX params for dynamic
HDR
Bug: 273935108
Bug: 281065553
(cherry picked from https://partner-android-review.googlesource.com/q/commit:b2c67bdcf57149a5e19a04466205266dc543fd86)
(cherry picked from commit a542f2c50700ca6df93e966fe8d4c468e1a15d9a)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:80e0acc096d201e80a1b65af944b1e47c9dd6f7b)
Merged-In: I707745594a9196d8d85d4c4bb498eba3c6198b42
Change-Id: I707745594a9196d8d85d4c4bb498eba3c6198b42
---
media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index e853da9763..418302389d 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -616,6 +616,10 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig(
DescribeHDR10PlusInfoParams* outParams =
(DescribeHDR10PlusInfoParams *)params;
+ if (!isValidOMXParam(outParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
outParams->nParamSizeUsed = info->size();
// If the buffer provided by the client does not have enough
@@ -694,6 +698,10 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetConfig(
const DescribeHDR10PlusInfoParams* inParams =
(DescribeHDR10PlusInfoParams *)params;
+ if (!isValidOMXParam(inParams)) {
+ return OMX_ErrorBadParameter;
+ }
+
if (*frameConfig) {
// This is a request to append to the current frame config set.
// For now, we only support kDescribeHdr10PlusInfoIndex, which

View File

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Haripriya Deshmukh <haripriya.deshmukh@ittiam.com>
Date: Tue, 5 Dec 2023 18:32:38 +0000
Subject: [PATCH] Fix out of bounds read and write in onQueueFilled in outQueue
Bug: 276442130
Test: POC in bug descriptions
(cherry picked from https://partner-android-review.googlesource.com/q/commit:7aef41e59412e2f95bab5de7e33f5f04bb808643)
(cherry picked from commit 8f4cfda9fc75f1e9ba3b6dee3fbffda4b6111d64)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:208e430bc6380fafafca8041b239f835263a9d47)
Merged-In: Ic230d10048193a785f185dc6a7de6f455f9318c1
Change-Id: Ic230d10048193a785f185dc6a7de6f455f9318c1
---
media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 60750d9a61..db08030ad1 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -312,8 +312,11 @@ void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) {
outHeader->nFilledLen = frameSize;
List<BufferInfo *>::iterator it = outQueue.begin();
- while ((*it)->mHeader != outHeader) {
- ++it;
+ while (it != outQueue.end() && (*it)->mHeader != outHeader) {
+ ++it;
+ }
+ if (it == outQueue.end()) {
+ return;
}
BufferInfo *outInfo = *it;

View File

@ -22,7 +22,7 @@ index a8dd041454c9..6940b9eb36ed 100644
<!-- Allows applications to access information about networks.
<p>Protection level: normal
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 4649b88b9804..feaa92d0f615 100644
index 65646aef6c9e..adf6fa87be3e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1024,7 +1024,7 @@ public class PermissionManagerService {

View File

@ -34,7 +34,7 @@ index b99634c11742..d74627f45dbd 100644
field public static final String SENSORS = "android.permission-group.SENSORS";
field public static final String SMS = "android.permission-group.SMS";
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7f728febe5d9..f9f3ead23fb8 100644
index 3da6255ff7e0..ff520f7a38f7 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -288,6 +288,8 @@ public class PackageParser {
@ -100,7 +100,7 @@ index 2cf2b923ef90..ae206c1f5872 100644
<string name="permlab_readCalendar">Read calendar events and details</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index feaa92d0f615..ce9ceb573a39 100644
index adf6fa87be3e..648502f7ba02 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1024,7 +1024,7 @@ public class PermissionManagerService {

View File

@ -25,7 +25,7 @@ index d27b5ad0d646..32b022455451 100644
Process.SYSTEM_UID, userId, delayingPermCallback);
// Allow app op later as we are holding mPackages
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 9f8e6eae3ba8..4649b88b9804 100644
index 2fcdec7c92d6..65646aef6c9e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1023,6 +1023,10 @@ public class PermissionManagerService {

View File

@ -25,7 +25,7 @@ Change-Id: I64a252aac9bb196a11ed7b4b5d8c7e59a3413bd4
3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f9f3ead23fb8..1da73e46f81d 100644
index ff520f7a38f7..21d683f0eed1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6348,6 +6348,38 @@ public class PackageParser {

View File

@ -0,0 +1,140 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexander Grund <flamefire89@gmail.com>
Date: Sun, 26 Mar 2023 17:36:03 +0200
Subject: [PATCH] Revert "[RESTRICT AUTOMERGE] Trim the activity info of
another uid if no privilege"
This reverts commit bff14ff38a014fc3059c6bfe8a16aec9f5447554.
Reason for revert: apps crashed due to the top activity info trimmed
Bug: 264269392 263434196 263438172
Change-Id: I078080b14b7cf7c6e605739f22f40f86802d3950
(cherry picked from commit 5caf2dde3d264966e1ba0dd3e18a0524858157ba)
Merged-In: I078080b14b7cf7c6e605739f22f40f86802d3950
---
.../com/android/server/wm/AppTaskImpl.java | 3 +-
.../com/android/server/wm/RecentTasks.java | 7 ++--
.../com/android/server/wm/RunningTasks.java | 8 ++---
.../com/android/server/wm/TaskRecord.java | 34 -------------------
4 files changed, 5 insertions(+), 47 deletions(-)
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 900b59e0a8a2..1eb7455135c7 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -84,8 +84,7 @@ class AppTaskImpl extends IAppTask.Stub {
if (tr == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
- return mService.getRecentTasks().createRecentTaskInfo(tr,
- true /* getTasksAllowed */);
+ return mService.getRecentTasks().createRecentTaskInfo(tr);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 56367f42886d..541a8bbc8865 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -944,7 +944,7 @@ class RecentTasks {
continue;
}
- final ActivityManager.RecentTaskInfo rti = createRecentTaskInfo(tr, getTasksAllowed);
+ final ActivityManager.RecentTaskInfo rti = createRecentTaskInfo(tr);
if (!getDetailedTasks) {
rti.baseIntent.replaceExtras((Bundle) null);
}
@@ -1715,15 +1715,12 @@ class RecentTasks {
/**
* Creates a new RecentTaskInfo from a TaskRecord.
*/
- ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr, boolean getTasksAllowed) {
+ ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
tr.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
- if (!getTasksAllowed) {
- TaskRecord.trimIneffectiveInfo(tr, rti);
- }
return rti;
}
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 3c2e36cf245d..81a85476c53a 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -69,7 +69,7 @@ class RunningTasks {
}
final TaskRecord task = iter.next();
- list.add(createRunningTaskInfo(task, allowed));
+ list.add(createRunningTaskInfo(task));
maxNum--;
}
}
@@ -77,15 +77,11 @@ class RunningTasks {
/**
* Constructs a {@link RunningTaskInfo} from a given {@param task}.
*/
- private RunningTaskInfo createRunningTaskInfo(TaskRecord task, boolean allowed) {
+ private RunningTaskInfo createRunningTaskInfo(TaskRecord task) {
final RunningTaskInfo rti = new RunningTaskInfo();
task.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.taskId;
-
- if (!allowed) {
- TaskRecord.trimIneffectiveInfo(task, rti);
- }
return rti;
}
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 9de4c8121e4d..361f66e3106a 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -2436,40 +2436,6 @@ class TaskRecord extends ConfigurationContainer {
info.configuration.setTo(getConfiguration());
}
- /**
- * Removes the activity info if the activity belongs to a different uid, which is
- * different from the app that hosts the task.
- */
- static void trimIneffectiveInfo(TaskRecord task, TaskInfo info) {
- int topActivityUid = task.effectiveUid;
- for (int i = task.mActivities.size() - 1; i >= 0; --i) {
- final ActivityRecord r = task.mActivities.get(i);
- if (r.finishing || r.isState(ActivityState.INITIALIZING)) {
- continue;
- }
- topActivityUid = r.info.applicationInfo.uid;
- break;
- }
-
- if (task.effectiveUid != topActivityUid) {
- info.topActivity = null;
- }
-
- int baseActivityUid = task.effectiveUid;
- for (int i = 0; i < task.mActivities.size(); ++i) {
- final ActivityRecord r = task.mActivities.get(i);
- if (r.finishing) {
- continue;
- }
- baseActivityUid = r.info.applicationInfo.uid;
- break;
- }
-
- if (task.effectiveUid != baseActivityUid) {
- info.baseActivity = null;
- }
- }
-
/**
* Returns a {@link TaskInfo} with information from this task.
*/

View File

@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Julia Reynolds <juliacr@google.com>
Date: Mon, 16 May 2022 15:28:24 -0400
Subject: [PATCH] Move service initialization
Occasionally ILockSettings can fail to be initialized otherwise
Fixes: 232714129
Test: boot (and eventually bootstress/reboot-long)
Change-Id: I2f9f9bdba37f4ebfaea56c1a6662f0474ae8a002
Merged-In: I2f9f9bdba37f4ebfaea56c1a6662f0474ae8a002
(cherry picked from commit 0340c219c094cbd0a07600eac471cfeeaceba60e)
---
.../server/notification/NotificationManagerService.java | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 347811d82862..c9831781b543 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1567,7 +1567,6 @@ public class NotificationManagerService extends SystemService {
}
}
- private LockPatternUtils mLockPatternUtils;
private StrongAuthTracker mStrongAuthTracker;
public NotificationManagerService(Context context) {
@@ -1761,7 +1760,6 @@ public class NotificationManagerService extends SystemService {
mHandler = new WorkerHandler(looper);
mRankingThread.start();
- mLockPatternUtils = new LockPatternUtils(getContext());
mStrongAuthTracker = new StrongAuthTracker(getContext());
String[] extractorNames;
try {
@@ -2059,7 +2057,7 @@ public class NotificationManagerService extends SystemService {
mRoleObserver = new RoleObserver(getContext().getSystemService(RoleManager.class),
mPackageManager, getContext().getMainExecutor());
mRoleObserver.init();
- mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
+ new LockPatternUtils(getContext()).registerStrongAuthTracker(mStrongAuthTracker);
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
// This observer will force an update when observe is called, causing us to
// bind to listener services.

View File

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Johnston <acjohnston@google.com>
Date: Tue, 5 Oct 2021 11:44:37 +0000
Subject: [PATCH] Stop managed profile owner granting READ_SMS
Reason: There is only one telephony stack shared
between the personal and work profile.
Bug: 194382185
Bug: 189942529
Test: build
Change-Id: If0d27a317a7c0ee46af371b30208327e5636c7cf
(cherry picked from commit 87f37319bf7ee22c6e7c29432b6c9bbce0fdb591)
Merged-In: If0d27a317a7c0ee46af371b30208327e5636c7cf
---
core/java/android/app/admin/DevicePolicyManager.java | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 08e6ff318fbc..5e263b0d05b6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8836,6 +8836,15 @@ public class DevicePolicyManager {
* {@link android.os.Build.VERSION_CODES#M} the app-op matching the permission is set to
* {@link android.app.AppOpsManager#MODE_IGNORED}, but the permission stays granted.
*
+ * Control over the following permissions are restricted for managed profile owners:
+ * <ul>
+ * <li>Manifest.permission.READ_SMS</li>
+ * </ul>
+ * <p>
+ * A managed profile owner may not grant these permissions (i.e. call this method with any of
+ * the permissions listed above and {@code grantState} of
+ * {@code #PERMISSION_GRANT_STATE_GRANTED}), but may deny them.
+ *
* @param admin Which profile or device owner this request is associated with.
* @param packageName The application to grant or revoke a permission to.
* @param permission The permission to grant or revoke.

View File

@ -0,0 +1,512 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Wenhao Wang <wenhaowang@google.com>
Date: Tue, 30 Aug 2022 11:09:46 -0700
Subject: [PATCH] Enable user graularity for lockdown mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The NotificationManagerService registers a LockPatternUtils.StrongAuthTracker
to observe the StrongAuth changes of every user.
More specifically, its the STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN flag.
Via this flag, NotificationManagerService can perform the following operations
when the user enter or exit lockdown mode:
Enter lockdown:
1. Remove all the notifications belonging to the user.
2. Set the local flag to indicate the lockdown is on for the user.
The local flag will suppress the user's notifications on the
post, remove and update functions.
Exit lockdown:
1. Clear the local flag to indicate the lockdown is off for the user.
2. Repost the users notifications (suppressed during lockdown mode).
The CL also updates corresponding tests.
Bug: 173721373
Bug: 250743174
Test: atest NotificationManagerServiceTest
Test: atest NotificationListenersTest
Ignore-AOSP-First: pending fix for a security issue.
Change-Id: I4f30e56550729db7d673a92d2a1250509713f36d
Merged-In: I4f30e56550729db7d673a92d2a1250509713f36d
(cherry picked from commit de3b12fca23178d8c821058261572449b67d5967)
(cherry picked from commit 5e40f39f5bd4ae769d79ce022a64f1345512b65d)
Merged-In: I4f30e56550729db7d673a92d2a1250509713f36d
---
.../NotificationManagerService.java | 75 ++++++----
.../NotificationListenersTest.java | 136 ++++++++++++------
.../NotificationManagerServiceTest.java | 64 ++++++++-
3 files changed, 197 insertions(+), 78 deletions(-)
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c9831781b543..7ae80d927aaa 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1535,34 +1535,39 @@ public class NotificationManagerService extends SystemService {
return (haystack & needle) != 0;
}
- public boolean isInLockDownMode() {
- return mIsInLockDownMode;
+ // Return whether the user is in lockdown mode.
+ // If the flag is not set, we assume the user is not in lockdown.
+ public boolean isInLockDownMode(int userId) {
+ return mUserInLockDownMode.get(userId, false);
}
@Override
public synchronized void onStrongAuthRequiredChanged(int userId) {
boolean userInLockDownModeNext = containsFlag(getStrongAuthForUser(userId),
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- mUserInLockDownMode.put(userId, userInLockDownModeNext);
- boolean isInLockDownModeNext = mUserInLockDownMode.indexOfValue(true) != -1;
- if (mIsInLockDownMode == isInLockDownModeNext) {
+ // Nothing happens if the lockdown mode of userId keeps the same.
+ if (userInLockDownModeNext == isInLockDownMode(userId)) {
return;
}
- if (isInLockDownModeNext) {
- cancelNotificationsWhenEnterLockDownMode();
+ // When the lockdown mode is changed, we perform the following steps.
+ // If the userInLockDownModeNext is true, all the function calls to
+ // notifyPostedLocked and notifyRemovedLocked will not be executed.
+ // The cancelNotificationsWhenEnterLockDownMode calls notifyRemovedLocked
+ // and postNotificationsWhenExitLockDownMode calls notifyPostedLocked.
+ // So we shall call cancelNotificationsWhenEnterLockDownMode before
+ // we set mUserInLockDownMode as true.
+ // On the other hand, if the userInLockDownModeNext is false, we shall call
+ // postNotificationsWhenExitLockDownMode after we put false into mUserInLockDownMode
+ if (userInLockDownModeNext) {
+ cancelNotificationsWhenEnterLockDownMode(userId);
}
- // When the mIsInLockDownMode is true, both notifyPostedLocked and
- // notifyRemovedLocked will be dismissed. So we shall call
- // cancelNotificationsWhenEnterLockDownMode before we set mIsInLockDownMode
- // as true and call postNotificationsWhenExitLockDownMode after we set
- // mIsInLockDownMode as false.
- mIsInLockDownMode = isInLockDownModeNext;
+ mUserInLockDownMode.put(userId, userInLockDownModeNext);
- if (!isInLockDownModeNext) {
- postNotificationsWhenExitLockDownMode();
+ if (!userInLockDownModeNext) {
+ postNotificationsWhenExitLockDownMode(userId);
}
}
}
@@ -7579,11 +7584,14 @@ public class NotificationManagerService extends SystemService {
}
}
- private void cancelNotificationsWhenEnterLockDownMode() {
+ private void cancelNotificationsWhenEnterLockDownMode(int userId) {
synchronized (mNotificationLock) {
int numNotifications = mNotificationList.size();
for (int i = 0; i < numNotifications; i++) {
NotificationRecord rec = mNotificationList.get(i);
+ if (rec.getUser().getIdentifier() != userId) {
+ continue;
+ }
mListeners.notifyRemovedLocked(rec, REASON_CANCEL_ALL,
rec.getStats());
}
@@ -7591,14 +7599,23 @@ public class NotificationManagerService extends SystemService {
}
}
- private void postNotificationsWhenExitLockDownMode() {
+ private void postNotificationsWhenExitLockDownMode(int userId) {
synchronized (mNotificationLock) {
int numNotifications = mNotificationList.size();
+ // Set the delay to spread out the burst of notifications.
+ long delay = 0;
for (int i = 0; i < numNotifications; i++) {
NotificationRecord rec = mNotificationList.get(i);
- mListeners.notifyPostedLocked(rec, rec);
+ if (rec.getUser().getIdentifier() != userId) {
+ continue;
+ }
+ mHandler.postDelayed(() -> {
+ synchronized (mNotificationLock) {
+ mListeners.notifyPostedLocked(rec, rec);
+ }
+ }, delay);
+ delay += 20;
}
-
}
}
@@ -7777,12 +7794,15 @@ public class NotificationManagerService extends SystemService {
* notifications visible to the given listener.
*/
@GuardedBy("mNotificationLock")
- private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
+ NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
final int N = mNotificationList.size();
final ArrayList<NotificationListenerService.Ranking> rankings = new ArrayList<>();
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
+ if (isInLockDownMode(record.getUser().getIdentifier())) {
+ continue;
+ }
if (!isVisibleToListener(record.sbn, info)) {
continue;
}
@@ -7818,8 +7838,8 @@ public class NotificationManagerService extends SystemService {
rankings.toArray(new NotificationListenerService.Ranking[0]));
}
- boolean isInLockDownMode() {
- return mStrongAuthTracker.isInLockDownMode();
+ boolean isInLockDownMode(int userId) {
+ return mStrongAuthTracker.isInLockDownMode(userId);
}
boolean hasCompanionDevice(ManagedServiceInfo info) {
@@ -7854,7 +7874,8 @@ public class NotificationManagerService extends SystemService {
ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));
}
- private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
+ @VisibleForTesting
+ boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
if (!listener.enabledAndUserMatches(sbn.getUserId())) {
return false;
}
@@ -8454,7 +8475,7 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
boolean notifyAllListeners) {
- if (isInLockDownMode()) {
+ if (isInLockDownMode(r.getUser().getIdentifier())) {
return;
}
@@ -8520,7 +8541,7 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
public void notifyRemovedLocked(NotificationRecord r, int reason,
NotificationStats notificationStats) {
- if (isInLockDownMode()) {
+ if (isInLockDownMode(r.getUser().getIdentifier())) {
return;
}
@@ -8575,10 +8596,6 @@ public class NotificationManagerService extends SystemService {
*/
@GuardedBy("mNotificationLock")
public void notifyRankingUpdateLocked(List<NotificationRecord> changedHiddenNotifications) {
- if (isInLockDownMode()) {
- return;
- }
-
boolean isHiddenRankingUpdate = changedHiddenNotifications != null
&& changedHiddenNotifications.size() > 0;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index 793739bfe8f5..66bacbbe7ed1 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;
import android.app.INotificationManager;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.testing.TestableContext;
@@ -40,8 +41,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.internal.util.reflection.FieldSetter;
-import java.util.List;
-
public class NotificationListenersTest extends UiServiceTestCase {
@Mock
@@ -70,66 +69,117 @@ public class NotificationListenersTest extends UiServiceTestCase {
@Test
public void testNotifyPostedLockedInLockdownMode() {
- NotificationRecord r = mock(NotificationRecord.class);
- NotificationRecord old = mock(NotificationRecord.class);
+ NotificationRecord r0 = mock(NotificationRecord.class);
+ NotificationRecord old0 = mock(NotificationRecord.class);
+ UserHandle uh0 = mock(UserHandle.class);
+
+ NotificationRecord r1 = mock(NotificationRecord.class);
+ NotificationRecord old1 = mock(NotificationRecord.class);
+ UserHandle uh1 = mock(UserHandle.class);
+
+ // Neither user0 and user1 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(false);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+
+ mListeners.notifyPostedLocked(r0, old0, true);
+ mListeners.notifyPostedLocked(r0, old0, false);
+ verify(mListeners, times(2)).getServices();
- // before the lockdown mode
- when(mNm.isInLockDownMode()).thenReturn(false);
- mListeners.notifyPostedLocked(r, old, true);
- mListeners.notifyPostedLocked(r, old, false);
+ mListeners.notifyPostedLocked(r1, old1, true);
+ mListeners.notifyPostedLocked(r1, old1, false);
verify(mListeners, times(2)).getServices();
- // in the lockdown mode
- reset(r);
- reset(old);
+ // Reset
+ reset(r0);
+ reset(old0);
+ reset(r1);
+ reset(old1);
reset(mListeners);
- when(mNm.isInLockDownMode()).thenReturn(true);
- mListeners.notifyPostedLocked(r, old, true);
- mListeners.notifyPostedLocked(r, old, false);
+
+ // Only user 0 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(true);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+
+ mListeners.notifyPostedLocked(r0, old0, true);
+ mListeners.notifyPostedLocked(r0, old0, false);
verify(mListeners, never()).getServices();
- }
- @Test
- public void testnotifyRankingUpdateLockedInLockdownMode() {
- List chn = mock(List.class);
-
- // before the lockdown mode
- when(mNm.isInLockDownMode()).thenReturn(false);
- mListeners.notifyRankingUpdateLocked(chn);
- verify(chn, times(1)).size();
-
- // in the lockdown mode
- reset(chn);
- when(mNm.isInLockDownMode()).thenReturn(true);
- mListeners.notifyRankingUpdateLocked(chn);
- verify(chn, never()).size();
+ mListeners.notifyPostedLocked(r1, old1, true);
+ mListeners.notifyPostedLocked(r1, old1, false);
+ verify(mListeners, times(2)).getServices();
}
@Test
public void testNotifyRemovedLockedInLockdownMode() throws NoSuchFieldException {
+ NotificationRecord r0 = mock(NotificationRecord.class);
+ NotificationStats rs0 = mock(NotificationStats.class);
+ UserHandle uh0 = mock(UserHandle.class);
+
+ NotificationRecord r1 = mock(NotificationRecord.class);
+ NotificationStats rs1 = mock(NotificationStats.class);
+ UserHandle uh1 = mock(UserHandle.class);
+
StatusBarNotification sbn = mock(StatusBarNotification.class);
- NotificationRecord r = mock(NotificationRecord.class);
- NotificationStats rs = mock(NotificationStats.class);
- FieldSetter.setField(r,
+ FieldSetter.setField(r0,
+ NotificationRecord.class.getDeclaredField("sbn"),
+ sbn);
+ FieldSetter.setField(r1,
NotificationRecord.class.getDeclaredField("sbn"),
sbn);
FieldSetter.setField(mNm,
NotificationManagerService.class.getDeclaredField("mHandler"),
mock(NotificationManagerService.WorkerHandler.class));
- // before the lockdown mode
- when(mNm.isInLockDownMode()).thenReturn(false);
- mListeners.notifyRemovedLocked(r, 0, rs);
- mListeners.notifyRemovedLocked(r, 0, rs);
- verify(sbn, times(2)).cloneLight();
+ // Neither user0 and user1 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(false);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
+ verify(sbn, atLeast(2)).cloneLight();
- // in the lockdown mode
reset(sbn);
- reset(r);
- reset(rs);
- when(mNm.isInLockDownMode()).thenReturn(true);
- mListeners.notifyRemovedLocked(r, 0, rs);
- mListeners.notifyRemovedLocked(r, 0, rs);
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ verify(sbn, atLeast(2)).cloneLight();
+
+ // Reset
+ reset(sbn);
+ reset(r0);
+ reset(rs0);
+ reset(r1);
+ reset(rs1);
+
+ // Only user 0 is in the lockdown mode
+ when(r0.getUser()).thenReturn(uh0);
+ when(uh0.getIdentifier()).thenReturn(0);
+ when(mNm.isInLockDownMode(0)).thenReturn(true);
+
+ when(r1.getUser()).thenReturn(uh1);
+ when(uh1.getIdentifier()).thenReturn(1);
+ when(mNm.isInLockDownMode(1)).thenReturn(false);
+
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
+ mListeners.notifyRemovedLocked(r0, 0, rs0);
verify(sbn, never()).cloneLight();
+
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ mListeners.notifyRemovedLocked(r1, 0, rs1);
+ verify(sbn, atLeast(2)).cloneLight();
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 5030e124e4ce..6c1620751866 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -124,6 +124,7 @@ import android.provider.MediaStore;
import android.provider.Settings;
import android.service.notification.Adjustment;
import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationRankingUpdate;
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenPolicy;
@@ -149,6 +150,7 @@ import com.android.server.SystemService;
import com.android.server.UiServiceTestCase;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
+import com.android.server.notification.ManagedServices.ManagedServiceInfo;
import com.android.server.notification.NotificationManagerService.NotificationAssistants;
import com.android.server.notification.NotificationManagerService.NotificationListeners;
import com.android.server.pm.PackageManagerService;
@@ -264,6 +266,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Nullable
NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
+ @Nullable
+ Boolean mIsVisibleToListenerReturnValue = null;
+
TestableNotificationManagerService(Context context) {
super(context);
}
@@ -333,6 +338,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
return true;
}
+ protected void setIsVisibleToListenerReturnValue(boolean value) {
+ mIsVisibleToListenerReturnValue = value;
+ }
+
+ @Override
+ boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
+ if (mIsVisibleToListenerReturnValue != null) {
+ return mIsVisibleToListenerReturnValue;
+ }
+ return super.isVisibleToListener(sbn, listener);
+ }
+
class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
private int mGetStrongAuthForUserReturnValue = 0;
StrongAuthTrackerFake(Context context) {
@@ -5607,10 +5624,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
- assertTrue(mStrongAuthTracker.isInLockDownMode());
- mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+ assertTrue(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
+ mStrongAuthTracker.setGetStrongAuthForUserReturnValue(mContext.getUserId());
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
- assertFalse(mStrongAuthTracker.isInLockDownMode());
+ assertFalse(mStrongAuthTracker.isInLockDownMode(mContext.getUserId()));
}
@Test
@@ -5626,8 +5643,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// when entering the lockdown mode, cancel the 2 notifications.
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
- assertTrue(mStrongAuthTracker.isInLockDownMode());
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertTrue(mStrongAuthTracker.isInLockDownMode(0));
// the notifyRemovedLocked function is called twice due to REASON_LOCKDOWN.
ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
@@ -5636,9 +5653,44 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// exit lockdown mode.
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
- mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertFalse(mStrongAuthTracker.isInLockDownMode(0));
// the notifyPostedLocked function is called twice.
verify(mListeners, times(2)).notifyPostedLocked(any(), any());
}
+
+ @Test
+ public void testMakeRankingUpdateLockedInLockDownMode() {
+ // post 2 notifications from a same package
+ NotificationRecord pkgA = new NotificationRecord(mContext,
+ generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
+ mService.addNotification(pkgA);
+ NotificationRecord pkgB = new NotificationRecord(mContext,
+ generateSbn("a", 1000, 9, 1), mTestNotificationChannel);
+ mService.addNotification(pkgB);
+
+ mService.setIsVisibleToListenerReturnValue(true);
+ NotificationRankingUpdate nru = mService.makeRankingUpdateLocked(null);
+ assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
+
+ // when only user 0 entering the lockdown mode, its notification will be suppressed.
+ mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
+ STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertTrue(mStrongAuthTracker.isInLockDownMode(0));
+ assertFalse(mStrongAuthTracker.isInLockDownMode(1));
+
+ nru = mService.makeRankingUpdateLocked(null);
+ assertEquals(1, nru.getRankingMap().getOrderedKeys().length);
+
+ // User 0 exits lockdown mode. Its notification will be resumed.
+ mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+ mStrongAuthTracker.onStrongAuthRequiredChanged(0);
+ assertFalse(mStrongAuthTracker.isInLockDownMode(0));
+ assertFalse(mStrongAuthTracker.isInLockDownMode(1));
+
+ nru = mService.makeRankingUpdateLocked(null);
+ assertEquals(2, nru.getRankingMap().getOrderedKeys().length);
+ }
}

View File

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nate Myren <ntmyren@google.com>
Date: Fri, 2 Dec 2022 09:44:31 -0800
Subject: [PATCH] RESTRICT AUTOMERGE Revoke dev perm if app is upgrading to
post 23 and perm has pre23 flag
If a permission has the "pre23" flag, and an app is upgrading past api
23, then we should not assume that a "development" permission remains
granted
Fixes: 259458532
Test: atest RevokeSawPermissionTest
Change-Id: I214396f455c5ed9e8bac2e50b1525b86475c81c7
(cherry picked from commit 2f30a63b11e59f9daf42f51eb85aa91c86f4baf4)
Merged-In: I214396f455c5ed9e8bac2e50b1525b86475c81c7
---
.../server/pm/permission/PermissionManagerService.java | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 23af4e6c1c3e..9f8e6eae3ba8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -671,7 +671,7 @@ public class PermissionManagerService {
}
final PackageSetting ps = (PackageSetting) newPackage.mExtras;
if (grantSignaturePermission(Manifest.permission.SYSTEM_ALERT_WINDOW, newPackage, saw,
- ps.getPermissionsState())) {
+ ps.getPermissionsState(), true)) {
return;
}
for (int userId: mUserManagerInt.getUserIds()) {
@@ -1836,6 +1836,11 @@ public class PermissionManagerService {
private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
BasePermission bp, PermissionsState origPermissions) {
+ return grantSignaturePermission(perm, pkg, bp, origPermissions, false);
+ }
+ private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
+ BasePermission bp, PermissionsState origPermissions,
+ boolean isApi23Upgrade) {
boolean oemPermission = bp.isOEM();
boolean vendorPrivilegedPermission = bp.isVendorPrivileged();
boolean privilegedPermission = bp.isPrivileged() || bp.isVendorPrivileged();
@@ -2022,7 +2027,7 @@ public class PermissionManagerService {
// Any pre-installed system app is allowed to get this permission.
allowed = true;
}
- if (!allowed && bp.isDevelopment()) {
+ if (!allowed && bp.isDevelopment() && !(bp.isPre23() && isApi23Upgrade)) {
// For development permissions, a development permission
// is granted only if it was already granted.
allowed = origPermissions.hasInstallPermission(perm);

View File

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Wright <michaelwr@google.com>
Date: Mon, 26 Sep 2022 20:37:33 +0100
Subject: [PATCH] Reconcile WorkSource parcel and unparcel code.
Prior to this CL, WorkSources would Parcel their list of WorkChains as
-1 if null, or the size of the list followed by the list itself if
non-null. When reading it back in, on the other hand, they would check
if the size was positive, and only then read the list from the Parcel.
This works for all cases except when the WorkSource has an empty but
non-null list of WorkChains as the list would get written to the parcel,
but then never read on the other side.
If parceling a list was a no-op when empty this wouldn't be an issue,
but it must write at least its size into the parcel to know how many
elements to extract. In the empty list case, this single element is left
unread as the size is not positive which essentially corrupts any future
items read from that same parcelable.
Bug: 220302519
Test: atest android.security.cts.WorkSourceTest#testWorkChainParceling
Change-Id: I2fec40dfced420ca38e717059b0e95ee8ef9946a
(cherry picked from commit 266b3bddcf14d448c0972db64b42950f76c759e3)
Merged-In: I2fec40dfced420ca38e717059b0e95ee8ef9946a
---
core/java/android/os/WorkSource.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 0b4a56121038..4e7a280aa2c1 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -114,7 +114,7 @@ public class WorkSource implements Parcelable {
mNames = in.createStringArray();
int numChains = in.readInt();
- if (numChains > 0) {
+ if (numChains >= 0) {
mChains = new ArrayList<>(numChains);
in.readParcelableList(mChains, WorkChain.class.getClassLoader());
} else {

View File

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Winson Chung <winsonc@google.com>
Date: Wed, 11 Jan 2023 18:58:41 +0000
Subject: [PATCH] Revert "Ensure that only SysUI can override pending intent
launch flags"
This reverts commit c4d3106e347922610f8c554de3ae238175ed393e.
Reason for revert: b/264884187, b/264885689
Change-Id: I9fb0d66327f3f872a92e6b9d682d58489e81e6ba
(cherry picked from commit 7bb933f48ff15d8f08d2185005b7b3e212915276)
Merged-In: I9fb0d66327f3f872a92e6b9d682d58489e81e6ba
---
.../com/android/server/am/PendingIntentRecord.java | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 44d67ed0d642..54504c3c1e24 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -317,16 +317,11 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
resolvedType = key.requestResolvedType;
}
- // Apply any launch flags from the ActivityOptions. This is used only by SystemUI
- // to ensure that we can launch the pending intent with a consistent launch mode even
- // if the provided PendingIntent is immutable (ie. to force an activity to launch into
- // a new task, or to launch multiple instances if supported by the app)
+ // Apply any launch flags from the ActivityOptions. This is to ensure that the caller
+ // can specify a consistent launch mode even if the PendingIntent is immutable
final ActivityOptions opts = ActivityOptions.fromBundle(options);
if (opts != null) {
- // TODO(b/254490217): Move this check into SafeActivityOptions
- if (controller.mAtmInternal.isCallerRecents(Binder.getCallingUid())) {
- finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
- }
+ finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
}
// Extract options before clearing calling identity

View File

@ -0,0 +1,82 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Liahav Eitan <liahav@google.com>
Date: Tue, 11 Oct 2022 13:20:52 +0000
Subject: [PATCH] Fix sharing to another profile where an app has multiple
targets
Moves the fixUris call from onTargetSelected directly to the intent
launch to ensure the intent which is actually started is updated with
userId specific URIs.
This is a backport of ag/19657256 and ag/20063949.
Bug:242165528
Bug:244876518
Bug:242605257
Test: manually share image from personal profile to work gmail,
first with chat target then backing up and selecting the main target
Test: manually share image from work Photos app to personal WhatsApp's
frequent contact target.
Change-Id: Id815984e691bf962e19e30a54f7247d16060b3b8
Merged-In: Id815984e691bf962e19e30a54f7247d16060b3b8
Merged-In: Ib41c8a3c46afcc2d62a4c1a924212bcd98bcfbe4
Merged-In: Iabf5dcf2612fe718f2f0886e2e5e9b76f37af1e1
(cherry picked from commit f50ced5f1e619d7fa7858748d6a9dbe861354f04)
Merged-In: Id815984e691bf962e19e30a54f7247d16060b3b8
(cherry picked from commit 0b4cfaca78dfadd546adc47cbcbcdde5425cf17a)
---
.../com/android/internal/app/ChooserActivity.java | 1 +
.../com/android/internal/app/ResolverActivity.java | 13 +++++++++++++
2 files changed, 14 insertions(+)
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 4d71911921a8..f43ff17ed7d0 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2455,6 +2455,7 @@ public class ChooserActivity extends ResolverActivity {
}
intent.setComponent(mChooserTarget.getComponentName());
intent.putExtras(mChooserTarget.getIntentExtras());
+ TargetInfo.prepareIntentForCrossProfileLaunch(intent, userId);
// Important: we will ignore the target security checks in ActivityManager
// if and only if the ChooserTarget's target package is the same package
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 070e3c101c8e..3de79838eaff 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1514,6 +1514,7 @@ public class ResolverActivity extends Activity {
if (mEnableChooserDelegate) {
return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
} else {
+ TargetInfo.prepareIntentForCrossProfileLaunch(mResolvedIntent, userId);
activity.startActivityAsCaller(mResolvedIntent, options, null, false, userId);
return true;
}
@@ -1521,6 +1522,7 @@ public class ResolverActivity extends Activity {
@Override
public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
+ TargetInfo.prepareIntentForCrossProfileLaunch(mResolvedIntent, user.getIdentifier());
activity.startActivityAsUser(mResolvedIntent, options, user);
return false;
}
@@ -1642,6 +1644,17 @@ public class ResolverActivity extends Activity {
* @return true if this target should be pinned to the front by the request of the user
*/
boolean isPinned();
+
+ /**
+ * Fix the URIs in {@code intent} if cross-profile sharing is required. This should be called
+ * before launching the intent as another user.
+ */
+ static void prepareIntentForCrossProfileLaunch(Intent intent, int targetUserId) {
+ final int currentUserId = UserHandle.myUserId();
+ if (targetUserId != currentUserId) {
+ intent.fixUris(currentUserId);
+ }
+ }
}
public class ResolveListAdapter extends BaseAdapter {

View File

@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jing Ji <jji@google.com>
Date: Thu, 4 Aug 2022 11:36:26 -0700
Subject: [PATCH] DO NOT MERGE: Context#startInstrumentation could be started
from SHELL only now.
Or, if an instrumentation starts another instrumentation and so on,
and the original instrumentation is started from SHELL, allow all
Context#startInstrumentation calls in this chain.
Otherwise, it'll throw a SecurityException.
Bug: 237766679
Test: atest CtsAppTestCases:InstrumentationTest
Merged-In: Ia08f225c21a3933067d066a578ea4af9c23e7d4c
Merged-In: I1b76f61c5fd6c9f7e738978592260945a606f40c
Merged-In: I3ea7aa27bd776fec546908a37f667f680da9c892
Change-Id: I7ca7345b064e8e74f7037b8fa3ed45bb6423e406
(cherry picked from commit 8c90891a38ecb5047e115e13baf700a8b486a5d1)
Merged-In: I7ca7345b064e8e74f7037b8fa3ed45bb6423e406
---
.../server/am/ActivityManagerService.java | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bb78408617b8..efbccb3b8f94 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15761,6 +15761,17 @@ public class ActivityManagerService extends IActivityManager.Stub
reportStartInstrumentationFailureLocked(watcher, className, msg);
throw new SecurityException(msg);
}
+ if (!Build.IS_DEBUGGABLE && callingUid != ROOT_UID && callingUid != SHELL_UID
+ && callingUid != SYSTEM_UID && !hasActiveInstrumentationLocked(callingPid)) {
+ // If it's not debug build and not called from root/shell/system uid, reject it.
+ final String msg = "Permission Denial: instrumentation test "
+ + className + " from pid=" + callingPid + ", uid=" + callingUid
+ + ", pkgName=" + getPackageNameByPid(callingPid)
+ + " not allowed because it's not started from SHELL";
+ Slog.wtfQuiet(TAG, msg);
+ reportStartInstrumentationFailureLocked(watcher, className, msg);
+ throw new SecurityException(msg);
+ }
ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
activeInstr.mClass = className;
@@ -15817,6 +15828,29 @@ public class ActivityManagerService extends IActivityManager.Stub
return true;
}
+ @GuardedBy("this")
+ private boolean hasActiveInstrumentationLocked(int pid) {
+ if (pid == 0) {
+ return false;
+ }
+ synchronized (mPidsSelfLocked) {
+ ProcessRecord process = mPidsSelfLocked.get(pid);
+ return process != null && process.getActiveInstrumentation() != null;
+ }
+ }
+
+ private String getPackageNameByPid(int pid) {
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord app = mPidsSelfLocked.get(pid);
+
+ if (app != null && app.info != null) {
+ return app.info.packageName;
+ }
+
+ return null;
+ }
+ }
+
private boolean isCallerShell() {
final int callingUid = Binder.getCallingUid();
return callingUid == SHELL_UID || callingUid == ROOT_UID;

View File

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kunal Malhotra <malhk@google.com>
Date: Mon, 7 Nov 2022 23:33:55 +0000
Subject: [PATCH] Checking if package belongs to UID before registering
broadcast receiver
Test: manual testing done on device by installing test APK and checking if receiver can register
Bug: 242040055
Change-Id: Ia525f218a46f8bf7fff660cec0d6432f09fdf24d
Merged-In: Ia525f218a46f8bf7fff660cec0d6432f09fdf24d
(cherry picked from commit 790a8d0dd329460bc60456681cb446accf2a27e0)
(cherry picked from commit 4f0dc37b896e06086391e71ce471e413215e1130)
Merged-In: Ia525f218a46f8bf7fff660cec0d6432f09fdf24d
---
services/core/java/com/android/server/am/ActiveServices.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 84702ddfe231..c6d94eb3b408 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2186,6 +2186,11 @@ public final class ActiveServices {
throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ className + " is not an isolatedProcess");
}
+ if (AppGlobals.getPackageManager().getPackageUid(callingPackage,
+ 0, userId) != callingUid) {
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ + "calling package not owned by calling UID ");
+ }
// Run the service under the calling package's application.
ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId);

View File

@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hao Ke <haok@google.com>
Date: Mon, 12 Dec 2022 15:49:16 +0000
Subject: [PATCH] Fix checkKeyIntentParceledCorrectly's bypass
The checkKeyIntentParceledCorrectly method was added in checkKeyIntent, which was originaly only invoked when AccountManagerService deserializes the KEY_INTENT value as not NULL. However, due to the self-changing bundle technique in Parcel mismatch problems, the Intent value can change after reparceling; hence would bypass the added checkKeyIntentParceledCorrectly call.
This CL did the following:
- Ensure the checkKeyIntent method is also called when result.getParcelable(AccountManager.KEY_INTENT) == null.
Bug: 260567867
Bug: 262230405
Test: local test, see b/262230405
Test: atest CtsAccountManagerTestCases
Merged-In: I7b528f52c41767ae12731838fdd36aa26a8f3477
Change-Id: I7b528f52c41767ae12731838fdd36aa26a8f3477
(cherry picked from commit 9f623983a8d4ec48d58b0eda56fa461fc6748981)
Merged-In: I7b528f52c41767ae12731838fdd36aa26a8f3477
---
.../server/accounts/AccountManagerService.java | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 58978a55a32a..b4edf94927b2 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3434,8 +3434,7 @@ public class AccountManagerService
Bundle.setDefusable(result, true);
mNumResults++;
Intent intent = null;
- if (result != null
- && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
+ if (result != null) {
if (!checkKeyIntent(
Binder.getCallingUid(),
result)) {
@@ -4800,8 +4799,10 @@ public class AccountManagerService
EventLog.writeEvent(0x534e4554, "250588548", authUid, "");
return false;
}
-
Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
+ if (intent == null) {
+ return true;
+ }
// Explicitly set an empty ClipData to ensure that we don't offer to
// promote any Uris contained inside for granting purposes
if (intent.getClipData() == null) {
@@ -4854,7 +4855,10 @@ public class AccountManagerService
p.recycle();
Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT);
- return (intent.filterEquals(simulateIntent));
+ if (intent == null) {
+ return (simulateIntent == null);
+ }
+ return intent.filterEquals(simulateIntent);
}
private boolean isExportedSystemActivity(ActivityInfo activityInfo) {
@@ -4999,8 +5003,7 @@ public class AccountManagerService
}
}
}
- if (result != null
- && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
+ if (result != null) {
if (!checkKeyIntent(
Binder.getCallingUid(),
result)) {

View File

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Winson Chiu <chiuwinson@google.com>
Date: Fri, 6 Jan 2023 21:26:24 +0000
Subject: [PATCH] Encode Intent scheme when serializing to URI string RESTRICT
AUTOMERGE
Avoids deserialization error when the scheme contains a
reserved character.
Bug: 261858325
Test: atest android.content.cts.IntentTest#testEncoding
Merged-In: Ic34b3f796b762763db5aa7b5d7c109ae70607470
Change-Id: Ic34b3f796b762763db5aa7b5d7c109ae70607470
(cherry picked from commit 43437b4ee6424933d4e403f0375ef8c1f07986f4)
Merged-In: Ic34b3f796b762763db5aa7b5d7c109ae70607470
---
core/java/android/content/Intent.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d7898776965e..72e0fa615b09 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -10393,7 +10393,7 @@ public class Intent implements Parcelable, Cloneable {
private void toUriInner(StringBuilder uri, String scheme, String defAction,
String defPackage, int flags) {
if (scheme != null) {
- uri.append("scheme=").append(scheme).append(';');
+ uri.append("scheme=").append(Uri.encode(scheme)).append(';');
}
if (mAction != null && !mAction.equals(defAction)) {
uri.append("action=").append(Uri.encode(mAction)).append(';');

View File

@ -0,0 +1,430 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Christophe Pinelli <cpinelli@google.com>
Date: Tue, 27 Dec 2022 20:29:33 +0000
Subject: [PATCH] Backport BAL restrictions from S to R, this blocks apps from
using Alarm Manager to bypass BAL restrictions.
Test: atest BackgroundActivityLaunchTest
Bug: 195756028
Change-Id: Ifa3f79bc74c10d0ac8322079f2e6e3e0ba476b0f
(cherry picked from commit 1d737c2fbdc71570bbcaca0f44da4ee132fa545f)
Merged-In: Ifa3f79bc74c10d0ac8322079f2e6e3e0ba476b0f
---
core/java/android/app/ActivityOptions.java | 10 +--
core/java/android/app/BroadcastOptions.java | 25 +++++-
core/java/android/app/ComponentOptions.java | 84 +++++++++++++++++++
.../android/server/AlarmManagerService.java | 21 ++++-
.../server/am/PendingIntentRecord.java | 23 ++++-
.../android/server/wm/ActivityStarter.java | 22 +++--
.../server/wm/ActivityTaskManagerService.java | 2 +-
.../com/android/server/wm/AppTaskImpl.java | 2 +-
8 files changed, 169 insertions(+), 20 deletions(-)
create mode 100644 core/java/android/app/ComponentOptions.java
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 926044bffdd0..36ab62aedc09 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -59,7 +59,7 @@ import java.util.ArrayList;
* {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
* Context.startActivity(Intent, Bundle)} and related methods.
*/
-public class ActivityOptions {
+public class ActivityOptions extends ComponentOptions {
private static final String TAG = "ActivityOptions";
/**
@@ -881,13 +881,12 @@ public class ActivityOptions {
}
private ActivityOptions() {
+ super();
}
/** @hide */
public ActivityOptions(Bundle opts) {
- // If the remote side sent us bad parcelables, they won't get the
- // results they want, which is their loss.
- opts.setDefusable(true);
+ super(opts);
mPackageName = opts.getString(KEY_PACKAGE_NAME);
try {
@@ -1439,8 +1438,9 @@ public class ActivityOptions {
* object; you must not modify it, but can supply it to the startActivity
* methods that take an options Bundle.
*/
+ @Override
public Bundle toBundle() {
- Bundle b = new Bundle();
+ Bundle b = super.toBundle();
if (mPackageName != null) {
b.putString(KEY_PACKAGE_NAME, mPackageName);
}
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 161e2ad06ec0..8947fb44b07b 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -28,7 +28,7 @@ import android.os.Bundle;
* {@hide}
*/
@SystemApi
-public class BroadcastOptions {
+public class BroadcastOptions extends ComponentOptions {
private long mTemporaryAppWhitelistDuration;
private int mMinManifestReceiverApiLevel = 0;
private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
@@ -72,10 +72,12 @@ public class BroadcastOptions {
}
private BroadcastOptions() {
+ super();
}
/** @hide */
public BroadcastOptions(Bundle opts) {
+ super(opts);
mTemporaryAppWhitelistDuration = opts.getLong(KEY_TEMPORARY_APP_WHITELIST_DURATION);
mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0);
mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
@@ -173,6 +175,24 @@ public class BroadcastOptions {
return mAllowBackgroundActivityStarts;
}
+ /**
+ * Set PendingIntent activity is allowed to be started in the background if the caller
+ * can start background activities.
+ * @hide
+ */
+ public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) {
+ super.setPendingIntentBackgroundActivityLaunchAllowed(allowed);
+ }
+
+ /**
+ * Get PendingIntent activity is allowed to be started in the background if the caller
+ * can start background activities.
+ * @hide
+ */
+ public boolean isPendingIntentBackgroundActivityLaunchAllowed() {
+ return super.isPendingIntentBackgroundActivityLaunchAllowed();
+ }
+
/**
* Returns the created options as a Bundle, which can be passed to
* {@link android.content.Context#sendBroadcast(android.content.Intent)
@@ -181,8 +201,9 @@ public class BroadcastOptions {
* object; you must not modify it, but can supply it to the sendBroadcast
* methods that take an options Bundle.
*/
+ @Override
public Bundle toBundle() {
- Bundle b = new Bundle();
+ Bundle b = super.toBundle();
if (mTemporaryAppWhitelistDuration > 0) {
b.putLong(KEY_TEMPORARY_APP_WHITELIST_DURATION, mTemporaryAppWhitelistDuration);
}
diff --git a/core/java/android/app/ComponentOptions.java b/core/java/android/app/ComponentOptions.java
new file mode 100644
index 000000000000..34ee9138a364
--- /dev/null
+++ b/core/java/android/app/ComponentOptions.java
@@ -0,0 +1,84 @@
+/*
+ * 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 android.app;
+
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+public class ComponentOptions {
+
+ /**
+ * Default value for KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED.
+ * @hide
+ **/
+ public static final boolean PENDING_INTENT_BAL_ALLOWED_DEFAULT = true;
+
+ /**
+ * PendingIntent caller allows activity start even if PendingIntent creator is in background.
+ * This only works if the PendingIntent caller is allowed to start background activities,
+ * for example if it's in the foreground, or has BAL permission.
+ * @hide
+ */
+ public static final String KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED =
+ "android.pendingIntent.backgroundActivityAllowed";
+
+ private boolean mPendingIntentBalAllowed = PENDING_INTENT_BAL_ALLOWED_DEFAULT;
+
+ ComponentOptions() {
+ }
+
+ ComponentOptions(Bundle opts) {
+ // If the remote side sent us bad parcelables, they won't get the
+ // results they want, which is their loss.
+ opts.setDefusable(true);
+ setPendingIntentBackgroundActivityLaunchAllowed(
+ opts.getBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED,
+ PENDING_INTENT_BAL_ALLOWED_DEFAULT));
+ }
+
+ /**
+ * Set PendingIntent activity is allowed to be started in the background if the caller
+ * can start background activities.
+ *
+ * @hide
+ */
+ public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) {
+ mPendingIntentBalAllowed = allowed;
+ }
+
+ /**
+ * Get PendingIntent activity is allowed to be started in the background if the caller
+ * can start background activities.
+ *
+ * @hide
+ */
+ public boolean isPendingIntentBackgroundActivityLaunchAllowed() {
+ return mPendingIntentBalAllowed;
+ }
+
+ /**
+ * @hide
+ */
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED,
+ mPendingIntentBalAllowed);
+ return bundle;
+ }
+}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index a65603cb4020..d82b435b4612 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -26,6 +26,7 @@ import static android.app.AlarmManager.RTC_WAKEUP;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -272,6 +273,8 @@ class AlarmManagerService extends SystemService {
* Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
*/
Bundle mIdleOptions;
+ ActivityOptions mActivityOptsRestrictBal = ActivityOptions.makeBasic();
+ BroadcastOptions mBroadcastOptsRestrictBal = BroadcastOptions.makeBasic();
private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
new SparseArray<>();
@@ -497,6 +500,7 @@ class AlarmManagerService extends SystemService {
mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
BroadcastOptions opts = BroadcastOptions.makeBasic();
opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
+ opts.setPendingIntentBackgroundActivityLaunchAllowed(false);
mIdleOptions = opts.toBundle();
}
}
@@ -1495,6 +1499,8 @@ class AlarmManagerService extends SystemService {
@Override
public void onStart() {
mInjector.init();
+ mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false);
synchronized (mLock) {
mHandler = new AlarmHandler();
@@ -4143,6 +4149,13 @@ class AlarmManagerService extends SystemService {
return alarm.creatorUid;
}
+ private Bundle getAlarmOperationBundle(Alarm alarm) {
+ if (alarm.operation.isActivity()) {
+ return mActivityOptsRestrictBal.toBundle();
+ }
+ return mBroadcastOptsRestrictBal.toBundle();
+ }
+
@VisibleForTesting
class AlarmHandler extends Handler {
public static final int ALARM_EVENT = 1;
@@ -4181,7 +4194,11 @@ class AlarmManagerService extends SystemService {
for (int i=0; i<triggerList.size(); i++) {
Alarm alarm = triggerList.get(i);
try {
- alarm.operation.send();
+ // Disallow AlarmManager to start random background activity.
+ final Bundle bundle = getAlarmOperationBundle(alarm);
+ alarm.operation.send(/* context */ null, /* code */0, /* intent */
+ null, /* onFinished */null, /* handler */
+ null, /* requiredPermission */ null, bundle);
} catch (PendingIntent.CanceledException e) {
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
@@ -4696,7 +4713,7 @@ class AlarmManagerService extends SystemService {
mBackgroundIntent.putExtra(
Intent.EXTRA_ALARM_COUNT, alarm.count),
mDeliveryTracker, mHandler, null,
- allowWhileIdle ? mIdleOptions : null);
+ allowWhileIdle ? mIdleOptions : getAlarmOperationBundle(alarm));
} catch (PendingIntent.CanceledException e) {
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 54504c3c1e24..20d87e6882ac 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.START_SUCCESS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.IIntentSender;
@@ -277,6 +278,25 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
requiredPermission, null, null, 0, 0, 0, options);
}
+ /**
+ * Return true if the activity options allows PendingIntent to use caller's BAL permission.
+ */
+ public static boolean isPendingIntentBalAllowedByCaller(
+ @Nullable ActivityOptions activityOptions) {
+ if (activityOptions == null) {
+ return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT;
+ }
+ return isPendingIntentBalAllowedByCaller(activityOptions.toBundle());
+ }
+
+ private static boolean isPendingIntentBalAllowedByCaller(@Nullable Bundle options) {
+ if (options == null) {
+ return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT;
+ }
+ return options.getBoolean(ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED,
+ ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT);
+ }
+
public int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
@@ -389,7 +409,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
// temporarily allow receivers and services to open activities from background if the
// PendingIntent.send() caller was foreground at the time of sendInner() call
final boolean allowTrampoline = uid != callingUid
- && controller.mAtmInternal.isUidForeground(callingUid);
+ && controller.mAtmInternal.isUidForeground(callingUid)
+ && isPendingIntentBalAllowedByCaller(options);
// note: we on purpose don't pass in the information about the PendingIntent's creator,
// like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index f37698de34d5..44fef5427cc3 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -767,6 +767,10 @@ class ActivityStarter {
abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
callingPackage);
+ // Merge the two options bundles, while realCallerOptions takes precedence.
+ ActivityOptions checkedOptions = options != null
+ ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
+
boolean restrictedBgActivity = false;
if (!abort) {
try {
@@ -774,15 +778,12 @@ class ActivityStarter {
"shouldAbortBackgroundActivityStart");
restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
- originatingPendingIntent, allowBackgroundActivityStart, intent);
+ originatingPendingIntent, allowBackgroundActivityStart, intent, checkedOptions);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
- // Merge the two options bundles, while realCallerOptions takes precedence.
- ActivityOptions checkedOptions = options != null
- ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
if (allowPendingRemoteAnimationRegistryLookup) {
checkedOptions = mService.getActivityStartController()
.getPendingRemoteAnimationRegistry()
@@ -941,7 +942,7 @@ class ActivityStarter {
boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
final String callingPackage, int realCallingUid, int realCallingPid,
WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
- boolean allowBackgroundActivityStart, Intent intent) {
+ boolean allowBackgroundActivityStart, Intent intent, ActivityOptions checkedOptions) {
// don't abort for the most important UIDs
final int callingAppId = UserHandle.getAppId(callingUid);
if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
@@ -976,7 +977,11 @@ class ActivityStarter {
? isCallingUidPersistentSystemProcess
: (realCallingAppId == Process.SYSTEM_UID)
|| realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
- if (realCallingUid != callingUid) {
+ // Legacy behavior allows to use caller foreground state to bypass BAL restriction.
+ final boolean balAllowedByPiSender =
+ PendingIntentRecord.isPendingIntentBalAllowedByCaller(checkedOptions);
+
+ if (balAllowedByPiSender && realCallingUid != callingUid) {
// don't abort if the realCallingUid has a visible window
if (realCallingUidHasAnyVisibleWindow) {
return false;
@@ -1013,9 +1018,10 @@ class ActivityStarter {
// If we don't have callerApp at this point, no caller was provided to startActivity().
// That's the case for PendingIntent-based starts, since the creator's process might not be
// up and alive. If that's the case, we retrieve the WindowProcessController for the send()
- // caller, so that we can make the decision based on its foreground/whitelisted state.
+ // caller if caller allows, so that we can make the decision
+ // based on its foreground/whitelisted state.
int callerAppUid = callingUid;
- if (callerApp == null) {
+ if (callerApp == null && balAllowedByPiSender) {
callerApp = mService.getProcessController(realCallingPid, realCallingUid);
callerAppUid = realCallingUid;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 5e2626b9a7dd..d0dad0a23729 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2398,7 +2398,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityStarter starter = getActivityStartController().obtainStarter(
null /* intent */, "moveTaskToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1,
- -1, callerApp, null, false, null)) {
+ -1, callerApp, null, false, null, null)) {
if (!isBackgroundActivityStartsEnabled()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 1eb7455135c7..f221c3a4573f 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -117,7 +117,7 @@ class AppTaskImpl extends IAppTask.Stub {
final ActivityStarter starter = mService.getActivityStartController().obtainStarter(
null /* intent */, "moveToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid,
- callingPackage, -1, -1, callerApp, null, false, null)) {
+ callingPackage, -1, -1, callerApp, null, false, null, null)) {
if (!mService.isBackgroundActivityStartsEnabled()) {
return;
}

View File

@ -0,0 +1,152 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Louis Chang <louischang@google.com>
Date: Wed, 28 Sep 2022 06:46:29 +0000
Subject: [PATCH] Strip part of the activity info of another uid if no
privilege
The activity info could be from another uid which is different
from the app that hosts the task. The information should be
trimmed if the caller app doesn't have the privilege.
However, removing the entire info may result in app compatibility
issues. So, only swiping the info that are sensitive to empty
string.
Bug: 243130512
Test: verified market app locally
Test: atest RecentTasksTest
Change-Id: I5b6775dd3c4e2ccdacd30741884d336b2eaa70da
Merged-In: I5b6775dd3c4e2ccdacd30741884d336b2eaa70da
(cherry picked from commit 5ba72200f6a66b5da48c9c3abd103a73aea1ef95)
(cherry picked from commit e534fa2a7119f39cb76f1d08557b7dcae3b6d94e)
(cherry picked from commit 20fc1c7244cdf840e4a6cbfa71904b4d608bb093)
Merged-In: I5b6775dd3c4e2ccdacd30741884d336b2eaa70da
---
.../com/android/server/wm/AppTaskImpl.java | 3 +-
.../com/android/server/wm/RecentTasks.java | 8 +++--
.../com/android/server/wm/RunningTasks.java | 7 ++++
.../com/android/server/wm/TaskRecord.java | 34 +++++++++++++++++++
4 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index f221c3a4573f..e12c8259d8a7 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -84,7 +84,8 @@ class AppTaskImpl extends IAppTask.Stub {
if (tr == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
- return mService.getRecentTasks().createRecentTaskInfo(tr);
+ return mService.getRecentTasks().createRecentTaskInfo(tr,
+ true /* getTasksAllowed */);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 541a8bbc8865..67fb4c28cf22 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -944,7 +944,7 @@ class RecentTasks {
continue;
}
- final ActivityManager.RecentTaskInfo rti = createRecentTaskInfo(tr);
+ final ActivityManager.RecentTaskInfo rti = createRecentTaskInfo(tr, getTasksAllowed);
if (!getDetailedTasks) {
rti.baseIntent.replaceExtras((Bundle) null);
}
@@ -1715,12 +1715,16 @@ class RecentTasks {
/**
* Creates a new RecentTaskInfo from a TaskRecord.
*/
- ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
+ ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr,
+ boolean getTasksAllowed) {
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
tr.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
+ if (!getTasksAllowed) {
+ TaskRecord.trimIneffectiveInfo(tr, rti);
+ }
return rti;
}
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 81a85476c53a..16d041a7a1c0 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -39,6 +39,8 @@ class RunningTasks {
private final TreeSet<TaskRecord> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
private final ArrayList<TaskRecord> mTmpStackTasks = new ArrayList<>();
+ private boolean mAllowed;
+
void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType,
@WindowingMode int ignoreWindowingMode, ArrayList<ActivityDisplay> activityDisplays,
int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
@@ -49,6 +51,7 @@ class RunningTasks {
// Gather all of the tasks across all of the tasks, and add them to the sorted set
mTmpSortedSet.clear();
+ mAllowed = allowed;
final int numDisplays = activityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final ActivityDisplay display = activityDisplays.get(displayNdx);
@@ -82,6 +85,10 @@ class RunningTasks {
task.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.taskId;
+
+ if (!mAllowed) {
+ TaskRecord.trimIneffectiveInfo(task, rti);
+ }
return rti;
}
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 361f66e3106a..78d13e95df81 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -2436,6 +2436,40 @@ class TaskRecord extends ConfigurationContainer {
info.configuration.setTo(getConfiguration());
}
+ /**
+ * Removes the activity info if the activity belongs to a different uid, which is
+ * different from the app that hosts the task.
+ */
+ static void trimIneffectiveInfo(TaskRecord task, TaskInfo info) {
+ int topActivityUid = task.effectiveUid;
+ for (int i = task.mActivities.size() - 1; i >= 0; --i) {
+ final ActivityRecord r = task.mActivities.get(i);
+ if (r.finishing || r.isState(ActivityState.INITIALIZING)) {
+ continue;
+ }
+ topActivityUid = r.info.applicationInfo.uid;
+ break;
+ }
+
+ if (task.effectiveUid != topActivityUid) {
+ info.topActivity = new ComponentName("", "");
+ }
+
+ int baseActivityUid = task.effectiveUid;
+ for (int i = 0; i < task.mActivities.size(); ++i) {
+ final ActivityRecord r = task.mActivities.get(i);
+ if (r.finishing) {
+ continue;
+ }
+ baseActivityUid = r.info.applicationInfo.uid;
+ break;
+ }
+
+ if (task.effectiveUid != baseActivityUid) {
+ info.baseActivity = new ComponentName("", "");
+ }
+ }
+
/**
* Returns a {@link TaskInfo} with information from this task.
*/

View File

@ -0,0 +1,134 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Julia Reynolds <juliacr@google.com>
Date: Tue, 18 Jan 2022 11:59:54 -0500
Subject: [PATCH] Add a limit on channel group creation
Same as exists for channels
This is a backport of the fix in ag/16659457, including the adjustment from ag/20920023 (changed the max value from 50000 to 6000).
Test: PreferencesHelperTest
Bug: 210114537
Bug: 261723753
Change-Id: Ic27efba4c54e22eebca16fc948879e652df4467b
(cherry picked from commit 37b3549807d15452ac334fae316e615c3b9b8e8b & I3f3a99765c161369e1b026686a0e5f0c83ed839e)
Merged-In: I3f3a99765c161369e1b026686a0e5f0c83ed839e
Merged-In: Ic27efba4c54e22eebca16fc948879e652df4467b
(cherry picked from commit 0f29716ab6fbf236e5d8f688bcdfdadf32429545)
Merged-In: Ic27efba4c54e22eebca16fc948879e652df4467b
---
.../notification/PreferencesHelper.java | 16 ++++++-
.../notification/PreferencesHelperTest.java | 47 +++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index d4ba51cc3146..1a3779f7c607 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -73,7 +73,9 @@ public class PreferencesHelper implements RankingConfig {
private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":";
@VisibleForTesting
- static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 50000;
+ static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
+ @VisibleForTesting
+ static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 6000;
@VisibleForTesting
static final String TAG_RANKING = "ranking";
@@ -184,6 +186,7 @@ public class PreferencesHelper implements RankingConfig {
}
}
boolean skipWarningLogged = false;
+ boolean skipGroupWarningLogged = false;
PackagePreferences r = getOrCreatePackagePreferencesLocked(name, uid,
XmlUtils.readIntAttribute(
@@ -220,6 +223,14 @@ public class PreferencesHelper implements RankingConfig {
String tagName = parser.getName();
// Channel groups
if (TAG_GROUP.equals(tagName)) {
+ if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
+ if (!skipGroupWarningLogged) {
+ Slog.w(TAG, "Skipping further groups for " + r.pkg
+ + "; app has too many");
+ skipGroupWarningLogged = true;
+ }
+ continue;
+ }
String id = parser.getAttributeValue(null, ATT_ID);
CharSequence groupName = parser.getAttributeValue(null,
ATT_NAME);
@@ -610,6 +621,9 @@ public class PreferencesHelper implements RankingConfig {
}
if (fromTargetApp) {
group.setBlocked(false);
+ if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
+ throw new IllegalStateException("Limit exceed; cannot create more groups");
+ }
}
final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
if (!group.equals(oldGroup)) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 2cede07de257..dfb62999be5f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -23,6 +23,7 @@ import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
+import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.fail;
@@ -2729,4 +2730,50 @@ public class PreferencesHelperTest extends UiServiceTestCase {
assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel, true));
assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel1, true));
}
+
+ @Test
+ public void testTooManyGroups() {
+ for (int i = 0; i < NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; i++) {
+ NotificationChannelGroup group = new NotificationChannelGroup(String.valueOf(i),
+ String.valueOf(i));
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ }
+ try {
+ NotificationChannelGroup group = new NotificationChannelGroup(
+ String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT),
+ String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT));
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ fail("Allowed to create too many notification channel groups");
+ } catch (IllegalStateException e) {
+ // great
+ }
+ }
+
+ @Test
+ public void testTooManyGroups_xml() throws Exception {
+ String extraGroup = "EXTRA";
+ String extraGroup1 = "EXTRA1";
+
+ // create first... many... directly so we don't need a big xml blob in this test
+ for (int i = 0; i < NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; i++) {
+ NotificationChannelGroup group = new NotificationChannelGroup(String.valueOf(i),
+ String.valueOf(i));
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ }
+
+ final String xml = "<ranking version=\"1\">\n"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
+ + "<channelGroup id=\"" + extraGroup + "\" name=\"hi\"/>"
+ + "<channelGroup id=\"" + extraGroup1 + "\" name=\"hi2\"/>"
+ + "</package>"
+ + "</ranking>";
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+ assertNull(mHelper.getNotificationChannelGroup(extraGroup, PKG_O, UID_O));
+ assertNull(mHelper.getNotificationChannelGroup(extraGroup1, PKG_O, UID_O));
+ }
}

View File

@ -0,0 +1,241 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rhed Jao <rhedjao@google.com>
Date: Wed, 11 Jan 2023 16:02:27 +0800
Subject: [PATCH] Fix bypass BG-FGS and BAL via package manager APIs
Opt-in for BAL of PendingIntent for following APIs:
* PackageInstaller.uninstall()
* PackageInstaller.installExistingPackage()
* PackageInstaller.uninstallExistingPackage()
* PackageInstaller.Session.commit()
* PackageInstaller.Session.commitTransferred()
* PackageManager.freeStorage()
Bug: 230492955
Bug: 243377226
Test: atest android.security.cts.PackageInstallerTest
Test: atest CtsStagedInstallHostTestCases
Change-Id: I9b6f801d69ea6d2244a38dbe689e81afa4e798bf
(cherry picked from commit b0b1ddb4b4ba5db27f5616b02ae2cdca8b63496f)
Merged-In: I9b6f801d69ea6d2244a38dbe689e81afa4e798bf
---
core/java/android/content/IntentSender.java | 42 ++++++++++++++++++-
.../server/pm/PackageInstallerService.java | 21 ++++++++--
.../server/pm/PackageInstallerSession.java | 19 +++++++--
.../server/pm/PackageManagerService.java | 10 ++++-
4 files changed, 81 insertions(+), 11 deletions(-)
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index ec0bac486c65..0ef0a71fffe0 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -16,8 +16,10 @@
package android.content;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.Handler;
@@ -154,7 +156,7 @@ public class IntentSender implements Parcelable {
*/
public void sendIntent(Context context, int code, Intent intent,
OnFinished onFinished, Handler handler) throws SendIntentException {
- sendIntent(context, code, intent, onFinished, handler, null);
+ sendIntent(context, code, intent, onFinished, handler, null, null /* options */);
}
/**
@@ -186,6 +188,42 @@ public class IntentSender implements Parcelable {
public void sendIntent(Context context, int code, Intent intent,
OnFinished onFinished, Handler handler, String requiredPermission)
throws SendIntentException {
+ sendIntent(context, code, intent, onFinished, handler, requiredPermission,
+ null /* options */);
+ }
+
+ /**
+ * Perform the operation associated with this IntentSender, allowing the
+ * caller to specify information about the Intent to use and be notified
+ * when the send has completed.
+ *
+ * @param context The Context of the caller. This may be null if
+ * <var>intent</var> is also null.
+ * @param code Result code to supply back to the IntentSender's target.
+ * @param intent Additional Intent data. See {@link Intent#fillIn
+ * Intent.fillIn()} for information on how this is applied to the
+ * original Intent. Use null to not modify the original Intent.
+ * @param onFinished The object to call back on when the send has
+ * completed, or null for no callback.
+ * @param handler Handler identifying the thread on which the callback
+ * should happen. If null, the callback will happen from the thread
+ * pool of the process.
+ * @param requiredPermission Name of permission that a recipient of the PendingIntent
+ * is required to hold. This is only valid for broadcast intents, and
+ * corresponds to the permission argument in
+ * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+ * If null, no permission is required.
+ * @param options Additional options the caller would like to provide to modify the sending
+ * behavior. May be built from an {@link ActivityOptions} to apply to an activity start.
+ *
+ * @throws SendIntentException Throws CanceledIntentException if the IntentSender
+ * is no longer allowing more intents to be sent through it.
+ * @hide
+ */
+ public void sendIntent(Context context, int code, Intent intent,
+ OnFinished onFinished, Handler handler, String requiredPermission,
+ @Nullable Bundle options)
+ throws SendIntentException {
try {
String resolvedType = intent != null ?
intent.resolveTypeIfNeeded(context.getContentResolver())
@@ -195,7 +233,7 @@ public class IntentSender implements Parcelable {
onFinished != null
? new FinishedDispatcher(this, onFinished, handler)
: null,
- requiredPermission, null);
+ requiredPermission, options);
if (res < 0) {
throw new SendIntentException();
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index c73f489cb143..ea144fd7c4d5 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -23,6 +23,7 @@ import android.Manifest;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PackageDeleteObserver;
@@ -1021,7 +1022,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
PackageInstaller.STATUS_PENDING_USER_ACTION);
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException ignored) {
}
}
@@ -1046,7 +1050,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
PackageManager.deleteStatusToString(returnCode, msg));
fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException ignored) {
}
}
@@ -1076,7 +1083,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
PackageInstaller.STATUS_PENDING_USER_ACTION);
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException ignored) {
}
}
@@ -1116,7 +1126,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
}
try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException ignored) {
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5a880cb5fa52..71d06d8a2d03 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -44,6 +44,7 @@ import static com.android.server.pm.PackageInstallerService.prepareStageDir;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.BroadcastOptions;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
@@ -960,13 +961,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
try {
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID,
PackageInstallerSession.this.sessionId);
- mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mStatusReceiver.sendIntent(mContext, 0, intent,
+ null /* onFinished*/, null /* handler */,
+ null /* requiredPermission */, options.toBundle());
} catch (IntentSender.SendIntentException ignore) {
}
}
} else if (PackageInstaller.STATUS_PENDING_USER_ACTION == status) {
try {
- mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mStatusReceiver.sendIntent(mContext, 0, intent,
+ null /* onFinished*/, null /* handler */,
+ null /* requiredPermission */, options.toBundle());
} catch (IntentSender.SendIntentException ignore) {
}
} else {
@@ -974,7 +983,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
PackageInstallerSession.this.sessionId);
mChildSessionsRemaining.clear(); // we're done. Don't send any more.
try {
- mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mStatusReceiver.sendIntent(mContext, 0, intent,
+ null /* onFinished*/, null /* handler */,
+ null /* requiredPermission */, options.toBundle());
} catch (IntentSender.SendIntentException ignore) {
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1bd1396c6d45..ef97d61d26d7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4893,7 +4893,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (pi != null) {
try {
- pi.sendIntent(null, success ? 1 : 0, null, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ pi.sendIntent(null, success ? 1 : 0, null /* intent */, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException e) {
Slog.w(TAG, e);
}
@@ -13738,7 +13741,10 @@ public class PackageManagerService extends IPackageManager.Stub
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageManager.installStatusToPublicStatus(returnCode));
try {
- target.sendIntent(context, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ target.sendIntent(context, 0, fillIn, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException ignored) {
}
}

View File

@ -0,0 +1,85 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Songchun Fan <schfan@google.com>
Date: Thu, 26 Jan 2023 17:43:24 -0800
Subject: [PATCH] prevent system app downgrades of versions lower than preload
Also remove misleading commandline output.
BUG: 256202273
Test: manual
1. Install preload system app v90, reboot
2. (W/O data, W/ Flag, 90->80 NOK) adb install -d ~/Downloads/PrivApplication_80.apk
Performing Streamed Install
adb: failed to install /usr/local/google/home/schfan/Downloads/PrivApplication_80.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE: System app: com.example.privapplication cannot be downgraded to older than its preloaded version on the system image. Update version code 80 is older than current 90]
3. (90->100) Install data app v100
4. (W/ data, W/O Flag, 100->90 NOK) adb install ~/Downloads/PrivApplication_90.apk
Performing Streamed Install
adb: failed to install /usr/local/google/home/schfan/Downloads/PrivApplication_90.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE: Downgrade detected: Update version code 90 is older than current 100]
5. (W/ data, W/ Flag, 100->90 downgrade OK) adb install -d ~/Downloads/PrivApplication_90.apk
Performing Streamed Install
Success
6. (90->100) Install v100
6. (W/data, W/ Flag, 100->80 NOK) adb install -d ~/Downloads/PrivApplication_80.apk
Performing Streamed Install
adb: failed to install /usr/local/google/home/schfan/Downloads/PrivApplication_80.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE: System app: com.example.privapplication cannot be downgraded to older than its preloaded version on the system image. Update version code 80 is older than current 90]
Change-Id: I5a8ee9e29a3a58f6e3fd188e0122355744b8b0ce
(cherry picked from commit a4484d7f1be1fa413258fe18644d61f85611f586)
(cherry picked from commit on googleplex-android-review.googlesource.com host: aec76152d65cfd5774f6c0dcf4cb6009ba48c1ee)
Merged-In: I5a8ee9e29a3a58f6e3fd188e0122355744b8b0ce
---
.../server/pm/PackageManagerService.java | 26 ++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ef97d61d26d7..37b85cf4fe79 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15281,10 +15281,10 @@ public class PackageManagerService extends IPackageManager.Stub
// will be null whereas dataOwnerPkg will contain information about the package
// which was uninstalled while keeping its data.
PackageParser.Package dataOwnerPkg = installedPkg;
+ PackageSetting dataOwnerPs = mSettings.mPackages.get(packageName);
if (dataOwnerPkg == null) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps != null) {
- dataOwnerPkg = ps.pkg;
+ if (dataOwnerPs != null) {
+ dataOwnerPkg = dataOwnerPs.pkg;
}
}
@@ -15308,12 +15308,32 @@ public class PackageManagerService extends IPackageManager.Stub
if (dataOwnerPkg != null) {
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
dataOwnerPkg.applicationInfo.flags)) {
+ // Downgrade is not permitted; a lower version of the app will not be
+ // allowed
try {
checkDowngrade(dataOwnerPkg, pkgLite);
} catch (PackageManagerException e) {
Slog.w(TAG, "Downgrade detected: " + e.getMessage());
return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
}
+ } else if (dataOwnerPs.isSystem()) {
+ // Downgrade is permitted, but system apps can't be downgraded below
+ // the version preloaded onto the system image
+ final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(
+ dataOwnerPs);
+ if (disabledPs != null) {
+ dataOwnerPkg = disabledPs.pkg;
+ }
+ try {
+ checkDowngrade(dataOwnerPkg, pkgLite);
+ } catch (PackageManagerException e) {
+ String errorMsg = "System app: " + packageName
+ + " cannot be downgraded to"
+ + " older than its preloaded version on the system image. "
+ + e.getMessage();
+ Slog.w(TAG, errorMsg);
+ return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
+ }
}
}

View File

@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Songchun Fan <schfan@google.com>
Date: Thu, 2 Feb 2023 10:35:56 -0800
Subject: [PATCH] still allow debuggable for system app downgrades
Turns out we do have internal tests that downgrades system apps, so adding this exception to allow for that.
BUG: 267232653
BUG: 256202273
Test: manual
Change-Id: Ie281bbdc8788ee64ff99a7c5150da7ce7926235e
(cherry picked from commit ceeca68b8c3f0ed8427b0212f63defe2f075146e)
(cherry picked from commit on googleplex-android-review.googlesource.com host: 341669af524058dd4c64a176ddc54ada589591e1)
Merged-In: Ie281bbdc8788ee64ff99a7c5150da7ce7926235e
---
.../server/pm/PackageManagerService.java | 22 +++++++++++--------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 37b85cf4fe79..27282c0a2dda 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15324,15 +15324,19 @@ public class PackageManagerService extends IPackageManager.Stub
if (disabledPs != null) {
dataOwnerPkg = disabledPs.pkg;
}
- try {
- checkDowngrade(dataOwnerPkg, pkgLite);
- } catch (PackageManagerException e) {
- String errorMsg = "System app: " + packageName
- + " cannot be downgraded to"
- + " older than its preloaded version on the system image. "
- + e.getMessage();
- Slog.w(TAG, errorMsg);
- return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
+ if (!Build.IS_DEBUGGABLE && (dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+ // Only restrict non-debuggable builds and non-debuggable version of
+ // the app
+ try {
+ checkDowngrade(dataOwnerPkg, pkgLite);
+ } catch (PackageManagerException e) {
+ String errorMsg = "System app: " + packageName
+ + " cannot be downgraded to"
+ + " older than its preloaded version on the system image. "
+ + e.getMessage();
+ Slog.w(TAG, errorMsg);
+ return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
+ }
}
}
}

View File

@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Norman <danielnorman@google.com>
Date: Thu, 9 Feb 2023 12:28:26 -0800
Subject: [PATCH] Checks if AccessibilityServiceInfo is within parcelable size.
- If too large when parsing service XMLs then skip this service.
- If too large when a service attempts to update its own info
then throw an error.
Bug: 261589597
Test: atest AccessibilityServiceInfoTest
Change-Id: Iffc0cd48cc713f7904d68059e141cb7de5a4b906
Merged-In: Iffc0cd48cc713f7904d68059e141cb7de5a4b906
(cherry picked from commit on googleplex-android-review.googlesource.com host: 553232c29079fbeab28f95307d025c1426aa7142)
Merged-In: Iffc0cd48cc713f7904d68059e141cb7de5a4b906
---
.../accessibilityservice/AccessibilityService.java | 4 ++++
.../accessibilityservice/AccessibilityServiceInfo.java | 10 ++++++++++
.../accessibility/AccessibilityManagerService.java | 6 ++++++
3 files changed, 20 insertions(+)
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 90b80e73c323..5820dbee7e87 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -1585,6 +1585,10 @@ public abstract class AccessibilityService extends Service {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
if (mInfo != null && connection != null) {
+ if (!mInfo.isWithinParcelableSize()) {
+ throw new IllegalStateException(
+ "Cannot update service info: size is larger than safe parcelable limits.");
+ }
try {
connection.setServiceInfo(mInfo);
mInfo = null;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index cf24b8e1ffa6..3cb35a8723ab 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -31,6 +31,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.hardware.fingerprint.FingerprintManager;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -850,6 +851,15 @@ public class AccessibilityServiceInfo implements Parcelable {
return 0;
}
+ /** @hide */
+ public final boolean isWithinParcelableSize() {
+ final Parcel parcel = Parcel.obtain();
+ writeToParcel(parcel, 0);
+ final boolean result = parcel.dataSize() <= IBinder.MAX_IPC_SIZE;
+ parcel.recycle();
+ return result;
+ }
+
public void writeToParcel(Parcel parcel, int flagz) {
parcel.writeInt(eventTypes);
parcel.writeStringArray(packageNames);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 457f27e679ef..194c90e125f9 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1371,6 +1371,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
AccessibilityServiceInfo accessibilityServiceInfo;
try {
accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
+ if (!accessibilityServiceInfo.isWithinParcelableSize()) {
+ Slog.e(LOG_TAG, "Skipping service "
+ + accessibilityServiceInfo.getResolveInfo().getComponentInfo()
+ + " because service info size is larger than safe parcelable limits.");
+ continue;
+ }
mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
} catch (XmlPullParserException | IOException xppe) {
Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);

View File

@ -0,0 +1,138 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orion Hodson <oth@google.com>
Date: Thu, 7 Apr 2022 21:42:04 +0100
Subject: [PATCH] Uri: check authority and scheme as part of determining URI
path
The interpretation of the path depends on whether the scheme or
authority are specified and should be observed when unparcelling
URIs.
Bug: 171966843
Test: atest FrameworksCoreTests:android.net.UriTest
Test: atest com.android.devicehealthchecks.SystemAppCheck
Change-Id: I06981d1c6e387b16df792494523994518848db37
Merged-In: I06981d1c6e387b16df792494523994518848db37
(cherry picked from commit f37a94ae920fa5879c557603fc285942ec4b84b1)
(cherry picked from commit on googleplex-android-review.googlesource.com host: c87f0623be4042c39a9b73f7a6e02aa116925e50)
Merged-In: I06981d1c6e387b16df792494523994518848db37
---
core/java/android/net/Uri.java | 22 +++++---
.../coretests/src/android/net/UriTest.java | 54 +++++++++++++++++++
2 files changed, 69 insertions(+), 7 deletions(-)
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 8cf182b41566..33acef7f9506 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1194,13 +1194,16 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
}
static Uri readFrom(Parcel parcel) {
- return new HierarchicalUri(
- parcel.readString(),
- Part.readFrom(parcel),
- PathPart.readFrom(parcel),
- Part.readFrom(parcel),
- Part.readFrom(parcel)
- );
+ final String scheme = parcel.readString();
+ final Part authority = Part.readFrom(parcel);
+ // In RFC3986 the path should be determined based on whether there is a scheme or
+ // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3).
+ final boolean hasSchemeOrAuthority =
+ (scheme != null && scheme.length() > 0) || !authority.isEmpty();
+ final PathPart path = PathPart.readFrom(hasSchemeOrAuthority, parcel);
+ final Part query = Part.readFrom(parcel);
+ final Part fragment = Part.readFrom(parcel);
+ return new HierarchicalUri(scheme, authority, path, query, fragment);
}
public int describeContents() {
@@ -2263,6 +2266,11 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
}
}
+ static PathPart readFrom(boolean hasSchemeOrAuthority, Parcel parcel) {
+ final PathPart path = readFrom(parcel);
+ return hasSchemeOrAuthority ? makeAbsolute(path) : path;
+ }
+
/**
* Creates a path from the encoded string.
*
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index f20220c4ab9b..670aefd21d36 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -48,6 +48,7 @@ public class UriTest extends TestCase {
public void testParcelling() {
parcelAndUnparcel(Uri.parse("foo:bob%20lee"));
parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment"));
+ parcelAndUnparcel(Uri.fromParts("https", "www.google.com", null));
parcelAndUnparcel(new Uri.Builder()
.scheme("http")
.authority("crazybob.org")
@@ -873,9 +874,62 @@ public class UriTest extends TestCase {
Throwable targetException = expected.getTargetException();
// Check that the exception was thrown for the correct reason.
assertEquals("Unknown representation: 0", targetException.getMessage());
+ } finally {
+ parcel.recycle();
}
}
+ private Uri buildUriFromRawParcel(boolean argumentsEncoded,
+ String scheme,
+ String authority,
+ String path,
+ String query,
+ String fragment) {
+ // Representation value (from AbstractPart.REPRESENTATION_{ENCODED,DECODED}).
+ final int representation = argumentsEncoded ? 1 : 2;
+ Parcel parcel = Parcel.obtain();
+ try {
+ parcel.writeInt(3); // hierarchical
+ parcel.writeString8(scheme);
+ parcel.writeInt(representation);
+ parcel.writeString8(authority);
+ parcel.writeInt(representation);
+ parcel.writeString8(path);
+ parcel.writeInt(representation);
+ parcel.writeString8(query);
+ parcel.writeInt(representation);
+ parcel.writeString8(fragment);
+ parcel.setDataPosition(0);
+ return Uri.CREATOR.createFromParcel(parcel);
+ } finally {
+ parcel.recycle();
+ }
+ }
+
+ public void testUnparcelMalformedPath() {
+ // Regression tests for b/171966843.
+
+ // Test cases with arguments encoded (covering testing `scheme` * `authority` options).
+ Uri uri0 = buildUriFromRawParcel(true, "https", "google.com", "@evil.com", null, null);
+ assertEquals("https://google.com/@evil.com", uri0.toString());
+ Uri uri1 = buildUriFromRawParcel(true, null, "google.com", "@evil.com", "name=spark", "x");
+ assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString());
+ Uri uri2 = buildUriFromRawParcel(true, "http:", null, "@evil.com", null, null);
+ assertEquals("http::/@evil.com", uri2.toString());
+ Uri uri3 = buildUriFromRawParcel(true, null, null, "@evil.com", null, null);
+ assertEquals("@evil.com", uri3.toString());
+
+ // Test cases with arguments not encoded (covering testing `scheme` * `authority` options).
+ Uri uriA = buildUriFromRawParcel(false, "https", "google.com", "@evil.com", null, null);
+ assertEquals("https://google.com/%40evil.com", uriA.toString());
+ Uri uriB = buildUriFromRawParcel(false, null, "google.com", "@evil.com", null, null);
+ assertEquals("//google.com/%40evil.com", uriB.toString());
+ Uri uriC = buildUriFromRawParcel(false, "http:", null, "@evil.com", null, null);
+ assertEquals("http::/%40evil.com", uriC.toString());
+ Uri uriD = buildUriFromRawParcel(false, null, null, "@evil.com", "name=spark", "y");
+ assertEquals("%40evil.com?name%3Dspark#y", uriD.toString());
+ }
+
public void testToSafeString() {
checkToSafeString("tel:xxxxxx", "tel:Google");
checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890");

View File

@ -0,0 +1,74 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Thomas Stuart <tjstuart@google.com>
Date: Mon, 21 Nov 2022 17:38:21 -0800
Subject: [PATCH] enforce stricter rules when registering phoneAccounts
- include disable accounts when looking up accounts for a package to
check if the limit is reached (10)
- put a new limit of 10 supported schemes
- put a new limit of 256 characters per scheme
- put a new limit of 256 characters per address
- ensure the Icon can write to memory w/o throwing an exception
bug: 259064622
bug: 256819769
Test: cts + unit
Change-Id: Ia7d8d00d9de0fb6694ded6a80c40bd55d7fdf7a7
Merged-In: Ia7d8d00d9de0fb6694ded6a80c40bd55d7fdf7a7
(cherry picked from commit on googleplex-android-review.googlesource.com host: a66a3156e03fbd1c3a29015db9193d66f2709f98)
Merged-In: Ia7d8d00d9de0fb6694ded6a80c40bd55d7fdf7a7
---
.../java/android/telecom/PhoneAccount.java | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 1b783b7beb7f..d0e9a40a1a15 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -466,6 +466,11 @@ public final class PhoneAccount implements Parcelable {
/**
* Sets the address. See {@link PhoneAccount#getAddress}.
+ * <p>
+ * Note: The entire URI value is limited to 256 characters. This check is
+ * enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
+ * {@link IllegalArgumentException} to be thrown if URI is over 256.
*
* @param value The address of the phone account.
* @return The builder.
@@ -499,6 +504,10 @@ public final class PhoneAccount implements Parcelable {
/**
* Sets the icon. See {@link PhoneAccount#getIcon}.
+ * <p>
+ * Note: An {@link IllegalArgumentException} if the Icon cannot be written to memory.
+ * This check is enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}
*
* @param icon The icon to set.
*/
@@ -532,6 +541,10 @@ public final class PhoneAccount implements Parcelable {
/**
* Specifies an additional URI scheme supported by the {@link PhoneAccount}.
*
+ * <p>
+ * Each URI scheme is limited to 256 characters. Adding a scheme over 256 characters will
+ * cause an {@link IllegalArgumentException} to be thrown when the account is registered.
+ *
* @param uriScheme The URI scheme.
* @return The builder.
*/
@@ -545,6 +558,12 @@ public final class PhoneAccount implements Parcelable {
/**
* Specifies the URI schemes supported by the {@link PhoneAccount}.
*
+ * <p>
+ * A max of 10 URI schemes can be added per account. Additionally, each URI scheme is
+ * limited to 256 characters. Adding more than 10 URI schemes or 256 characters on any
+ * scheme will cause an {@link IllegalArgumentException} to be thrown when the account
+ * is registered.
+ *
* @param uriSchemes The URI schemes.
* @return The builder.
*/

View File

@ -0,0 +1,106 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Renouf <mrenouf@google.com>
Date: Wed, 22 Feb 2023 15:14:08 +0000
Subject: [PATCH] Prevent sharesheet from previewing unowned URIs
Bug: 261036568
Test: manually via supplied tool (see bug)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3062b80fb28014a7482d5fa8b2a5c852134a5845)
Merged-In: I21accf6f753d2f676f1602d6e1ce829c5ef29e9a
Change-Id: I21accf6f753d2f676f1602d6e1ce829c5ef29e9a
---
.../android/internal/app/ChooserActivity.java | 36 +++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index f43ff17ed7d0..2e17dce90240 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -16,6 +16,8 @@
package com.android.internal.app;
+import static android.content.ContentProvider.getUserIdFromUri;
+
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.animation.Animator;
@@ -140,6 +142,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -1082,7 +1085,7 @@ public class ChooserActivity extends ResolverActivity {
ImageView previewThumbnailView = contentPreviewLayout.findViewById(
R.id.content_preview_thumbnail);
- if (previewThumbnail == null) {
+ if (!validForContentPreview(previewThumbnail)) {
previewThumbnailView.setVisibility(View.GONE);
} else {
mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
@@ -1109,6 +1112,10 @@ public class ChooserActivity extends ResolverActivity {
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+ if (!validForContentPreview(uri)) {
+ contentPreviewLayout.setVisibility(View.GONE);
+ return contentPreviewLayout;
+ }
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
} else {
ContentResolver resolver = getContentResolver();
@@ -1116,7 +1123,7 @@ public class ChooserActivity extends ResolverActivity {
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
List<Uri> imageUris = new ArrayList<>();
for (Uri uri : uris) {
- if (isImageType(resolver.getType(uri))) {
+ if (validForContentPreview(uri) && isImageType(resolver.getType(uri))) {
imageUris.add(uri);
}
}
@@ -1222,9 +1229,16 @@ public class ChooserActivity extends ResolverActivity {
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+ if (!validForContentPreview(uri)) {
+ contentPreviewLayout.setVisibility(View.GONE);
+ return contentPreviewLayout;
+ }
loadFileUriIntoView(uri, contentPreviewLayout);
} else {
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+ uris = uris.stream()
+ .filter(ChooserActivity::validForContentPreview)
+ .collect(Collectors.toList());
int uriCount = uris.size();
if (uriCount == 0) {
@@ -1278,6 +1292,24 @@ public class ChooserActivity extends ResolverActivity {
}
}
+ /**
+ * Indicate if the incoming content URI should be allowed.
+ *
+ * @param uri the uri to test
+ * @return true if the URI is allowed for content preview
+ */
+ private static boolean validForContentPreview(Uri uri) throws SecurityException {
+ if (uri == null) {
+ return false;
+ }
+ int userId = getUserIdFromUri(uri, UserHandle.USER_CURRENT);
+ if (userId != UserHandle.USER_CURRENT && userId != UserHandle.myUserId()) {
+ Log.e(TAG, "dropped invalid content URI belonging to user " + userId);
+ return false;
+ }
+ return true;
+ }
+
@VisibleForTesting
protected boolean isImageType(String mimeType) {
return mimeType != null && mimeType.startsWith("image/");

View File

@ -0,0 +1,263 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Valentin Iftime <valiiftime@google.com>
Date: Wed, 15 Feb 2023 20:39:44 +0100
Subject: [PATCH] Wait for preloading images to complete before inflating
notifications
NotificationContentInflater waits on SysUiBg thread for images to load, with a timeout
of 1000ms.
Test: 1. Build a test app that posts MessagingStyle notifications with a huge image (8k+) set as data Uri.
2. SystemUi should not ANR
3. adb logcat | grep NotificationInlineImageCache - shows timeout/cancellation logs
Bug: 252766417
Bug: 223859644
(cherry picked from commit 195043f40e46ddcd2fe534a9dac344792d39d91c)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:733089e71ca4b98417586e593a1fb0e50f3a5c61)
Merged-In: I341db60223214cf2282b5c0270e343e1ce95fa01
Change-Id: I341db60223214cf2282b5c0270e343e1ce95fa01
---
.../row/NotificationContentInflater.java | 22 ++++++-
.../row/NotificationInlineImageCache.java | 24 ++++++--
.../row/NotificationInlineImageResolver.java | 57 ++++++++++++++++++-
3 files changed, 92 insertions(+), 11 deletions(-)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index a612a1721c41..29aaf5201412 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -475,6 +475,7 @@ public class NotificationContentInflater {
CancellationSignal cancellationSignal = new CancellationSignal();
cancellationSignal.setOnCancelListener(
() -> runningInflations.values().forEach(CancellationSignal::cancel));
+
return cancellationSignal;
}
@@ -751,6 +752,7 @@ public class NotificationContentInflater {
public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress>
implements InflationCallback, InflationTask {
+ private static final long IMG_PRELOAD_TIMEOUT_MS = 1000L;
private final StatusBarNotification mSbn;
private final Context mContext;
private final boolean mInflateSynchronously;
@@ -817,9 +819,15 @@ public class NotificationContentInflater {
InflationProgress inflationProgress = createRemoteViews(mReInflateFlags,
recoveredBuilder, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight,
mUsesIncreasedHeadsUpHeight, packageContext);
- return inflateSmartReplyViews(inflationProgress, mReInflateFlags, mRow.getEntry(),
+
+ InflationProgress result = inflateSmartReplyViews(inflationProgress, mReInflateFlags, mRow.getEntry(),
mRow.getContext(), packageContext, mRow.getHeadsUpManager(),
mRow.getExistingSmartRepliesAndActions());
+
+ // wait for image resolver to finish preloading
+ mRow.getImageResolver().waitForPreloadedImages(IMG_PRELOAD_TIMEOUT_MS);
+
+ return result;
} catch (Exception e) {
mError = e;
return null;
@@ -842,8 +850,13 @@ public class NotificationContentInflater {
final String ident = sbn.getPackageName() + "/0x"
+ Integer.toHexString(sbn.getId());
Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
- mCallback.handleInflationException(sbn,
- new InflationException("Couldn't inflate contentViews" + e));
+ if (mCallback != null) {
+ mCallback.handleInflationException(sbn,
+ new InflationException("Couldn't inflate contentViews" + e));
+ }
+
+ // Cancel any image loading tasks, not useful any more
+ mRow.getImageResolver().cancelRunningTasks();
}
@Override
@@ -877,6 +890,9 @@ public class NotificationContentInflater {
// Notify the resolver that the inflation task has finished,
// try to purge unnecessary cached entries.
mRow.getImageResolver().purgeCache();
+
+ // Cancel any image loading tasks that have not completed at this point
+ mRow.getImageResolver().cancelRunningTasks();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
index 4b0e2ffd5d7f..6fdc8a3dce0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
@@ -21,10 +21,12 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
-import java.io.IOException;
import java.util.Set;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* A cache for inline images of image messages.
@@ -57,12 +59,13 @@ public class NotificationInlineImageCache implements NotificationInlineImageReso
}
@Override
- public Drawable get(Uri uri) {
+ public Drawable get(Uri uri, long timeoutMs) {
Drawable result = null;
try {
- result = mCache.get(uri).get();
- } catch (InterruptedException | ExecutionException ex) {
- Log.d(TAG, "get: Failed get image from " + uri);
+ result = mCache.get(uri).get(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException | ExecutionException
+ | TimeoutException | CancellationException ex) {
+ Log.d(TAG, "get: Failed get image from " + uri + " " + ex);
}
return result;
}
@@ -73,6 +76,15 @@ public class NotificationInlineImageCache implements NotificationInlineImageReso
mCache.entrySet().removeIf(entry -> !wantedSet.contains(entry.getKey()));
}
+ @Override
+ public void cancelRunningTasks() {
+ mCache.forEach((key, value) -> {
+ if (value.getStatus() != AsyncTask.Status.FINISHED) {
+ value.cancel(true);
+ }
+ });
+ }
+
private static class PreloadImageTask extends AsyncTask<Uri, Void, Drawable> {
private final NotificationInlineImageResolver mResolver;
@@ -87,7 +99,7 @@ public class NotificationInlineImageCache implements NotificationInlineImageReso
try {
drawable = mResolver.resolveImage(target);
- } catch (IOException | SecurityException ex) {
+ } catch (Exception ex) {
Log.d(TAG, "PreloadImageTask: Resolve failed from " + target, ex);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
index a3e13053d169..466be072afdb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
@@ -23,6 +23,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
+import android.os.SystemClock;
import android.util.Log;
import com.android.internal.widget.ImageResolver;
@@ -40,6 +41,9 @@ import java.util.Set;
public class NotificationInlineImageResolver implements ImageResolver {
private static final String TAG = NotificationInlineImageResolver.class.getSimpleName();
+ // Timeout for loading images from ImageCache when calling from UI thread
+ private static final long MAX_UI_THREAD_TIMEOUT_MS = 100L;
+
private final Context mContext;
private final ImageCache mImageCache;
private Set<Uri> mWantedUriSet;
@@ -76,17 +80,37 @@ public class NotificationInlineImageResolver implements ImageResolver {
return LocalImageResolver.resolveImage(uri, mContext);
}
+ /**
+ * Loads an image from the Uri.
+ * This method is synchronous and is usually called from the Main thread.
+ * It will time-out after MAX_UI_THREAD_TIMEOUT_MS.
+ *
+ * @param uri Uri of the target image.
+ * @return drawable of the image, null if loading failed/timeout
+ */
@Override
public Drawable loadImage(Uri uri) {
Drawable result = null;
try {
- result = hasCache() ? mImageCache.get(uri) : resolveImage(uri);
+ if (hasCache()) {
+ result = loadImageFromCache(uri, MAX_UI_THREAD_TIMEOUT_MS);
+ } else {
+ result = resolveImage(uri);
+ }
} catch (IOException | SecurityException ex) {
Log.d(TAG, "loadImage: Can't load image from " + uri, ex);
}
return result;
}
+ private Drawable loadImageFromCache(Uri uri, long timeoutMs) {
+ // if the uri isn't currently cached, try caching it first
+ if (!mImageCache.hasEntry(uri)) {
+ mImageCache.preload((uri));
+ }
+ return mImageCache.get(uri, timeoutMs);
+ }
+
/**
* Resolve the message list from specified notification and
* refresh internal cache according to the result.
@@ -158,6 +182,30 @@ public class NotificationInlineImageResolver implements ImageResolver {
return mWantedUriSet;
}
+ /**
+ * Wait for a maximum timeout for images to finish preloading
+ * @param timeoutMs total timeout time
+ */
+ void waitForPreloadedImages(long timeoutMs) {
+ if (!hasCache()) {
+ return;
+ }
+ Set<Uri> preloadedUris = getWantedUriSet();
+ if (preloadedUris != null) {
+ // Decrement remaining timeout after each image check
+ long endTimeMs = SystemClock.elapsedRealtime() + timeoutMs;
+ preloadedUris.forEach(
+ uri -> loadImageFromCache(uri, endTimeMs - SystemClock.elapsedRealtime()));
+ }
+ }
+
+ void cancelRunningTasks() {
+ if (!hasCache()) {
+ return;
+ }
+ mImageCache.cancelRunningTasks();
+ }
+
/**
* A interface for internal cache implementation of this resolver.
*/
@@ -167,7 +215,7 @@ public class NotificationInlineImageResolver implements ImageResolver {
* @param uri The uri of the image.
* @return Drawable of the image.
*/
- Drawable get(Uri uri);
+ Drawable get(Uri uri, long timeoutMs);
/**
* Set the image resolver that actually resolves image from specified uri.
@@ -192,6 +240,11 @@ public class NotificationInlineImageResolver implements ImageResolver {
* Purge unnecessary entries in the cache.
*/
void purge();
+
+ /**
+ * Cancel all unfinished image loading tasks
+ */
+ void cancelRunningTasks();
}
}

View File

@ -0,0 +1,167 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Lee <brnlee@google.com>
Date: Fri, 17 Feb 2023 16:05:17 -0800
Subject: [PATCH] Check key intent for selectors and prohibited flags
Bug: 265015796
Test: atest
FrameworksServicesTests: com.android.server.accounts.AccountManagerServiceTest
(cherry picked from commit e53a96304352e2965176c8d32ac1b504e52ef185)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:92114886bdce8467c52c655c186f3e7ab1e134d8)
Merged-In: Ie16f8654337bd75eaad3156817470674b4f0cee3
Change-Id: Ie16f8654337bd75eaad3156817470674b4f0cee3
---
.../accounts/AccountManagerService.java | 18 +++++++---
.../accounts/AccountManagerServiceTest.java | 36 +++++++++++++++++++
.../AccountManagerServiceTestFixtures.java | 5 ++-
.../TestAccountType1Authenticator.java | 5 +--
4 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index b4edf94927b2..a9c7b0c6a3f1 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -4808,10 +4808,6 @@ public class AccountManagerService
if (intent.getClipData() == null) {
intent.setClipData(ClipData.newPlainText(null, null));
}
- intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
- | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION));
long bid = Binder.clearCallingIdentity();
try {
PackageManager pm = mContext.getPackageManager();
@@ -4858,7 +4854,19 @@ public class AccountManagerService
if (intent == null) {
return (simulateIntent == null);
}
- return intent.filterEquals(simulateIntent);
+ if (!intent.filterEquals(simulateIntent)) {
+ return false;
+ }
+
+ if (intent.getSelector() != simulateIntent.getSelector()) {
+ return false;
+ }
+
+ int prohibitedFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
+ return (simulateIntent.getFlags() & prohibitedFlags) == 0;
}
private boolean isExportedSystemActivity(ActivityInfo activityInfo) {
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 215f1e8e2a9e..d379e8131268 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -18,6 +18,7 @@ package com.android.server.accounts;
import static android.database.sqlite.SQLiteDatabase.deleteDatabase;
+import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
@@ -686,6 +687,41 @@ public class AccountManagerServiceTest extends AndroidTestCase {
assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK));
}
+ @SmallTest
+ public void testStartAddAccountSessionWhereAuthenticatorReturnsIntentWithProhibitedFlags()
+ throws Exception {
+ unlockSystemUser();
+ ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = new ActivityInfo();
+ resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
+ when(mMockPackageManager.resolveActivityAsUser(
+ any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
+ when(mMockPackageManager.checkSignatures(
+ anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ Response response = new Response(latch, mMockAccountManagerResponse);
+ Bundle options = createOptionsWithAccountName(
+ AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE);
+ int prohibitedFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
+ options.putInt(AccountManagerServiceTestFixtures.KEY_INTENT_FLAGS, prohibitedFlags);
+
+ mAms.startAddAccountSession(
+ response, // response
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType
+ "authTokenType",
+ null, // requiredFeatures
+ true, // expectActivityLaunch
+ options); // optionsIn
+ waitForLatch(latch);
+
+ verify(mMockAccountManagerResponse).onError(
+ eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), contains("invalid intent"));
+ }
+
@SmallTest
public void testStartAddAccountSessionError() throws Exception {
unlockSystemUser();
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
index 73f30d9f9e79..b98a6a891d55 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
@@ -17,9 +17,6 @@ package com.android.server.accounts;
import android.accounts.Account;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Constants shared between test AccountAuthenticators and AccountManagerServiceTest.
*/
@@ -31,6 +28,8 @@ public final class AccountManagerServiceTestFixtures {
"account_manager_service_test:account_status_token_key";
public static final String KEY_ACCOUNT_PASSWORD =
"account_manager_service_test:account_password_key";
+ public static final String KEY_INTENT_FLAGS =
+ "account_manager_service_test:intent_flags_key";
public static final String KEY_OPTIONS_BUNDLE =
"account_manager_service_test:option_bundle_key";
public static final String ACCOUNT_NAME_SUCCESS = "success_on_return@fixture.com";
diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
index 8106364477d9..924443e9d5cf 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
@@ -24,8 +24,6 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import com.android.frameworks.servicestests.R;
-
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -270,11 +268,13 @@ public class TestAccountType1Authenticator extends AbstractAccountAuthenticator
String accountName = null;
Bundle sessionBundle = null;
String password = null;
+ int intentFlags = 0;
if (options != null) {
accountName = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME);
sessionBundle = options.getBundle(
AccountManagerServiceTestFixtures.KEY_ACCOUNT_SESSION_BUNDLE);
password = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_PASSWORD);
+ intentFlags = options.getInt(AccountManagerServiceTestFixtures.KEY_INTENT_FLAGS, 0);
}
Bundle result = new Bundle();
@@ -302,6 +302,7 @@ public class TestAccountType1Authenticator extends AbstractAccountAuthenticator
intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT,
eventualActivityResultData);
intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
+ intent.setFlags(intentFlags);
result.putParcelable(AccountManager.KEY_INTENT, intent);
} else {

View File

@ -0,0 +1,79 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kweku Adams <kwekua@google.com>
Date: Wed, 21 Sep 2022 22:13:01 +0000
Subject: [PATCH] Handle invalid data during job loading.
Catch exceptions that may be thrown if invalid data ended up in the
persisted job file.
Bug: 246541702
Bug: 246542132
Bug: 246542285
Bug: 246542330
Test: install test app with invalid job config, start app to schedule job, then reboot device
(cherry picked from commit c98fb42b480b3beedc2d94de6110f50212c4aa0b)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:df1ba00dd9f64a3ae9a9e05979dfae6a15c7e203)
Merged-In: Id0ceba345942baf21177f687b8dd85ef001c0a9e
Change-Id: Id0ceba345942baf21177f687b8dd85ef001c0a9e
---
.../java/com/android/server/job/JobStore.java | 26 ++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 4ef37a2e484d..1f2772571e71 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -677,6 +677,10 @@ public final class JobStore {
}
} catch (XmlPullParserException | IOException e) {
Slog.wtf(TAG, "Error jobstore xml.", e);
+ } catch (Exception e) {
+ // Crashing at this point would result in a boot loop, so live with a general
+ // Exception for system stability's sake.
+ Slog.wtf(TAG, "Unexpected exception", e);
} finally {
if (mPersistInfo.countAllJobsLoaded < 0) { // Only set them once.
mPersistInfo.countAllJobsLoaded = numJobs;
@@ -807,6 +811,15 @@ public final class JobStore {
} catch (NumberFormatException e) {
Slog.d(TAG, "Error reading constraints, skipping.");
return null;
+ } catch (XmlPullParserException e) {
+ Slog.d(TAG, "Error Parser Exception.", e);
+ return null;
+ } catch (IOException e) {
+ Slog.d(TAG, "Error I/O Exception.", e);
+ return null;
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Constraints contained invalid data", e);
+ return null;
}
parser.next(); // Consume </constraints>
@@ -902,8 +915,14 @@ public final class JobStore {
return null;
}
- PersistableBundle extras = PersistableBundle.restoreFromXml(parser);
- jobBuilder.setExtras(extras);
+ final PersistableBundle extras;
+ try {
+ extras = PersistableBundle.restoreFromXml(parser);
+ jobBuilder.setExtras(extras);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Persisted extras contained invalid data", e);
+ return null;
+ }
parser.nextTag(); // Consume </extras>
final JobInfo builtJob;
@@ -950,7 +969,8 @@ public final class JobStore {
return new JobInfo.Builder(jobId, cname);
}
- private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
+ private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
String val;
final String netCapabilities = parser.getAttributeValue(null, "net-capabilities");

View File

@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Groover <mpgroover@google.com>
Date: Fri, 31 Mar 2023 21:31:22 +0000
Subject: [PATCH] Limit the number of supported v1 and v2 signers
The v1 and v2 APK Signature Schemes support multiple signers; this
was intended to allow multiple entities to sign an APK. Previously,
the platform had no limits placed on the number of signers supported
in an APK, but this commit sets a hard limit of 10 supported signers
for these signature schemes to ensure a large number of signers
does not place undue burden on the platform.
Bug: 266580022
Test: Manually verified the platform only allowed an APK with the
maximum number of supported signers.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6f6ee8a55f37c2b8c0df041b2bd53ec928764597)
Merged-In: I6aa86b615b203cdc69d58a593ccf8f18474ca091
Change-Id: I6aa86b615b203cdc69d58a593ccf8f18474ca091
---
.../util/apk/ApkSignatureSchemeV2Verifier.java | 10 ++++++++++
core/java/android/util/jar/StrictJarVerifier.java | 11 +++++++++++
2 files changed, 21 insertions(+)
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index b36888e23f9c..0fa5358e9b86 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -83,6 +83,11 @@ public class ApkSignatureSchemeV2Verifier {
private static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a;
+ /**
+ * The maximum number of signers supported by the v2 APK signature scheme.
+ */
+ private static final int MAX_V2_SIGNERS = 10;
+
/**
* Returns {@code true} if the provided APK contains an APK Signature Scheme V2 signature.
*
@@ -188,6 +193,11 @@ public class ApkSignatureSchemeV2Verifier {
}
while (signers.hasRemaining()) {
signerCount++;
+ if (signerCount > MAX_V2_SIGNERS) {
+ throw new SecurityException(
+ "APK Signature Scheme v2 only supports a maximum of " + MAX_V2_SIGNERS
+ + " signers");
+ }
try {
ByteBuffer signer = getLengthPrefixedSlice(signers);
X509Certificate[] certs = verifySigner(signer, contentDigests, certFactory);
diff --git a/core/java/android/util/jar/StrictJarVerifier.java b/core/java/android/util/jar/StrictJarVerifier.java
index 45254908c5c9..a6aca330d323 100644
--- a/core/java/android/util/jar/StrictJarVerifier.java
+++ b/core/java/android/util/jar/StrictJarVerifier.java
@@ -78,6 +78,11 @@ class StrictJarVerifier {
"SHA1",
};
+ /**
+ * The maximum number of signers supported by the JAR signature scheme.
+ */
+ private static final int MAX_JAR_SIGNERS = 10;
+
private final String jarName;
private final StrictJarManifest manifest;
private final HashMap<String, byte[]> metaEntries;
@@ -293,10 +298,16 @@ class StrictJarVerifier {
return false;
}
+ int signerCount = 0;
Iterator<String> it = metaEntries.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
if (key.endsWith(".DSA") || key.endsWith(".RSA") || key.endsWith(".EC")) {
+ if (++signerCount > MAX_JAR_SIGNERS) {
+ throw new SecurityException(
+ "APK Signature Scheme v1 only supports a maximum of " + MAX_JAR_SIGNERS
+ + " signers");
+ }
verifyCertificate(key);
it.remove();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Nate(Qiang) Jiang" <qiangjiang@google.com>
Date: Thu, 13 Apr 2023 21:20:37 +0000
Subject: [PATCH] DO NOT MERGE: Add size check on PPS#policy
Bug: 275340417
Test: atest android.net.wifi
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d1afd2c47d086e0365bf6814a9f47555c294769f)
Merged-In: I6e6128b7ed5327da8dbc9186a82bef0f2e4197bb
Change-Id: I6e6128b7ed5327da8dbc9186a82bef0f2e4197bb
---
.../android/net/wifi/hotspot2/pps/Policy.java | 28 ++++++++++++++++---
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index b0a2cc397c53..4bdacebda060 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -16,6 +16,9 @@
package android.net.wifi.hotspot2.pps;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_ENTRIES;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH;
+
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -269,11 +272,19 @@ public final class Policy implements Parcelable {
*/
public boolean validate() {
if (TextUtils.isEmpty(mFqdn)) {
- Log.d(TAG, "Missing FQDN");
+ Log.e(TAG, "Missing FQDN");
+ return false;
+ }
+ if (mFqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.e(TAG, "FQDN is too long");
return false;
}
if (TextUtils.isEmpty(mCountries)) {
- Log.d(TAG, "Missing countries");
+ Log.e(TAG, "Missing countries");
+ return false;
+ }
+ if (mCountries.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.e(TAG, "country is too long");
return false;
}
return true;
@@ -449,7 +460,7 @@ public final class Policy implements Parcelable {
}
for (String ssid : mExcludedSsidList) {
if (ssid.getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
- Log.d(TAG, "Invalid SSID: " + ssid);
+ Log.e(TAG, "Invalid SSID: " + ssid);
return false;
}
}
@@ -457,15 +468,24 @@ public final class Policy implements Parcelable {
// Validate required protocol to port map.
if (mRequiredProtoPortMap != null) {
for (Map.Entry<Integer, String> entry : mRequiredProtoPortMap.entrySet()) {
+ int protocol = entry.getKey();
+ if (protocol < 0 || protocol > 255) {
+ Log.e(TAG, "Invalid IP protocol: " + protocol);
+ return false;
+ }
String portNumber = entry.getValue();
if (portNumber.getBytes(StandardCharsets.UTF_8).length > MAX_PORT_STRING_BYTES) {
- Log.d(TAG, "PortNumber string bytes exceeded the max: " + portNumber);
+ Log.e(TAG, "PortNumber string bytes exceeded the max: " + portNumber);
return false;
}
}
}
// Validate preferred roaming partner list.
if (mPreferredRoamingPartnerList != null) {
+ if (mPreferredRoamingPartnerList.size() > MAX_NUMBER_OF_ENTRIES) {
+ Log.e(TAG, "Number of the Preferred Roaming Partner exceed the limit");
+ return false;
+ }
for (RoamingPartner partner : mPreferredRoamingPartnerList) {
if (!partner.validate()) {
return false;

View File

@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Nate(Qiang) Jiang" <qiangjiang@google.com>
Date: Wed, 12 Apr 2023 18:32:50 +0000
Subject: [PATCH] DO NOT MERGE: Limit the ServiceFriendlyNames
Bug: 274445194
Test: atest android.net.wifi
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6b1746ab6f0ff4020c78381833554f20344c2e2a)
Merged-In: Id4e16007531ba1ce3e3f9fa3d3111b5af57751be
Change-Id: Id4e16007531ba1ce3e3f9fa3d3111b5af57751be
---
.../wifi/hotspot2/PasspointConfiguration.java | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 9095b5d927a2..dd23e504c467 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -597,6 +597,23 @@ public final class PasspointConfiguration implements Parcelable {
}
}
}
+ if (mServiceFriendlyNames != null) {
+ if (mServiceFriendlyNames.size() > MAX_NUMBER_OF_ENTRIES) {
+ Log.e(TAG, "ServiceFriendlyNames exceed the max!");
+ return false;
+ }
+ for (Map.Entry<String, String> names : mServiceFriendlyNames.entrySet()) {
+ if (names.getKey() == null || names.getValue() == null) {
+ Log.e(TAG, "Service friendly name entry should not be null");
+ return false;
+ }
+ if (names.getKey().length() > MAX_STRING_LENGTH
+ || names.getValue().length() > MAX_STRING_LENGTH) {
+ Log.e(TAG, "Service friendly name is to long");
+ return false;
+ }
+ }
+ }
return true;
}

View File

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Winson Chung <winsonc@google.com>
Date: Wed, 8 Feb 2023 01:04:46 +0000
Subject: [PATCH] Only allow NEW_TASK flag when adjusting pending intents
Bug: 243794108
Test: atest CtsSecurityBulletinHostTestCases:android.security.cts.CVE_2023_20918
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c62d2e1021a030f4f0ae5fcfc8fe8e0875fa669f)
Merged-In: I5d329beecef1902c36704e93d0bc5cb60d0e2f5b
Change-Id: I5d329beecef1902c36704e93d0bc5cb60d0e2f5b
---
core/java/android/app/ActivityOptions.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 36ab62aedc09..c8f54fd275ee 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -20,6 +20,8 @@ import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIO
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.Nullable;
@@ -1262,7 +1264,9 @@ public class ActivityOptions extends ComponentOptions {
* @hide
*/
public int getPendingIntentLaunchFlags() {
- return mPendingIntentLaunchFlags;
+ // b/243794108: Ignore all flags except the new task flag, to be reconsidered in b/254490217
+ return mPendingIntentLaunchFlags &
+ (FLAG_ACTIVITY_NEW_TASK | FLAG_RECEIVER_FOREGROUND);
}
/**

View File

@ -19,8 +19,7 @@ Cherry-picking this CL as a security fix
Bug: 222446076
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:09f004722284ef6b9790ddf9338a1708b3f0833c)
Merged-In: If4360dd6ae2e5f79b43eaf1a29687ac9cc4b6101
AOSP-Change-Id: If4360dd6ae2e5f79b43eaf1a29687ac9cc4b6101
Change-Id: Id6eb8eff88481f9ec2c9cbcde9d7b0f78a349d98
Change-Id: If4360dd6ae2e5f79b43eaf1a29687ac9cc4b6101
---
.../src/com/android/keyguard/KeyguardSecurityContainer.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

View File

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ioana Alexandru <aioana@google.com>
Date: Fri, 28 Apr 2023 14:11:04 +0000
Subject: [PATCH] DO NOT MERGE Increase notification channel limit.
This was previously reduced because it can cause an out of memory error or be abused to trigger a permanent denial of service, but it breaks some messages apps in Android 11, as they are creating too many channels. Rolling it back until the apps are fixed to reduce user impact.
Bug: 279447569
Bug: 261723753
Test: N/A, this was previously 50k
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5664378a7cac48184ec0702a41aaed0677d41136)
Merged-In: Id8da382f812d4abb8db723c40a61366a7402da4f
Change-Id: Id8da382f812d4abb8db723c40a61366a7402da4f
---
.../java/com/android/server/notification/PreferencesHelper.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 1a3779f7c607..32d1e7e53b6b 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -73,7 +73,7 @@ public class PreferencesHelper implements RankingConfig {
private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":";
@VisibleForTesting
- static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
+ static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 50000;
@VisibleForTesting
static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 6000;

View File

@ -0,0 +1,127 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ioana Alexandru <aioana@google.com>
Date: Thu, 27 Apr 2023 12:36:05 +0000
Subject: [PATCH] Visit URIs in landscape/portrait custom remote views.
Bug: 277740848
Test: atest RemoteViewsTest NotificationManagerServiceTest & tested with POC from bug
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e8acb2f660bdb03616989852f9dbbf1726f8237e)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:43e1ae4e0d408604b9e3c18ac0e9bf87529b92a8)
Merged-In: I7d3d35df0ec38945019f71755bed8797b7af4517
Change-Id: I7d3d35df0ec38945019f71755bed8797b7af4517
---
core/java/android/widget/RemoteViews.java | 6 ++
.../src/android/widget/RemoteViewsTest.java | 64 +++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 86cec5e0f0a2..21d38b559736 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -554,6 +554,12 @@ public class RemoteViews implements Parcelable, Filter {
mActions.get(i).visitUris(visitor);
}
}
+ if (mLandscape != null) {
+ mLandscape.visitUris(visitor);
+ }
+ if (mPortrait != null) {
+ mPortrait.visitUris(visitor);
+ }
}
private static void visitIconUri(Icon icon, @NonNull Consumer<Uri> visitor) {
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 8cb7e1b95245..46f2c0928fc3 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -20,6 +20,10 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.app.ActivityOptions;
import android.app.PendingIntent;
@@ -29,6 +33,8 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Parcel;
@@ -50,6 +56,7 @@ import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
+import java.util.function.Consumer;
/**
* Tests for RemoteViews.
@@ -499,4 +506,61 @@ public class RemoteViewsTest {
return null;
}
}
+
+ @Test
+ public void visitUris() {
+ RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
+
+ final Uri imageUri = Uri.parse("content://media/image");
+ final Icon icon1 = Icon.createWithContentUri("content://media/icon1");
+ final Icon icon2 = Icon.createWithContentUri("content://media/icon2");
+ final Icon icon3 = Icon.createWithContentUri("content://media/icon3");
+ final Icon icon4 = Icon.createWithContentUri("content://media/icon4");
+ views.setImageViewUri(R.id.image, imageUri);
+ views.setTextViewCompoundDrawables(R.id.text, icon1, icon2, icon3, icon4);
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ views.visitUris(visitor);
+ verify(visitor, times(1)).accept(eq(imageUri));
+ verify(visitor, times(1)).accept(eq(icon1.getUri()));
+ verify(visitor, times(1)).accept(eq(icon2.getUri()));
+ verify(visitor, times(1)).accept(eq(icon3.getUri()));
+ verify(visitor, times(1)).accept(eq(icon4.getUri()));
+ }
+
+ @Test
+ public void visitUris_separateOrientation() {
+ final RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test);
+ final Uri imageUriL = Uri.parse("content://landscape/image");
+ final Icon icon1L = Icon.createWithContentUri("content://landscape/icon1");
+ final Icon icon2L = Icon.createWithContentUri("content://landscape/icon2");
+ final Icon icon3L = Icon.createWithContentUri("content://landscape/icon3");
+ final Icon icon4L = Icon.createWithContentUri("content://landscape/icon4");
+ landscape.setImageViewUri(R.id.image, imageUriL);
+ landscape.setTextViewCompoundDrawables(R.id.text, icon1L, icon2L, icon3L, icon4L);
+
+ final RemoteViews portrait = new RemoteViews(mPackage, 33);
+ final Uri imageUriP = Uri.parse("content://portrait/image");
+ final Icon icon1P = Icon.createWithContentUri("content://portrait/icon1");
+ final Icon icon2P = Icon.createWithContentUri("content://portrait/icon2");
+ final Icon icon3P = Icon.createWithContentUri("content://portrait/icon3");
+ final Icon icon4P = Icon.createWithContentUri("content://portrait/icon4");
+ portrait.setImageViewUri(R.id.image, imageUriP);
+ portrait.setTextViewCompoundDrawables(R.id.text, icon1P, icon2P, icon3P, icon4P);
+
+ RemoteViews views = new RemoteViews(landscape, portrait);
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ views.visitUris(visitor);
+ verify(visitor, times(1)).accept(eq(imageUriL));
+ verify(visitor, times(1)).accept(eq(icon1L.getUri()));
+ verify(visitor, times(1)).accept(eq(icon2L.getUri()));
+ verify(visitor, times(1)).accept(eq(icon3L.getUri()));
+ verify(visitor, times(1)).accept(eq(icon4L.getUri()));
+ verify(visitor, times(1)).accept(eq(imageUriP));
+ verify(visitor, times(1)).accept(eq(icon1P.getUri()));
+ verify(visitor, times(1)).accept(eq(icon2P.getUri()));
+ verify(visitor, times(1)).accept(eq(icon3P.getUri()));
+ verify(visitor, times(1)).accept(eq(icon4P.getUri()));
+ }
}

View File

@ -0,0 +1,109 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jing Ji <jji@google.com>
Date: Tue, 25 Oct 2022 22:39:52 -0700
Subject: [PATCH] DO NOT MERGE: ActivityManager#killBackgroundProcesses can
kill caller's own app only
unless it's a system app.
Bug: 239423414
Bug: 223376078
Test: atest CtsAppTestCases:ActivityManagerTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8b382775b258220466a977453905797521e159de)
Merged-In: Iac6baa889965b8ffecd9a43179a4c96632ad1d02
Change-Id: Iac6baa889965b8ffecd9a43179a4c96632ad1d02
---
core/java/android/app/ActivityManager.java | 3 ++
core/res/AndroidManifest.xml | 6 +++-
.../server/am/ActivityManagerService.java | 32 +++++++++++++++++--
3 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 556b60bafd16..eff49bc1fe95 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3452,6 +3452,9 @@ public class ActivityManager {
* processes to reclaim memory; the system will take care of restarting
* these processes in the future as needed.
*
+ * <p class="note">Third party applications can only use this API to kill their own processes.
+ * </p>
+ *
* @param packageName The name of the package whose processes are to
* be killed.
*/
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 586d9a819d1e..a8dd041454c9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2379,7 +2379,11 @@
android:protectionLevel="normal" />
<!-- Allows an application to call
- {@link android.app.ActivityManager#killBackgroundProcesses}.
+ {@link android.app.ActivityManager#killBackgroundProcesses}.
+
+ <p class="note">Third party applications can only use this API to kill their own
+ processes.</p>
+
<p>Protection level: normal
-->
<permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index efbccb3b8f94..9bf5898102d4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4148,8 +4148,20 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int callingAppId = UserHandle.getAppId(callingUid);
- userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ ProcessRecord proc;
+ synchronized (mPidsSelfLocked) {
+ proc = mPidsSelfLocked.get(callingPid);
+ }
+ final boolean hasKillAllPermission = PERMISSION_GRANTED == checkPermission(
+ android.Manifest.permission.FORCE_STOP_PACKAGES, callingPid, callingUid)
+ || UserHandle.isCore(callingUid)
+ || (proc != null && proc.info.isSystemApp());
+
+ userId = mUserController.handleIncomingUser(callingPid, callingUid,
userId, true, ALLOW_FULL_ONLY, "killBackgroundProcesses", null);
final int[] userIds = mUserController.expandUserId(userId);
@@ -4164,7 +4176,7 @@ public class ActivityManagerService extends IActivityManager.Stub
targetUserId));
} catch (RemoteException e) {
}
- if (appId == -1) {
+ if (appId == -1 || (!hasKillAllPermission && appId != callingAppId)) {
Slog.w(TAG, "Invalid packageName: " + packageName);
return;
}
@@ -4189,6 +4201,22 @@ public class ActivityManagerService extends IActivityManager.Stub
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) {

View File

@ -0,0 +1,104 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Austin Borger <borgera@google.com>
Date: Sat, 18 Mar 2023 12:56:12 -0700
Subject: [PATCH] ActivityManagerService: Allow openContentUri from
vendor/system/product.
Apps should not have direct access to this entry point. Check that the
caller is a vendor, system, or product package.
Test: Ran PoC app and CtsMediaPlayerTestCases.
Bug: 236688380
(cherry picked from commit d0ba7467c2cb2815f94f6651cbb1c2f405e8e9c7)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:821f4c0d8ba06be32ce9b46c7a7c09d1cacd7b0e)
Merged-In: I0335496d28fa5fc3bfe1fecd4be90040b0b3687f
Change-Id: I0335496d28fa5fc3bfe1fecd4be90040b0b3687f
---
.../server/am/ActivityManagerService.java | 59 ++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9bf5898102d4..ec8841debb7a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -160,6 +160,7 @@ import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.app.ApplicationErrorReport;
import android.app.ApplicationThreadConstants;
+import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.ContentProviderHolder;
import android.app.Dialog;
@@ -7865,7 +7866,54 @@ public class ActivityManagerService extends IActivityManager.Stub
Binder token = new Binder();
sCallerIdentity.set(new Identity(
token, Binder.getCallingPid(), Binder.getCallingUid()));
+ boolean handlingSecurityViolation = false;
try {
+ // This method is exposed to the VNDK and to avoid changing its
+ // signature we just use the first package in the UID. For shared
+ // UIDs we may blame the wrong app but that is Okay as they are
+ // in the same security/privacy sandbox.
+ final int uid = Binder.getCallingUid();
+ // Here we handle some of the special UIDs (mediaserver, systemserver, etc)
+ // Note: This is moved to AppOpsManager.resolvePackageName in future versions.
+ final String packageName;
+ if (uid == Process.ROOT_UID) {
+ packageName = "root";
+ } else if (uid == Process.SHELL_UID) {
+ packageName = "com.android.shell";
+ } else if (uid == Process.MEDIA_UID) {
+ packageName = "media";
+ } else if (uid == Process.AUDIOSERVER_UID) {
+ packageName = "audioserver";
+ } else if (uid == Process.CAMERASERVER_UID) {
+ packageName = "cameraserver";
+ } else if (uid == Process.SYSTEM_UID) {
+ packageName = "android";
+ } else {
+ packageName = null;
+ }
+
+ final PackageParser.Package androidPackage;
+ if (packageName != null) {
+ androidPackage = mPackageManagerInt.getPackage(packageName);
+ } else {
+ androidPackage = mPackageManagerInt.getPackage(uid);
+ }
+ if (androidPackage == null) {
+ Log.e(TAG, "Cannot find package for uid: " + uid);
+ handlingSecurityViolation = true;
+ return null;
+ }
+
+ final ApplicationInfo appInfo = mPackageManagerInt.getApplicationInfo(
+ androidPackage.packageName, /*flags*/0, Process.SYSTEM_UID,
+ UserHandle.USER_SYSTEM);
+ if (!appInfo.isVendor() && !appInfo.isSystemApp()
+ && !appInfo.isProduct()) {
+ Log.e(TAG, "openContentUri may only be used by vendor/system/product.");
+ handlingSecurityViolation = true;
+ return null;
+ }
+
pfd = cph.provider.openFile(null, uri, "r", null, token);
} catch (FileNotFoundException e) {
// do nothing; pfd will be returned null
@@ -7873,7 +7921,16 @@ public class ActivityManagerService extends IActivityManager.Stub
// Ensure that whatever happens, we clean up the identity state
sCallerIdentity.remove();
// Ensure we're done with the provider.
- removeContentProviderExternalUnchecked(name, null, userId);
+ try {
+ removeContentProviderExternalUnchecked(name, null, userId);
+ } catch (SecurityException e) {
+ // A SecurityException may be thrown from computeOomAdjLocked if the calling
+ // UID is that of a malicious app accessing this hidden API. In that case
+ // we're already handling that by returning null, so tolerate this.
+ if (!handlingSecurityViolation) {
+ throw e;
+ }
+ }
}
} else {
Slog.d(TAG, "Failed to get provider for authority '" + name + "'");

View File

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Beverly <beverlyt@google.com>
Date: Mon, 8 May 2023 16:33:12 +0000
Subject: [PATCH] On device lockdown, always show the keyguard
Manual test steps:
1. Enable app pinning and disable "Ask for PIN before unpinning" setting
2. Pin an app (ie: Settings)
3. Lockdown from the power menu
Observe: user is brought to the keyguard, primary auth is required
to enter the device. After entering credential, the device is still in
app pinning mode.
Test: atest KeyguardViewMediatorTest
Test: manual steps outlined above
Bug: 218495634
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b23c2d5fb6630ea0da503b937f62880594b13e94)
Merged-In: I9a7c5e1acadabd4484e58573331f98dba895f2a2
Change-Id: I9a7c5e1acadabd4484e58573331f98dba895f2a2
---
.../systemui/keyguard/KeyguardViewMediator.java | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f025575623ca..cd02fe9a6c2d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -556,6 +556,13 @@ public class KeyguardViewMediator extends SystemUI {
notifyHasLockscreenWallpaperChanged(hasLockscreenWallpaper);
}
}
+
+ @Override
+ public void onStrongAuthStateChanged(int userId) {
+ if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
+ doKeyguardLocked(null);
+ }
+ }
};
ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
@@ -1319,7 +1326,8 @@ public class KeyguardViewMediator extends SystemUI {
}
// if another app is disabling us, don't show
- if (!mExternallyEnabled) {
+ if (!mExternallyEnabled
+ && !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
mNeedToReshowWhenReenabled = true;

View File

@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ioana Alexandru <aioana@google.com>
Date: Fri, 12 May 2023 15:41:09 +0000
Subject: [PATCH] Implement visitUris for RemoteViews ViewGroupActionAdd.
This is to prevent a vulnerability where notifications can show
resources belonging to other users, since the URI in the nested views
was not being checked.
Bug: 277740082
Test: atest RemoteViewsTest NotificationVisitUrisTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:850fd984e5f346645b5a941ed7307387c7e4c4de)
Merged-In: I5c71f0bad0a6f6361eb5ceffe8d1e47e936d78f8
Change-Id: I5c71f0bad0a6f6361eb5ceffe8d1e47e936d78f8
---
core/java/android/widget/RemoteViews.java | 5 ++++
.../src/android/widget/RemoteViewsTest.java | 24 +++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 21d38b559736..c2e591950e25 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1663,6 +1663,11 @@ public class RemoteViews implements Parcelable, Filter {
public int getActionTag() {
return VIEW_GROUP_ACTION_ADD_TAG;
}
+
+ @Override
+ public final void visitUris(@NonNull Consumer<Uri> visitor) {
+ mNestedViews.visitUris(visitor);
+ }
}
/**
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 46f2c0928fc3..83ff725b5b75 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -528,6 +528,30 @@ public class RemoteViewsTest {
verify(visitor, times(1)).accept(eq(icon4.getUri()));
}
+ @Test
+ public void visitUris_nestedViews() {
+ final RemoteViews outer = new RemoteViews(mPackage, R.layout.remote_views_test);
+
+ final RemoteViews inner = new RemoteViews(mPackage, 33);
+ final Uri imageUriI = Uri.parse("content://inner/image");
+ final Icon icon1 = Icon.createWithContentUri("content://inner/icon1");
+ final Icon icon2 = Icon.createWithContentUri("content://inner/icon2");
+ final Icon icon3 = Icon.createWithContentUri("content://inner/icon3");
+ final Icon icon4 = Icon.createWithContentUri("content://inner/icon4");
+ inner.setImageViewUri(R.id.image, imageUriI);
+ inner.setTextViewCompoundDrawables(R.id.text, icon1, icon2, icon3, icon4);
+
+ outer.addView(R.id.layout, inner);
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ outer.visitUris(visitor);
+ verify(visitor, times(1)).accept(eq(imageUriI));
+ verify(visitor, times(1)).accept(eq(icon1.getUri()));
+ verify(visitor, times(1)).accept(eq(icon2.getUri()));
+ verify(visitor, times(1)).accept(eq(icon3.getUri()));
+ verify(visitor, times(1)).accept(eq(icon4.getUri()));
+ }
+
@Test
public void visitUris_separateOrientation() {
final RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test);

View File

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ioana Alexandru <aioana@google.com>
Date: Mon, 15 May 2023 16:15:55 +0000
Subject: [PATCH] Check URIs in notification public version.
Bug: 276294099
Test: atest NotificationManagerServiceTest NotificationVisitUrisTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:9663d493142b59c65311bc09d48427d3bdde0222)
Merged-In: I670198b213abb2cb29a9865eb9d1e897700508b4
Change-Id: I670198b213abb2cb29a9865eb9d1e897700508b4
---
core/java/android/app/Notification.java | 4 ++++
.../NotificationManagerServiceTest.java | 20 +++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5b9e1ea6daf1..7921a89ca96f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2451,6 +2451,10 @@ public class Notification implements Parcelable
* @hide
*/
public void visitUris(@NonNull Consumer<Uri> visitor) {
+ if (publicVersion != null) {
+ publicVersion.visitUris(visitor);
+ }
+
visitor.accept(sound);
if (tickerView != null) tickerView.visitUris(visitor);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index da4a2420b924..f3a9ef1eb63e 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3436,6 +3436,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
verify(visitor, times(1)).accept(eq(largeIcon.getUri()));
}
+ @Test
+ public void testVisitUris_publicVersion() throws Exception {
+ final Icon smallIconPublic = Icon.createWithContentUri("content://media/small/icon");
+ final Icon largeIconPrivate = Icon.createWithContentUri("content://media/large/icon");
+
+ Notification publicVersion = new Notification.Builder(mContext, "a")
+ .setContentTitle("notification with uris")
+ .setSmallIcon(smallIconPublic)
+ .build();
+ Notification n = new Notification.Builder(mContext, "a")
+ .setLargeIcon(largeIconPrivate)
+ .setPublicVersion(publicVersion)
+ .build();
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ n.visitUris(visitor);
+ verify(visitor, times(1)).accept(eq(smallIconPublic.getUri()));
+ verify(visitor, times(1)).accept(eq(largeIconPrivate.getUri()));
+ }
+
@Test
public void testVisitUris_messagingStyle() {
final Icon personIcon1 = Icon.createWithContentUri("content://media/person1");

View File

@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Chandru S <chandruis@google.com>
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 cd02fe9a6c2d..a7d5c64dd3a3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -913,9 +913,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()
@@ -927,8 +927,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
@@ -1762,7 +1762,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

View File

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexander Grund <flamefire89@gmail.com>
Date: Mon, 14 Aug 2023 13:04:21 +0200
Subject: [PATCH] Add `PackageParser.Package getPackage(int uid)`
Partial backport of ca1ea17a3eacf71a64dc501c4374a4eeb6246451
Change-Id: I8adb1ffac1ebe3d419c1fcf2c14b22a50b31fd5b
---
.../android/content/pm/PackageManagerInternal.java | 6 ++++++
.../android/server/pm/PackageManagerService.java | 13 +++++++++++++
2 files changed, 19 insertions(+)
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 84d9743eec9e..9f9ff88c1541 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -667,6 +667,12 @@ public abstract class PackageManagerInternal {
*/
public abstract @Nullable PackageParser.Package getPackage(@NonNull String packageName);
+ /**
+ * Returns a package for the given UID. If the UID is part of a shared user ID, one
+ * of the packages will be chosen to be returned.
+ */
+ public abstract @Nullable PackageParser.Package getPackage(int uid);
+
/**
* Returns a list without a change observer.
*
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 27282c0a2dda..5bd1b4ac0195 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -24648,6 +24648,19 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ @Override
+ public PackageParser.Package getPackage(int uid) {
+ synchronized (mPackages) {
+ final String[] packageNames = getPackagesForUid(uid);
+ PackageParser.Package pkg = null;
+ final int numPackages = packageNames == null ? 0 : packageNames.length;
+ for (int i = 0; pkg == null && i < numPackages; i++) {
+ pkg = mPackages.get(packageNames[i]);
+ }
+ return pkg;
+ }
+ }
+
@Override
public PackageList getPackageList(PackageListObserver observer) {
synchronized (mPackages) {

View File

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Dementyev <dementyev@google.com>
Date: Fri, 30 Jun 2023 14:36:44 -0700
Subject: [PATCH] Update AccountManagerService checkKeyIntentParceledCorrectly.
Bug: 265798288
Test: manual
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b117b506ec0504ff9eb2fa523e82f1879ecb8cc1)
Merged-In: Iad33851af32a11c99d11bc2b5c76d124c3e97ebb
Change-Id: Iad33851af32a11c99d11bc2b5c76d124c3e97ebb
---
.../com/android/server/accounts/AccountManagerService.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index a9c7b0c6a3f1..715b32687054 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -4850,6 +4850,9 @@ public class AccountManagerService
Bundle simulateBundle = p.readBundle();
p.recycle();
Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
+ if (intent != null && intent.getClass() != Intent.class) {
+ return false;
+ }
Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT);
if (intent == null) {
return (simulateIntent == null);

View File

@ -0,0 +1,60 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jean-Michel Trivi <jmtrivi@google.com>
Date: Wed, 7 Dec 2022 04:36:46 +0000
Subject: [PATCH] RingtoneManager: verify default ringtone is audio
When a ringtone picker tries to set a ringtone through
RingtoneManager.setActualDefaultRingtoneUri (also
called by com.android.settings.DefaultRingtonePreference),
verify the mimeType can be obtained (not found when caller
doesn't have access to it) and it is an audio resource.
Bug: 205837340
Test: atest android.media.audio.cts.RingtoneManagerTest
(cherry picked from commit 38618f9fb16d3b5617e2289354d47abe5af17dad)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:377144b64325dadad102f5233ecb50a4446b205b)
Merged-In: I3f2c487ded405c0c1a83ef0a2fe99cff7cc9328e
Change-Id: I3f2c487ded405c0c1a83ef0a2fe99cff7cc9328e
---
media/java/android/media/RingtoneManager.java | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 05b96ad016a8..ad4751165d30 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -792,10 +792,10 @@ public class RingtoneManager {
return ringtoneUri;
}
-
+
/**
* Sets the {@link Uri} of the default sound for a given sound type.
- *
+ *
* @param context A context used for querying.
* @param type The type whose default sound should be set. One of
* {@link #TYPE_RINGTONE}, {@link #TYPE_NOTIFICATION}, or
@@ -816,6 +816,21 @@ public class RingtoneManager {
if(!isInternalRingtoneUri(ringtoneUri)) {
ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
}
+
+ if (ringtoneUri != null) {
+ final String mimeType = resolver.getType(ringtoneUri);
+ if (mimeType == null) {
+ Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
+ + " ignored: failure to find mimeType (no access from this context?)");
+ return;
+ }
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
+ Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
+ + " ignored: associated mimeType:" + mimeType + " is not an audio type");
+ return;
+ }
+ }
+
Settings.System.putStringForUser(resolver, setting,
ringtoneUri != null ? ringtoneUri.toString() : null, context.getUserId());

View File

@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Josep del Rio <joseprio@google.com>
Date: Mon, 26 Jun 2023 11:16:37 +0000
Subject: [PATCH] Do not share key mappings with JNI object
The key mapping information between the native key mappings and
the KeyCharacterMap object available in Java is currently shared,
which means that a read can be attempted while it's being modified.
Because the code changed between R and S, this CL fixes it just
for R; the patch for versions S+ is ag/23785419
Bug: 274058082
Test: Presubmit
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4b3c4620166071561ec44961fb08a56676b4fd6c)
Merged-In: I3be94534dcda365da473f82347ae2e3f57bb1b42
Change-Id: I3be94534dcda365da473f82347ae2e3f57bb1b42
---
core/jni/android_view_InputDevice.cpp | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 9f4e3e516ada..81ada6ad535c 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <binder/Parcel.h>
#include <input/Input.h>
#include <android_runtime/AndroidRuntime.h>
@@ -48,9 +49,16 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
return NULL;
}
+ sp<KeyCharacterMap> map = deviceInfo.getKeyCharacterMap();
+ if (map != nullptr) {
+ Parcel parcel;
+ map->writeToParcel(&parcel);
+ map = map->readFromParcel(&parcel);
+ }
+
ScopedLocalRef<jobject> kcmObj(env,
- android_view_KeyCharacterMap_create(env, deviceInfo.getId(),
- deviceInfo.getKeyCharacterMap()));
+ android_view_KeyCharacterMap_create(env, deviceInfo.getId(),
+ map));
if (!kcmObj.get()) {
return NULL;
}

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Josep del Rio <joseprio@google.com>
Date: Wed, 12 Jul 2023 16:32:05 +0000
Subject: [PATCH] Fix KCM key mapping cloning
ag/23792288 tried to fix a security issue by cloning the key
mappings, but unfortunately the parcel was not being rewinded.
Bug: 274058082
Test: Confirmed change works in newer Android versions
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:aaaba6cf190d976efdc5db6c78997dbdc9214c15)
Merged-In: I6f75b9202e20d82ebf81a35a2916e653ee1b8372
Change-Id: I6f75b9202e20d82ebf81a35a2916e653ee1b8372
---
core/jni/android_view_InputDevice.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 81ada6ad535c..87102d3359a7 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -53,6 +53,7 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
if (map != nullptr) {
Parcel parcel;
map->writeToParcel(&parcel);
+ parcel.setDataPosition(0);
map = map->readFromParcel(&parcel);
}

View File

@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hongwei Wang <hwwang@google.com>
Date: Wed, 24 May 2023 19:35:44 -0700
Subject: [PATCH] Disallow loading icon from content URI to PipMenu
Bug: 278246904
Test: manually, with the PoC app attached to the bug
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5f5a87d8a0dc9190327ba0e6113d5b80ee96abae)
Merged-In: Iecfc1fb962de611cbe3c51a44ba4fded53925a7d
Change-Id: Iecfc1fb962de611cbe3c51a44ba4fded53925a7d
---
.../systemui/pip/phone/PipMenuActivity.java | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index ec6d7ffaedb0..de45720fe11e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -51,6 +51,7 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -457,11 +458,17 @@ public class PipMenuActivity extends Activity {
final RemoteAction action = mActions.get(i);
final ImageView actionView = (ImageView) mActionsGroup.getChildAt(i);
- // TODO: Check if the action drawable has changed before we reload it
- action.getIcon().loadDrawableAsync(this, d -> {
- d.setTint(Color.WHITE);
- actionView.setImageDrawable(d);
- }, mHandler);
+ final int iconType = action.getIcon().getType();
+ if (iconType == Icon.TYPE_URI) {
+ // Disallow loading icon from content URI
+ actionView.setImageDrawable(null);
+ } else {
+ // TODO: Check if the action drawable has changed before we reload it
+ action.getIcon().loadDrawableAsync(this, d -> {
+ d.setTint(Color.WHITE);
+ actionView.setImageDrawable(d);
+ }, mHandler);
+ }
actionView.setContentDescription(action.getContentDescription());
if (action.isEnabled()) {
actionView.setOnClickListener(v -> {

View File

@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kunal Malhotra <malhk@google.com>
Date: Fri, 2 Jun 2023 23:32:02 +0000
Subject: [PATCH] Fixing DatabaseUtils to detect malformed UTF-16 strings
Test: tested with POC in bug, also using atest
Bug: 224771621
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:fb4a72e3943d166088407e61aa4439ac349f3f12)
Merged-In: Ide65205b83063801971c5778af3154bcf3f0e530
Change-Id: Ide65205b83063801971c5778af3154bcf3f0e530
---
core/java/android/database/DatabaseUtils.java | 32 +++++++++++++------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 992da312201d..53431a7414c4 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -429,17 +429,31 @@ public class DatabaseUtils {
*/
public static void appendEscapedSQLString(StringBuilder sb, String sqlString) {
sb.append('\'');
- if (sqlString.indexOf('\'') != -1) {
- int length = sqlString.length();
- for (int i = 0; i < length; i++) {
- char c = sqlString.charAt(i);
- if (c == '\'') {
- sb.append('\'');
+ int length = sqlString.length();
+ for (int i = 0; i < length; i++) {
+ char c = sqlString.charAt(i);
+ if (Character.isHighSurrogate(c)) {
+ if (i == length - 1) {
+ continue;
+ }
+ if (Character.isLowSurrogate(sqlString.charAt(i + 1))) {
+ // add them both
+ sb.append(c);
+ sb.append(sqlString.charAt(i + 1));
+ continue;
+ } else {
+ // this is a lone surrogate, skip it
+ continue;
}
- sb.append(c);
}
- } else
- sb.append(sqlString);
+ if (Character.isLowSurrogate(c)) {
+ continue;
+ }
+ if (c == '\'') {
+ sb.append('\'');
+ }
+ sb.append(c);
+ }
sb.append('\'');
}

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aaron Liu <aaronjli@google.com>
Date: Thu, 10 Aug 2023 15:37:24 +0000
Subject: [PATCH] Revert "DO NOT MERGE Dismiss keyguard when simpin auth'd
and..."
This reverts commit 09f004722284ef6b9790ddf9338a1708b3f0833c.
Reason for revert: causing a partner bug
Fixes: 295205456
Bug: 222446076
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8df038265475bb062ead9eec1749ee92a0f5eb4e)
Merged-In: Ida11d98117727f63547b096617a4778bea429e22
Change-Id: Ida11d98117727f63547b096617a4778bea429e22
---
.../src/com/android/keyguard/KeyguardSecurityContainer.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index bd555e7360d8..89514a52d0bd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -529,7 +529,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
case SimPuk:
// Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
- if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled(
+ if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser())) {
finish = true;
eventSubtype = BOUNCER_DISMISS_SIM;

View File

@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nan Wu <wnan@google.com>
Date: Fri, 16 Jun 2023 14:42:24 +0000
Subject: [PATCH] DO NOT MERGE Fix BAL via notification.publicVersion
We stripped the token that allows app to retrieve their own notification
and fire their own PI to launch activities from background. But we
forgot to strip the token from notification.publicVersion
Bug: 278558814
Test: NotificationManagerTest#testActivityStartFromRetrievedNotification_isBlocked
(cherry picked from commit cf851d81a954f0a6dd0c2fd7defa93932539e7f9)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1896c2e7068c9ec1ab8355d863d7e8107d5d5706)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:75fcbb37617246c43c2af34b12c9ae4b4043f9ac)
Merged-In: I8f25d7a5e47890a0496af023149717e1df482f98
Change-Id: I8f25d7a5e47890a0496af023149717e1df482f98
---
core/java/android/app/Notification.java | 7 +++++--
.../server/notification/NotificationManagerService.java | 2 +-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7921a89ca96f..d8eefc3d3be4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2987,8 +2987,11 @@ public class Notification implements Parcelable
*
* @hide
*/
- public void setAllowlistToken(@Nullable IBinder token) {
- mWhitelistToken = token;
+ public void clearAllowlistToken() {
+ mWhitelistToken = null;
+ if (publicVersion != null) {
+ publicVersion.clearAllowlistToken();
+ }
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d056eac37039..e09491867f91 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3249,7 +3249,7 @@ public class NotificationManagerService extends SystemService {
// Remove background token before returning notification to untrusted app, this
// ensures the app isn't able to perform background operations that are
// associated with notification interactions.
- notification.setAllowlistToken(null);
+ notification.clearAllowlistToken();
return new StatusBarNotification(
sbn.getPackageName(),
sbn.getOpPkg(),

View File

@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Piyush Mehrotra <piee@google.com>
Date: Thu, 27 Jul 2023 19:35:14 +0000
Subject: [PATCH] Check caller's uid in backupAgentCreated callback
AM.backupAgentCreated() should enforce that caller belongs the package called in the API.
Bug: 289549315
Test: atest android.security.cts.ActivityManagerTest#testActivityManager_backupAgentCreated_rejectIfCallerUidNotEqualsPackageUid
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:52b91363583c4e2b68f1a818b067cefe04809285)
Merged-In: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d
Change-Id: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d
---
.../server/am/ActivityManagerService.java | 23 +++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ec8841debb7a..3e99e594a702 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3136,6 +3136,22 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ /**
+ * Enforces that the uid of the caller matches the uid of the package.
+ *
+ * @param packageName the name of the package to match uid against.
+ * @param callingUid the uid of the caller.
+ * @throws SecurityException if the calling uid doesn't match uid of the package.
+ */
+ private void enforceCallingPackage(String packageName, int callingUid) {
+ final int userId = UserHandle.getUserId(callingUid);
+ final int packageUid = getPackageManagerInternalLocked().getPackageUid(packageName,
+ /*flags=*/ 0, userId);
+ if (packageUid != callingUid) {
+ throw new SecurityException(packageName + " does not belong to uid " + callingUid);
+ }
+ }
+
@Override
public void setPackageScreenCompatMode(String packageName, int mode) {
mActivityTaskManager.setPackageScreenCompatMode(packageName, mode);
@@ -14345,13 +14361,16 @@ public class ActivityManagerService extends IActivityManager.Stub
// A backup agent has just come up
@Override
public void backupAgentCreated(String agentPackageName, IBinder agent, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ enforceCallingPackage(agentPackageName, callingUid);
+
// Resolve the target user id and enforce permissions.
- userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid,
userId, /* allowAll */ false, ALLOW_FULL_ONLY, "backupAgentCreated", null);
if (DEBUG_BACKUP) {
Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent
+ " callingUserId = " + UserHandle.getCallingUserId() + " userId = " + userId
- + " callingUid = " + Binder.getCallingUid() + " uid = " + Process.myUid());
+ + " callingUid = " + callingUid + " uid = " + Process.myUid());
}
synchronized(this) {

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kumarashishg <kumarashishg@google.com>
Date: Thu, 3 Aug 2023 12:01:29 +0000
Subject: [PATCH] Use type safe API of readParcelableArray
Bug: 291299076
Test: Build and flash the device and check if it throws exception for
non UsbInterface object
Test: atest CtsUsbManagerTestCases
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:85d7e6712a9eeeed3bdd68ea3c3862c7e88bfe70)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:60bfbde79f2ffb012abced55d358fdf6380c0bae)
Merged-In: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503
Change-Id: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503
---
core/java/android/hardware/usb/UsbConfiguration.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
index 66269cb772f8..b25f47b11532 100644
--- a/core/java/android/hardware/usb/UsbConfiguration.java
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
@@ -172,7 +172,8 @@ public class UsbConfiguration implements Parcelable {
String name = in.readString();
int attributes = in.readInt();
int maxPower = in.readInt();
- Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
+ Parcelable[] interfaces = in.readParcelableArray(
+ UsbInterface.class.getClassLoader(), UsbInterface.class);
UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower);
configuration.setInterfaces(interfaces);
return configuration;

View File

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Songchun Fan <schfan@google.com>
Date: Mon, 14 Aug 2023 15:24:11 -0700
Subject: [PATCH] verify ringtone URI before setting
Similar to ag/24422287, but the same URI verification should be done in
SettingsProvider as well, which can be called by apps via
Settings.System API or ContentProvider APIs without using
RingtoneManager.
BUG: 227201030
Test: manual with a test app. Will add a CTS test.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b234678ec122994ccbfc52ac48aafdad7fdb1ed)
Merged-In: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b
Change-Id: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b
---
.../providers/settings/SettingsProvider.java | 31 +++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 760b0604a604..7cb41275984e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1734,6 +1734,9 @@ public class SettingsProvider extends ContentProvider {
cacheName = Settings.System.ALARM_ALERT_CACHE;
}
if (cacheName != null) {
+ if (!isValidAudioUri(name, value)) {
+ return false;
+ }
final File cacheFile = new File(
getRingtoneCacheDir(owningUserId), cacheName);
cacheFile.delete();
@@ -1766,6 +1769,34 @@ public class SettingsProvider extends ContentProvider {
}
}
+ private boolean isValidAudioUri(String name, String uri) {
+ if (uri != null) {
+ Uri audioUri = Uri.parse(uri);
+ if (Settings.AUTHORITY.equals(
+ ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) {
+ // Don't accept setting the default uri to self-referential URIs like
+ // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this
+ // setting.
+ return false;
+ }
+ final String mimeType = getContext().getContentResolver().getType(audioUri);
+ if (mimeType == null) {
+ Slog.e(LOG_TAG,
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
+ + " ignored: failure to find mimeType (no access from this context?)");
+ return false;
+ }
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
+ || mimeType.equals("application/x-flac"))) {
+ Slog.e(LOG_TAG,
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
+ + " ignored: associated mimeType: " + mimeType + " is not an audio type");
+ return false;
+ }
+ }
+ return true;
+ }
+
private boolean hasWriteSecureSettingsPermission() {
// Write secure settings is a more protected permission. If caller has it we are good.
if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)

View File

@ -0,0 +1,95 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= <matiashe@google.com>
Date: Wed, 5 Jul 2023 13:52:21 +0200
Subject: [PATCH] Visit Uris added by WearableExtender
Bug: 283962802
Test: atest + manual (POC app now crashes on notify() as expected)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a6f44e911f2d7204cc28c710e54f97c96231abab)
Merged-In: I0da18c631eb5e4844a48760c7aaedab715a0bfed
Change-Id: I0da18c631eb5e4844a48760c7aaedab715a0bfed
---
core/java/android/app/Notification.java | 17 +++++++++++++++-
.../NotificationManagerServiceTest.java | 20 +++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index d8eefc3d3be4..9d0a5e93e2d8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1790,6 +1790,10 @@ public class Notification implements Parcelable
}
}
+ private void visitUris(@NonNull Consumer<Uri> visitor) {
+ visitIconUri(visitor, getIcon());
+ }
+
@Override
public Action clone() {
return new Action(
@@ -2467,7 +2471,7 @@ public class Notification implements Parcelable
if (actions != null) {
for (Action action : actions) {
- visitIconUri(visitor, action.getIcon());
+ action.visitUris(visitor);
}
}
@@ -2501,6 +2505,11 @@ public class Notification implements Parcelable
if (mBubbleMetadata != null) {
visitIconUri(visitor, mBubbleMetadata.getIcon());
}
+
+ if (extras != null && extras.containsKey(WearableExtender.EXTRA_WEARABLE_EXTENSIONS)) {
+ WearableExtender extender = new WearableExtender(this);
+ extender.visitUris(visitor);
+ }
}
/**
@@ -9818,6 +9827,12 @@ public class Notification implements Parcelable
mFlags &= ~mask;
}
}
+
+ private void visitUris(@NonNull Consumer<Uri> visitor) {
+ for (Action action : mActions) {
+ action.visitUris(visitor);
+ }
+ }
}
/**
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 34550bb52a52..61297cf67ee0 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3528,6 +3528,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
verify(visitor, times(1)).accept(eq(personIcon3.getUri()));
}
+ @Test
+ public void testVisitUris_wearableExtender() {
+ Icon actionIcon = Icon.createWithContentUri("content://media/action");
+ Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction");
+ PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent(),
+ PendingIntent.FLAG_IMMUTABLE);
+ Notification n = new Notification.Builder(mContext, "a")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .addAction(new Notification.Action.Builder(actionIcon, "Hey!", intent).build())
+ .extend(new Notification.WearableExtender().addAction(
+ new Notification.Action.Builder(wearActionIcon, "Wear!", intent).build()))
+ .build();
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ n.visitUris(visitor);
+
+ verify(visitor).accept(eq(actionIcon.getUri()));
+ verify(visitor).accept(eq(wearActionIcon.getUri()));
+ }
+
@Test
public void testSetNotificationPolicy_preP_setOldFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lifu Tang <lifu@google.com>
Date: Wed, 5 Jul 2023 13:03:00 -0700
Subject: [PATCH] Fix bypass BAL via `requestGeofence`
Bug: 273729172
Test: manually
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7f9be7c3c859dc82d37452570d9878b58f6437a9)
Merged-In: Ia8094244f908b20d42711b6ea8f58f9b3345b563
Change-Id: Ia8094244f908b20d42711b6ea8f58f9b3345b563
---
services/core/java/com/android/server/PendingIntentUtils.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/services/core/java/com/android/server/PendingIntentUtils.java b/services/core/java/com/android/server/PendingIntentUtils.java
index 1600101b20f4..a72a4d254a2a 100644
--- a/services/core/java/com/android/server/PendingIntentUtils.java
+++ b/services/core/java/com/android/server/PendingIntentUtils.java
@@ -34,6 +34,7 @@ public class PendingIntentUtils {
public static Bundle createDontSendToRestrictedAppsBundle(@Nullable Bundle bundle) {
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setDontSendToRestrictedApps(true);
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
if (bundle == null) {
return options.toBundle();
}

View File

@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mady Mellor <madym@google.com>
Date: Wed, 29 Jan 2020 11:41:58 -0800
Subject: [PATCH] Make sure we visit the icon URIs of Person objects on
Notifications
Test: manual - have bubbles test app with uri based icons, send notifs,
notice the notifications show pictures of people instead
of blank spaces & there are no exceptions in the logs
Fixes: 148543216
Change-Id: Idfb7c75d9c5541f2dcebfb0f20daa99f039f4181
---
core/java/android/app/Notification.java | 24 ++++++++++++++++++++++++
core/java/android/app/Person.java | 14 ++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 9d0a5e93e2d8..068e85b24321 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2482,6 +2482,20 @@ public class Notification implements Parcelable
if (extras.containsKey(EXTRA_BACKGROUND_IMAGE_URI)) {
visitor.accept(Uri.parse(extras.getString(EXTRA_BACKGROUND_IMAGE_URI)));
}
+
+ ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST);
+ if (people != null && !people.isEmpty()) {
+ for (Person p : people) {
+ if (p.getIconUri() != null) {
+ visitor.accept(p.getIconUri());
+ }
+ }
+ }
+
+ final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON);
+ if (person != null && person.getIconUri() != null) {
+ visitor.accept(person.getIconUri());
+ }
}
if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) {
@@ -2490,6 +2504,11 @@ public class Notification implements Parcelable
for (MessagingStyle.Message message : MessagingStyle.Message
.getMessagesFromBundleArray(messages)) {
visitor.accept(message.getDataUri());
+
+ Person senderPerson = message.getSenderPerson();
+ if (senderPerson != null && senderPerson.getIconUri() != null) {
+ visitor.accept(senderPerson.getIconUri());
+ }
}
}
@@ -2498,6 +2517,11 @@ public class Notification implements Parcelable
for (MessagingStyle.Message message : MessagingStyle.Message
.getMessagesFromBundleArray(historic)) {
visitor.accept(message.getDataUri());
+
+ Person senderPerson = message.getSenderPerson();
+ if (senderPerson != null && senderPerson.getIconUri() != null) {
+ visitor.accept(senderPerson.getIconUri());
+ }
}
}
}
diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java
index 14a5589c04c2..b5820ba70020 100644
--- a/core/java/android/app/Person.java
+++ b/core/java/android/app/Person.java
@@ -19,6 +19,7 @@ package android.app;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.drawable.Icon;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -122,6 +123,19 @@ public final class Person implements Parcelable {
return "";
}
+ /**
+ * @return the URI associated with the {@link #getIcon()} for this person, iff the icon exists
+ * and is URI based.
+ * @hide
+ */
+ @Nullable
+ public Uri getIconUri() {
+ if (mIcon != null && mIcon.getType() == Icon.TYPE_URI) {
+ return mIcon.getUri();
+ }
+ return null;
+ }
+
@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {

View File

@ -0,0 +1,123 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kweku Adams <kwekua@google.com>
Date: Fri, 23 Sep 2022 21:06:53 +0000
Subject: [PATCH] RESTRICT AUTOMERGE: Drop invalid data.
Drop invalid data when writing or reading from XML. PersistableBundle
does lazy unparcelling, so checking the values during unparcelling would
remove the benefit of the lazy unparcelling. Checking the validity when
writing to or reading from XML seems like the best alternative.
Bug: 246542285
Bug: 247513680
Test: install test app with invalid job config, start app to schedule job, then check logcat and jobscheduler persisted file
(cherry picked from commit 666e8ac60a31e2cc52b335b41004263f28a8db06)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:62b37ab21ce27746a79a2071deee98c61b23c8d9)
Merged-In: Ie817aa0993e9046cb313a750d2323cadc8c1ef15
Change-Id: Ie817aa0993e9046cb313a750d2323cadc8c1ef15
---
core/java/android/os/PersistableBundle.java | 42 +++++++++++++++++----
1 file changed, 34 insertions(+), 8 deletions(-)
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 6f1bf71f187b..3e6312754359 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -18,6 +18,7 @@ package android.os;
import android.annotation.Nullable;
import android.util.ArrayMap;
+import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.XmlUtils;
@@ -38,6 +39,8 @@ import java.util.ArrayList;
*/
public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable,
XmlUtils.WriteMapCallback {
+ private static final String TAG = "PersistableBundle";
+
private static final String TAG_PERSISTABLEMAP = "pbundle_as_map";
public static final PersistableBundle EMPTY;
@@ -100,7 +103,11 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
* @hide
*/
public PersistableBundle(Bundle b) {
- this(b.getMap());
+ this(b, true);
+ }
+
+ private PersistableBundle(Bundle b, boolean throwException) {
+ this(b.getMap(), throwException);
}
/**
@@ -109,7 +116,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
* @param map a Map containing only those items that can be persisted.
* @throws IllegalArgumentException if any element of #map cannot be persisted.
*/
- private PersistableBundle(ArrayMap<String, Object> map) {
+ private PersistableBundle(ArrayMap<String, Object> map, boolean throwException) {
super();
mFlags = FLAG_DEFUSABLE;
@@ -118,16 +125,23 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
// Now verify each item throwing an exception if there is a violation.
final int N = mMap.size();
- for (int i=0; i<N; i++) {
+ for (int i = N - 1; i >= 0; --i) {
Object value = mMap.valueAt(i);
if (value instanceof ArrayMap) {
// Fix up any Maps by replacing them with PersistableBundles.
- mMap.setValueAt(i, new PersistableBundle((ArrayMap<String, Object>) value));
+ mMap.setValueAt(i,
+ new PersistableBundle((ArrayMap<String, Object>) value, throwException));
} else if (value instanceof Bundle) {
- mMap.setValueAt(i, new PersistableBundle(((Bundle) value)));
+ mMap.setValueAt(i, new PersistableBundle((Bundle) value, throwException));
} else if (!isValidType(value)) {
- throw new IllegalArgumentException("Bad value in PersistableBundle key="
- + mMap.keyAt(i) + " value=" + value);
+ final String errorMsg = "Bad value in PersistableBundle key="
+ + mMap.keyAt(i) + " value=" + value;
+ if (throwException) {
+ throw new IllegalArgumentException(errorMsg);
+ } else {
+ Slog.wtfStack(TAG, errorMsg);
+ mMap.removeAt(i);
+ }
}
}
}
@@ -242,6 +256,15 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
/** @hide */
public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
unparcel();
+ // Explicitly drop invalid types an attacker may have added before persisting.
+ for (int i = mMap.size() - 1; i >= 0; --i) {
+ final Object value = mMap.valueAt(i);
+ if (!isValidType(value)) {
+ Slog.e(TAG, "Dropping bad data before persisting: "
+ + mMap.keyAt(i) + "=" + value);
+ mMap.removeAt(i);
+ }
+ }
XmlUtils.writeMapXml(mMap, out, this);
}
@@ -290,9 +313,12 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
if (event == XmlPullParser.START_TAG) {
+ // Don't throw an exception when restoring from XML since an attacker could try to
+ // input invalid data in the persisted file.
return new PersistableBundle((ArrayMap<String, Object>)
XmlUtils.readThisArrayMapXml(in, startTag, tagName,
- new MyReadMapCallback()));
+ new MyReadMapCallback()),
+ /* throwException */ false);
}
}
return EMPTY;

View File

@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pinyao Ting <pinyaoting@google.com>
Date: Wed, 12 Jul 2023 21:38:36 +0000
Subject: [PATCH] Validate URI-based shortcut icon at creation time.
Bug: 288113797
Test: manual
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3d41fb7620ffb9c81b23977c8367c323e4721e65)
Merged-In: I392f8e923923bf40827a2b6207c4eaa262694fbc
Change-Id: I392f8e923923bf40827a2b6207c4eaa262694fbc
---
.../android/server/pm/ShortcutService.java | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index d1ee52eef2df..5e58ca73ccd4 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -28,6 +28,7 @@ import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -104,6 +105,7 @@ import com.android.internal.util.StatLogger;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.ShortcutUser.PackageWithUser;
+import com.android.server.uri.UriGrantsManagerInternal;
import libcore.io.IoUtils;
@@ -320,6 +322,7 @@ public class ShortcutService extends IShortcutService.Stub {
private final UserManagerInternal mUserManagerInternal;
private final UsageStatsManagerInternal mUsageStatsManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
+ private final UriGrantsManagerInternal mUriGrantsManagerInternal;
private final ShortcutRequestPinProcessor mShortcutRequestPinProcessor;
private final ShortcutBitmapSaver mShortcutBitmapSaver;
@@ -441,6 +444,8 @@ public class ShortcutService extends IShortcutService.Stub {
LocalServices.getService(UsageStatsManagerInternal.class));
mActivityManagerInternal = Preconditions.checkNotNull(
LocalServices.getService(ActivityManagerInternal.class));
+ mUriGrantsManagerInternal = Preconditions.checkNotNull(
+ LocalServices.getService(UriGrantsManagerInternal.class));
mShortcutRequestPinProcessor = new ShortcutRequestPinProcessor(this, mLock);
mShortcutBitmapSaver = new ShortcutBitmapSaver(this);
@@ -1693,11 +1698,32 @@ public class ShortcutService extends IShortcutService.Stub {
}
if (shortcut.getIcon() != null) {
ShortcutInfo.validateIcon(shortcut.getIcon());
+ validateIconURI(shortcut);
}
shortcut.replaceFlags(0);
}
+ // Validates the calling process has permission to access shortcut icon's image uri
+ private void validateIconURI(@NonNull final ShortcutInfo si) {
+ final int callingUid = injectBinderCallingUid();
+ final Icon icon = si.getIcon();
+ if (icon == null) {
+ // There's no icon in this shortcut, nothing to validate here.
+ return;
+ }
+ int iconType = icon.getType();
+ if (iconType != Icon.TYPE_URI) {
+ // The icon is not URI-based, nothing to validate.
+ return;
+ }
+ final Uri uri = icon.getUri();
+ mUriGrantsManagerInternal.checkGrantUriPermission(callingUid, si.getPackage(),
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(callingUid)));
+ }
+
private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
fixUpIncomingShortcutInfo(shortcut, forUpdate, /*forPinRequest=*/ false);
}

View File

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Marzia Favaro <marziana@google.com>
Date: Mon, 31 Jul 2023 15:10:34 +0000
Subject: [PATCH] Require permission to unlock keyguard
Bug: 288896339
Test: Manual, verify that the app which can be found on the bug can no longer call
keyguardGoingAway successfully
Require permission to unlock keyguard
Bug: 288896339
Test: Manual, verify that the app which can be found on the bug can no longer call
keyguardGoingAway successfully
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bd2aa5d309c5bf8e73161975bd5aba7945b25e84)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ef1345d278bd2a8944c6362bf65cff7305ca6fc5)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ad8e7e3b1db22684988a179e23639567a4096ca6)
Merged-In: I7ba7e56f954c8e6f1f734311f735215918975bc6
Change-Id: I7ba7e56f954c8e6f1f734311f735215918975bc6
---
.../java/com/android/server/wm/ActivityTaskManagerService.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d0dad0a23729..5bcc5975604a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.Manifest.permission.BIND_VOICE_INTERACTION;
import static android.Manifest.permission.CHANGE_CONFIGURATION;
+import static android.Manifest.permission.CONTROL_KEYGUARD;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
@@ -3890,6 +3891,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void keyguardGoingAway(int flags) {
+ mAmInternal.enforceCallingPermission(CONTROL_KEYGUARD, "unlock keyguard");
enforceNotIsolatedCaller("keyguardGoingAway");
final long token = Binder.clearCallingIdentity();
try {

View File

@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pawan Wagh <waghpawan@google.com>
Date: Tue, 13 Jun 2023 17:37:26 +0000
Subject: [PATCH] Use readUniqueFileDescriptor in incidentd service
readFileDescriptor doesn't provide ownership of the fds. fdopen
needs ownership of the fds. Fds read from parcel should be duped
in this scenario and readUniqueFileDescriptor dups fds internally.
Test: m incidentd_service_fuzzer && adb sync data && adb shell /data/fuzz/x86_64/incidentd_service_fuzzer/incidentd_service_fuzzer
Test: atest incidentd_test
Bug: 286931110
Bug: 283699145
(cherry picked from commit ba78ef276951269f7b024baebdf1b8fa40bedb23)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b4aaf180ee8f3e375c7ab411f03cf9c24c1d8055)
Merged-In: Ibe03a17dee91ac5bf25d123d4fd9c0bdd3c7d80e
Change-Id: Ibe03a17dee91ac5bf25d123d4fd9c0bdd3c7d80e
---
cmds/incidentd/src/IncidentService.cpp | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index a52726396b53..a4819633efee 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -418,9 +418,13 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel*
switch (code) {
case SHELL_COMMAND_TRANSACTION: {
- int in = data.readFileDescriptor();
- int out = data.readFileDescriptor();
- int err = data.readFileDescriptor();
+ unique_fd in, out, err;
+ if (status_t status = data.readUniqueFileDescriptor(&in); status != OK) return status;
+
+ if (status_t status = data.readUniqueFileDescriptor(&out); status != OK) return status;
+
+ if (status_t status = data.readUniqueFileDescriptor(&err); status != OK) return status;
+
int argc = data.readInt32();
Vector<String8> args;
for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
@@ -430,15 +434,15 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel*
sp<IResultReceiver> resultReceiver =
IResultReceiver::asInterface(data.readStrongBinder());
- FILE* fin = fdopen(in, "r");
- FILE* fout = fdopen(out, "w");
- FILE* ferr = fdopen(err, "w");
+ FILE* fin = fdopen(in.release(), "r");
+ FILE* fout = fdopen(out.release(), "w");
+ FILE* ferr = fdopen(err.release(), "w");
if (fin == NULL || fout == NULL || ferr == NULL) {
resultReceiver->send(NO_MEMORY);
} else {
- err = command(fin, fout, ferr, args);
- resultReceiver->send(err);
+ status_t result = command(fin, fout, ferr, args);
+ resultReceiver->send(result);
}
if (fin != NULL) {

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pinyao Ting <pinyaoting@google.com>
Date: Mon, 24 Jul 2023 14:58:56 -0700
Subject: [PATCH] Validate userId when publishing shortcuts
Bug: 288110451
Test: manual
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:01bfd04ff445db6290ae430d44ea1bf1a115fe3c)
Merged-In: Idbde676f871db83825155730e3714f3727e25762
Change-Id: Idbde676f871db83825155730e3714f3727e25762
---
services/core/java/com/android/server/pm/ShortcutService.java | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 5e58ca73ccd4..2e2883dcb2a5 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1594,6 +1594,10 @@ public class ShortcutService extends IShortcutService.Stub {
android.util.EventLog.writeEvent(0x534e4554, "109824443", -1, "");
throw new SecurityException("Shortcut package name mismatch");
}
+ final int callingUid = injectBinderCallingUid();
+ if (UserHandle.getUserId(callingUid) != si.getUserId()) {
+ throw new SecurityException("User-ID in shortcut doesn't match the caller");
+ }
}
private void verifyShortcutInfoPackages(

View File

@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Beverly Tai <beverlyt@google.com>
Date: Thu, 14 Sep 2023 20:50:28 +0000
Subject: [PATCH] Revert "On device lockdown, always show the keyguard"
This reverts commit b23c2d5fb6630ea0da503b937f62880594b13e94.
Reason for revert: b/300463732 regression
Bug: 300463732
Bug: 218495634
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f57217125f2b124c16c463ef4507fb054cc1ba4f)
Merged-In: I31485d0d8caa3060e998636b071dbe03f6b4fc82
Change-Id: I31485d0d8caa3060e998636b071dbe03f6b4fc82
---
.../systemui/keyguard/KeyguardViewMediator.java | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a7d5c64dd3a3..e21b14dec0b0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -556,13 +556,6 @@ public class KeyguardViewMediator extends SystemUI {
notifyHasLockscreenWallpaperChanged(hasLockscreenWallpaper);
}
}
-
- @Override
- public void onStrongAuthStateChanged(int userId) {
- if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
- doKeyguardLocked(null);
- }
- }
};
ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
@@ -1326,8 +1319,7 @@ public class KeyguardViewMediator extends SystemUI {
}
// if another app is disabling us, don't show
- if (!mExternallyEnabled
- && !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
+ if (!mExternallyEnabled) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
mNeedToReshowWhenReenabled = true;

View File

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kunal Malhotra <malhk@google.com>
Date: Thu, 2 Feb 2023 23:48:27 +0000
Subject: [PATCH] Adding in verification of calling UID in onShellCommand
Test: manual testing on device
Bug: b/261709193
(cherry picked from commit b651d295b44eb82d664861b77f33dbde1bce9453)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3ef3f18ba3094c4cc4f954ba23d1da421f9ca8b0)
Merged-In: I68903ebd6d3d85f4bc820b745e3233a448b62273
Change-Id: I68903ebd6d3d85f4bc820b745e3233a448b62273
---
.../java/com/android/server/am/ActivityManagerService.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3e99e594a702..faeb5f348834 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9884,6 +9884,13 @@ public class ActivityManagerService extends IActivityManager.Stub
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != ROOT_UID && callingUid != Process.SHELL_UID) {
+ if (resultReceiver != null) {
+ resultReceiver.send(-1, null);
+ }
+ throw new SecurityException("Shell commands are only callable by root or shell");
+ }
(new ActivityManagerShellCommand(this, false)).exec(
this, in, out, err, args, callback, resultReceiver);
}

View File

@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Beverly Tai <beverlyt@google.com>
Date: Tue, 19 Sep 2023 21:01:11 +0000
Subject: [PATCH] Updated: always show the keyguard on device lockdown
Additionally, don't hide keyguard when it's disabled if the user has locked
down the device.
Manual test steps:
1. Enable app pinning and disable "Ask for PIN before unpinning" setting
2. Pin an app (ie: Settings)
3. Lockdown from the power menu
4. Observe: user is brought to the keyguard, primary auth is
required to enter the device.
=> After entering correct credential, the device is still in
app pinning mode.
=> After entering an incorrect credential, the keyguard remains
showing and the user can attempt again up to the limit
Bug: 300463732
Bug: 218495634
Test: atest KeyguardViewMediatorTest
Test: manual
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:35a6e2f2c952440b1102033b2c3e496438503cff)
Merged-In: I70fdae80f717712b3dfc9df54b9649959b4bb8f0
Change-Id: I70fdae80f717712b3dfc9df54b9649959b4bb8f0
---
.../systemui/keyguard/KeyguardViewMediator.java | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e21b14dec0b0..5c343c941454 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -541,6 +541,13 @@ public class KeyguardViewMediator extends SystemUI {
}
}
+ @Override
+ public void onStrongAuthStateChanged(int userId) {
+ if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
+ doKeyguardLocked(null);
+ }
+ }
+
@Override
public void onTrustChanged(int userId) {
if (userId == KeyguardUpdateMonitor.getCurrentUser()) {
@@ -1107,6 +1114,10 @@ public class KeyguardViewMediator extends SystemUI {
mExternallyEnabled = enabled;
if (!enabled && mShowing) {
+ if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
+ Log.d(TAG, "keyguardEnabled(false) overridden by user lockdown");
+ return;
+ }
if (mExitSecureCallback != null) {
if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
// we're in the process of handling a request to verify the user
@@ -1318,8 +1329,9 @@ public class KeyguardViewMediator extends SystemUI {
return;
}
- // if another app is disabling us, don't show
- if (!mExternallyEnabled) {
+ // if another app is disabling us, don't show unless we're in lockdown mode
+ if (!mExternallyEnabled
+ && !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
mNeedToReshowWhenReenabled = true;

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Haibo Huang <hhb@google.com>
Date: Tue, 28 Apr 2020 14:47:47 -0700
Subject: [PATCH] Fix the use of pdfium
FPDF_LoadPage returns FPDF_PAGE and that's also what expected by other
APIs. There's no need for conversion.
This works now because FPDF_PAGE is defined as void*. But will fails
with new pdfium.
Bug: 155031873
Change-Id: I74381ec8ec36797a5901ea3de845c2b5d798ba0c
(cherry picked from commit 24fca180a146ec6e94a5058280c593216edbae15)
---
core/jni/android/graphics/pdf/PdfEditor.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
index 10c30260d7e3..913952f9e76c 100644
--- a/core/jni/android/graphics/pdf/PdfEditor.cpp
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -111,7 +111,7 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt
jlong transformPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom) {
FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
- FPDF_PAGE* page = (FPDF_PAGE*) FPDF_LoadPage(document, pageIndex);
+ FPDF_PAGE page = FPDF_LoadPage(document, pageIndex);
if (!page) {
jniThrowException(env, "java/lang/IllegalStateException",
"cannot open page");

View File

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hongwei Wang <hwwang@google.com>
Date: Thu, 23 Feb 2023 13:23:37 -0800
Subject: [PATCH] Remove Activity if it enters PiP without window
This is to prevent malicious app entering PiP without being visible
first, like blocking onResume from completion. Which in turn
leaves the PiP window in limbo and non-interactable.
Bug: 265293293
Test: atest PinnedStackTests
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4fad1456409b79d6e649a29d5116a4fe3160bd21)
Merged-In: I458a9508662e72a1adb9d9818105f2e9d7096d44
Change-Id: I458a9508662e72a1adb9d9818105f2e9d7096d44
---
.../core/java/com/android/server/wm/ActivityRecord.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 55e8e19fd278..66514b44ba94 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -781,6 +781,12 @@ final class ActivityRecord extends ConfigurationContainer {
}
schedulePictureInPictureModeChanged(newConfig);
scheduleMultiWindowModeChanged(newConfig);
+ if (inPictureInPictureMode && mAppWindowToken != null && mAppWindowToken.findMainWindow() == null) {
+ // Prevent malicious app entering PiP without valid WindowState, which can in turn
+ // result a non-touchable PiP window since the InputConsumer for PiP requires it.
+ EventLog.writeEvent(0x534e4554, "265293293", -1, "");
+ mAppWindowToken.removeImmediately();
+ }
}
}

View File

@ -0,0 +1,175 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Valentin Iftime <valiiftime@google.com>
Date: Wed, 22 Feb 2023 09:38:55 +0100
Subject: [PATCH] Prevent RemoteViews crashing SystemUi
Catch canvas drawing exceptions caused by unsuported image sizes.
Test: 1. Post a custom view notification with a layout
containing an ImageView that references a 5k x 5k image
2. Add an App Widget to the home screen with that has the
layout mentioned above as preview/initial layout.
Bug: 268193777
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:cfc0b34432ab54e3fa472db5c43e620293f64a5d)
Merged-In: Ib3bda769c499b4069b49c566b1b227f98f707a8a
Change-Id: Ib3bda769c499b4069b49c566b1b227f98f707a8a
---
.../android/appwidget/AppWidgetHostView.java | 39 ++++++++++++++-----
.../row/ExpandableNotificationRow.java | 1 +
.../row/NotificationContentView.java | 37 ++++++++++++++++++
3 files changed, 67 insertions(+), 10 deletions(-)
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 85f0e2342412..eafb631216e5 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -28,6 +28,7 @@ import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
@@ -250,19 +251,26 @@ public class AppWidgetHostView extends FrameLayout {
super.onLayout(changed, left, top, right, bottom);
} catch (final RuntimeException e) {
Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e);
- removeViewInLayout(mView);
- View child = getErrorView();
- prepareView(child);
- addViewInLayout(child, 0, child.getLayoutParams());
- measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
- child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
- child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
- mView = child;
- mViewMode = VIEW_MODE_ERROR;
+ handleViewError();
}
}
+ /**
+ * Remove bad view and replace with error message view
+ */
+ private void handleViewError() {
+ removeViewInLayout(mView);
+ View child = getErrorView();
+ prepareView(child);
+ addViewInLayout(child, 0, child.getLayoutParams());
+ measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+ child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
+ child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
+ mView = child;
+ mViewMode = VIEW_MODE_ERROR;
+ }
+
/**
* Provide guidance about the size of this widget to the AppWidgetManager. The widths and
* heights should correspond to the full area the AppWidgetHostView is given. Padding added by
@@ -711,4 +719,15 @@ public class AppWidgetHostView extends FrameLayout {
}
return null;
}
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ try {
+ super.dispatchDraw(canvas);
+ } catch (Exception e) {
+ // Catch draw exceptions that may be caused by RemoteViews
+ Log.e(TAG, "Drawing view failed: " + e);
+ post(this::handleViewError);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 12d537d3c646..37f780290935 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -69,6 +69,7 @@ import android.widget.RemoteViews;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ContrastColorUtil;
import com.android.internal.widget.CachingIconView;
import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 0c5b27b92878..e05269ebf6b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -20,8 +20,10 @@ import android.annotation.Nullable;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
+import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Build;
+import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -39,6 +41,7 @@ import android.widget.LinearLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.Dependency;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
import com.android.systemui.statusbar.MediaTransferManager;
import com.android.systemui.statusbar.RemoteInputController;
@@ -111,6 +114,8 @@ public class NotificationContentView extends FrameLayout {
private NotificationGroupManager mGroupManager;
private RemoteInputController mRemoteInputController;
private Runnable mExpandedVisibleListener;
+ private IStatusBarService mStatusBarService;
+
/**
* List of listeners for when content views become inactive (i.e. not the showing view).
*/
@@ -167,6 +172,7 @@ public class NotificationContentView extends FrameLayout {
mMediaTransferManager = new MediaTransferManager(getContext());
mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
mSmartReplyController = Dependency.get(SmartReplyController.class);
+ mStatusBarService = Dependency.get(IStatusBarService.class);
initView();
}
@@ -1818,4 +1824,35 @@ public class NotificationContentView extends FrameLayout {
public RemoteInputView getExpandedRemoteInput() {
return mExpandedRemoteInput;
}
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ try {
+ super.dispatchDraw(canvas);
+ } catch (Exception e) {
+ // Catch draw exceptions that may be caused by RemoteViews
+ Log.e(TAG, "Drawing view failed: " + e);
+ cancelNotification(e);
+ }
+ }
+
+ private void cancelNotification(Exception exception) {
+ try {
+ setVisibility(GONE);
+ if (mStatusBarService != null) {
+ // report notification inflation errors back up
+ // to notification delegates
+ mStatusBarService.onNotificationError(
+ mStatusBarNotification.getPackageName(),
+ mStatusBarNotification.getTag(),
+ mStatusBarNotification.getId(),
+ mStatusBarNotification.getUid(),
+ mStatusBarNotification.getInitialPid(),
+ exception.getMessage(),
+ mStatusBarNotification.getUser().getIdentifier());
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "cancelNotification failed: " + ex);
+ }
+ }
}

View File

@ -0,0 +1,221 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Julia Reynolds <juliacr@google.com>
Date: Tue, 7 Mar 2023 15:44:49 -0500
Subject: [PATCH] Allow filtering of services
Test: ServiceListingTest
Bug: 260570119
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:44dcb8351e61f4b3a63ec68fa5d8490501e8a823)
Merged-In: Ib4740ba401667de62fa1a33334c2c1fbee25b760
Change-Id: Ib4740ba401667de62fa1a33334c2c1fbee25b760
---
.../applications/ServiceListing.java | 16 ++-
.../applications/ServiceListingTest.java | 98 ++++++++++++++++++-
2 files changed, 111 insertions(+), 3 deletions(-)
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
index 454d1dce0b2f..59bb2730bcf6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
@@ -35,6 +35,7 @@ import android.util.Slog;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.function.Predicate;
/**
* Class for managing services matching a given intent and requesting a given permission.
@@ -50,11 +51,12 @@ public class ServiceListing {
private final HashSet<ComponentName> mEnabledServices = new HashSet<>();
private final List<ServiceInfo> mServices = new ArrayList<>();
private final List<Callback> mCallbacks = new ArrayList<>();
+ private final Predicate mValidator;
private boolean mListening;
private ServiceListing(Context context, String tag,
- String setting, String intentAction, String permission, String noun) {
+ String setting, String intentAction, String permission, String noun, Predicate validator) {
mContentResolver = context.getContentResolver();
mContext = context;
mTag = tag;
@@ -62,6 +64,7 @@ public class ServiceListing {
mIntentAction = intentAction;
mPermission = permission;
mNoun = noun;
+ mValidator = validator;
}
public void addCallback(Callback callback) {
@@ -141,6 +144,9 @@ public class ServiceListing {
+ mPermission);
continue;
}
+ if (mValidator != null && !mValidator.test(info)) {
+ continue;
+ }
mServices.add(info);
}
for (Callback callback : mCallbacks) {
@@ -186,6 +192,7 @@ public class ServiceListing {
private String mIntentAction;
private String mPermission;
private String mNoun;
+ private Predicate mValidator;
public Builder(Context context) {
mContext = context;
@@ -216,8 +223,13 @@ public class ServiceListing {
return this;
}
+ public Builder setValidator(Predicate<ServiceInfo> validator) {
+ mValidator = validator;
+ return this;
+ }
+
public ServiceListing build() {
- return new ServiceListing(mContext, mTag, mSetting, mIntentAction, mPermission, mNoun);
+ return new ServiceListing(mContext, mTag, mSetting, mIntentAction, mPermission, mNoun, mValidator);
}
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
index f7fd25b9fb7d..7ff0988c494d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
@@ -18,20 +18,35 @@ package com.android.settingslib.applications;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.provider.Settings;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.collect.ImmutableList;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class ServiceListingTest {
@@ -39,16 +54,97 @@ public class ServiceListingTest {
private static final String TEST_INTENT = "com.example.intent";
private ServiceListing mServiceListing;
+ private Context mContext;
+ private PackageManager mPm;
@Before
public void setUp() {
- mServiceListing = new ServiceListing.Builder(RuntimeEnvironment.application)
+ mPm = mock(PackageManager.class);
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getPackageManager()).thenReturn(mPm);
+
+ mServiceListing = new ServiceListing.Builder(mContext)
+ .setTag("testTag")
+ .setSetting(TEST_SETTING)
+ .setNoun("testNoun")
+ .setIntentAction(TEST_INTENT)
+ .setPermission("testPermission")
+ .build();
+ }
+
+ @Test
+ public void testValidator() {
+ ServiceInfo s1 = new ServiceInfo();
+ s1.permission = "testPermission";
+ s1.packageName = "pkg";
+ ServiceInfo s2 = new ServiceInfo();
+ s2.permission = "testPermission";
+ s2.packageName = "pkg2";
+ ResolveInfo r1 = new ResolveInfo();
+ r1.serviceInfo = s1;
+ ResolveInfo r2 = new ResolveInfo();
+ r2.serviceInfo = s2;
+
+ when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
+ ImmutableList.of(r1, r2));
+
+ mServiceListing = new ServiceListing.Builder(mContext)
+ .setTag("testTag")
+ .setSetting(TEST_SETTING)
+ .setNoun("testNoun")
+ .setIntentAction(TEST_INTENT)
+ .setValidator(info -> {
+ if (info.packageName.equals("pkg")) {
+ return true;
+ }
+ return false;
+ })
+ .setPermission("testPermission")
+ .build();
+ ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
+ mServiceListing.addCallback(callback);
+ mServiceListing.reload();
+
+ verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
+ verify(callback, times(1)).onServicesReloaded(captor.capture());
+
+ assertThat(captor.getValue().size()).isEqualTo(1);
+ assertThat(captor.getValue().get(0)).isEqualTo(s1);
+ }
+
+ @Test
+ public void testNoValidator() {
+ ServiceInfo s1 = new ServiceInfo();
+ s1.permission = "testPermission";
+ s1.packageName = "pkg";
+ ServiceInfo s2 = new ServiceInfo();
+ s2.permission = "testPermission";
+ s2.packageName = "pkg2";
+ ResolveInfo r1 = new ResolveInfo();
+ r1.serviceInfo = s1;
+ ResolveInfo r2 = new ResolveInfo();
+ r2.serviceInfo = s2;
+
+ when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
+ ImmutableList.of(r1, r2));
+
+ mServiceListing = new ServiceListing.Builder(mContext)
.setTag("testTag")
.setSetting(TEST_SETTING)
.setNoun("testNoun")
.setIntentAction(TEST_INTENT)
.setPermission("testPermission")
.build();
+ ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
+ mServiceListing.addCallback(callback);
+ mServiceListing.reload();
+
+ verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
+ verify(callback, times(1)).onServicesReloaded(captor.capture());
+
+ assertThat(captor.getValue().size()).isEqualTo(2);
}
@Test

View File

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeff DeCew <jeffdq@google.com>
Date: Fri, 24 Mar 2023 16:15:24 +0000
Subject: [PATCH] Add BubbleMetadata detection to block FSI
Bug: 274759612
Test: atest NotificationInterruptStateProviderImplTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c60e264a551df9f880fd73683321b7e821429da7)
Merged-In: I40e1aa6377b8a60d91cb2f4189df1e9a4a4578a2
Change-Id: I40e1aa6377b8a60d91cb2f4189df1e9a4a4578a2
---
.../NotificationInterruptionStateProvider.java | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index ff71db4dc3b5..579c2023e4bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -461,6 +461,20 @@ public class NotificationInterruptionStateProvider {
return false;
}
+ // If the notification has suppressive BubbleMetadata, block FSI and warn.
+ Notification.BubbleMetadata bubbleMetadata = sbn.getNotification().getBubbleMetadata();
+ if (bubbleMetadata != null && bubbleMetadata.isNotificationSuppressed()) {
+ // b/274759612: Detect and report an event when a notification has both an FSI and a
+ // suppressive BubbleMetadata, and now correctly block the FSI from firing.
+ final int uid = entry.notification.getUid();
+ android.util.EventLog.writeEvent(0x534e4554, "274759612", uid, "bubbleMetadata");
+ if (DEBUG) {
+ Log.w(TAG, "No FullScreenIntent: WARNING: BubbleMetadata may prevent HUN: "
+ + entry.key);
+ }
+ return false;
+ }
+
// If the screen is off, then launch the FullScreenIntent
if (!mPowerManager.isInteractive()) {
if (DEBUG) {

View File

@ -0,0 +1,231 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Nate(Qiang) Jiang" <qiangjiang@google.com>
Date: Wed, 26 Oct 2022 21:52:34 +0000
Subject: [PATCH] Passpoint Add more check to limit the config size
Bug: 245299920
Test: atest con.android.server.wifi
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e1a80210f3f0391c989a2a86fd4aef739bf2574c)
Merged-In: I97522ce3607547c10025caa107cd1a40455a9c5d
Change-Id: I97522ce3607547c10025caa107cd1a40455a9c5d
---
.../wifi/hotspot2/PasspointConfiguration.java | 47 ++++++++++-
.../net/wifi/hotspot2/pps/Credential.java | 10 ++-
.../android/net/wifi/hotspot2/pps/HomeSp.java | 79 ++++++++++++++++++-
.../hotspot2/PasspointConfigurationTest.java | 2 +-
4 files changed, 134 insertions(+), 4 deletions(-)
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index dd23e504c467..1fe66c0163b1 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -52,8 +52,42 @@ public final class PasspointConfiguration implements Parcelable {
/**
* Maximum bytes for URL string.
+ * @hide
+ */
+ public static final int MAX_URL_BYTES = 2048;
+
+ /**
+ * Maximum size for match entry, just to limit the size of the Passpoint config.
+ * @hide
+ */
+ public static final int MAX_NUMBER_OF_ENTRIES = 16;
+
+ /**
+ * Maximum size for OI entry.
+ * The spec allows a string of up to 255 characters, with comma delimited numbers like
+ * 001122,334455. So with minimum OI size of 7, the maximum amount of OIs is 36.
+ * @hide
+ */
+ public static final int MAX_NUMBER_OF_OI = 36;
+
+
+ /**
+ * Maximum bytes for a string entry like FQDN and friendly name.
+ * @hide
*/
- private static final int MAX_URL_BYTES = 1023;
+ public static final int MAX_STRING_LENGTH = 255;
+
+ /**
+ * HESSID is 48 bit.
+ * @hide
+ */
+ public static final long MAX_HESSID_VALUE = ((long) 1 << 48) - 1;
+
+ /**
+ * Organization Identifiers is 3 or 5 Octets. 24 or 36 bit.
+ * @hide
+ */
+ public static final long MAX_OI_VALUE = ((long) 1 << 40) - 1;
/**
* Integer value used for indicating null value in the Parcel.
@@ -572,7 +606,18 @@ public final class PasspointConfiguration implements Parcelable {
return false;
}
+ if (mSubscriptionType != null) {
+ if (mSubscriptionType.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "SubscriptionType is too long");
+ return false;
+ }
+ }
+
if (mTrustRootCertList != null) {
+ if (mTrustRootCertList.size() > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "Too many TrustRootCert");
+ return false;
+ }
for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
String url = entry.getKey();
byte[] certFingerprint = entry.getValue();
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 9409c03c614d..6d12ccef29ae 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -16,6 +16,8 @@
package android.net.wifi.hotspot2.pps;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH;
+
import android.net.wifi.EAPConstants;
import android.net.wifi.ParcelUtil;
import android.os.Parcel;
@@ -413,7 +415,13 @@ public final class Credential implements Parcelable {
+ mPassword.getBytes(StandardCharsets.UTF_8).length);
return false;
}
-
+ if (mSoftTokenApp != null) {
+ if (mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "app name exceeding maximum length: "
+ + mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length);
+ return false;
+ }
+ }
// Only supports EAP-TTLS for user credential.
if (mEapType != EAPConstants.EAP_TTLS) {
Log.d(TAG, "Invalid EAP Type for user credential: " + mEapType);
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 49a76c33d209..cdb9ec5cec3c 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -16,6 +16,13 @@
package android.net.wifi.hotspot2.pps;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_HESSID_VALUE;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_ENTRIES;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_OI;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_OI_VALUE;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH;
+import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES;
+
import android.os.Parcelable;
import android.os.Parcel;
import android.text.TextUtils;
@@ -328,16 +335,86 @@ public final class HomeSp implements Parcelable {
Log.d(TAG, "Missing FQDN");
return false;
}
+ if (mFqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "FQDN is too long");
+ return false;
+ }
if (TextUtils.isEmpty(mFriendlyName)) {
Log.d(TAG, "Missing friendly name");
return false;
}
+ if (mFriendlyName.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) {
+ Log.d(TAG, "Friendly name is too long");
+ return false;
+ }
// Verify SSIDs specified in the NetworkID
if (mHomeNetworkIds != null) {
+ if (mHomeNetworkIds.size() > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "too many SSID in HomeNetworkIDs");
+ return false;
+ }
for (Map.Entry<String, Long> entry : mHomeNetworkIds.entrySet()) {
if (entry.getKey() == null ||
entry.getKey().getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
- Log.d(TAG, "Invalid SSID in HomeNetworkIDs");
+ Log.d(TAG, "SSID is too long in HomeNetworkIDs");
+ return false;
+ }
+ if (entry.getValue() != null
+ && (entry.getValue() > MAX_HESSID_VALUE || entry.getValue() < 0)) {
+ Log.d(TAG, "HESSID is out of range");
+ return false;
+ }
+ }
+ }
+ if (mIconUrl != null && mIconUrl.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) {
+ Log.d(TAG, "Icon URL is too long");
+ return false;
+ }
+ if (mMatchAllOis != null) {
+ if (mMatchAllOis.length > MAX_NUMBER_OF_OI) {
+ Log.d(TAG, "too many match all Organization Identifiers in the profile");
+ return false;
+ }
+ for (long oi : mMatchAllOis) {
+ if (oi > MAX_OI_VALUE || oi < 0) {
+ Log.d(TAG, "Organization Identifiers is out of range");
+ return false;
+ }
+ }
+ }
+ if (mMatchAnyOis != null) {
+ if (mMatchAnyOis.length > MAX_NUMBER_OF_OI) {
+ Log.d(TAG, "too many match any Organization Identifiers in the profile");
+ return false;
+ }
+ for (long oi : mMatchAnyOis) {
+ if (oi > MAX_OI_VALUE || oi < 0) {
+ Log.d(TAG, "Organization Identifiers is out of range");
+ return false;
+ }
+ }
+ }
+ if (mRoamingConsortiumOis != null) {
+ if (mRoamingConsortiumOis.length > MAX_NUMBER_OF_OI) {
+ Log.d(TAG, "too many Roaming Consortium Organization Identifiers in the "
+ + "profile");
+ return false;
+ }
+ for (long oi : mRoamingConsortiumOis) {
+ if (oi > MAX_OI_VALUE || oi < 0) {
+ Log.d(TAG, "Organization Identifiers is out of range");
+ return false;
+ }
+ }
+ }
+ if (mOtherHomePartners != null) {
+ if (mOtherHomePartners.length > MAX_NUMBER_OF_ENTRIES) {
+ Log.d(TAG, "too many other home partners in the profile");
+ return false;
+ }
+ for (String fqdn : mOtherHomePartners) {
+ if (fqdn.length() > MAX_STRING_LENGTH) {
+ Log.d(TAG, "FQDN is too long in OtherHomePartners");
return false;
}
}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index fc03e7eb6176..6b4f7b0cc51e 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -43,7 +43,7 @@ import java.util.Map;
*/
@SmallTest
public class PasspointConfigurationTest {
- private static final int MAX_URL_BYTES = 1023;
+ private static final int MAX_URL_BYTES = 2048;
private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
/**

View File

@ -0,0 +1,145 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lucas Lin <lucaslin@google.com>
Date: Fri, 3 Mar 2023 08:13:50 +0000
Subject: [PATCH] Sanitize VPN label to prevent HTML injection
This commit will try to sanitize the content of VpnDialog. This
commit creates a function which will try to sanitize the VPN
label, if the sanitized VPN label is different from the original
one, which means the VPN label might contain HTML tag or the VPN
label violates the words restriction(may contain some wording
which will mislead the user). For this kind of case, show the
package name instead of the VPN label to prevent misleading the
user.
The malicious VPN app might be able to add a large number of line
breaks with HTML in order to hide the system-displayed text from
the user in the connection request dialog. Thus, sanitizing the
content of the dialog is needed.
Bug: 204554636
Test: N/A
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2178216b98bf9865edee198f45192f0b883624ab)
Merged-In: I8eb890fd2e5797d8d6ab5b12f9c628bc9616081d
Change-Id: I8eb890fd2e5797d8d6ab5b12f9c628bc9616081d
---
packages/VpnDialogs/res/values/strings.xml | 28 ++++++++++
.../com/android/vpndialogs/ConfirmDialog.java | 53 +++++++++++++++++--
2 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/packages/VpnDialogs/res/values/strings.xml b/packages/VpnDialogs/res/values/strings.xml
index 443a9bc33b90..b4166f0bedfd 100644
--- a/packages/VpnDialogs/res/values/strings.xml
+++ b/packages/VpnDialogs/res/values/strings.xml
@@ -89,4 +89,32 @@
without any consequences. [CHAR LIMIT=20] -->
<string name="dismiss">Dismiss</string>
+ <!-- Malicious VPN apps may provide very long labels or cunning HTML to trick the system dialogs
+ into displaying what they want. The system will attempt to sanitize the label, and if the
+ label is deemed dangerous, then this string is used instead. The first argument is the
+ first 30 characters of the label, and the second argument is the package name of the app.
+ Example : Normally a VPN app may be called "My VPN app" in which case the dialog will read
+ "My VPN app wants to set up a VPN connection...". If the label is very long, then, this
+ will be used to show "VerylongVPNlabel… (com.my.vpn.app) wants to set up a VPN
+ connection...". For this case, the code will refer to sanitized_vpn_label_with_ellipsis.
+ -->
+ <string name="sanitized_vpn_label_with_ellipsis">
+ <xliff:g id="sanitized_vpn_label_with_ellipsis" example="My VPN app">%1$s</xliff:g>… (
+ <xliff:g id="sanitized_vpn_label_with_ellipsis" example="com.my.vpn.app">%2$s</xliff:g>)
+ </string>
+
+ <!-- Malicious VPN apps may provide very long labels or cunning HTML to trick the system dialogs
+ into displaying what they want. The system will attempt to sanitize the label, and if the
+ label is deemed dangerous, then this string is used instead. The first argument is the
+ label, and the second argument is the package name of the app.
+ Example : Normally a VPN app may be called "My VPN app" in which case the dialog will read
+ "My VPN app wants to set up a VPN connection...". If the VPN label contains HTML tag but
+ the length is not very long, the dialog will show "VpnLabelWith&lt;br&gt;HtmlTag
+ (com.my.vpn.app) wants to set up a VPN connection...". For this case, the code will refer
+ to sanitized_vpn_label.
+ -->
+ <string name="sanitized_vpn_label">
+ <xliff:g id="sanitized_vpn_label" example="My VPN app">%1$s</xliff:g> (
+ <xliff:g id="sanitized_vpn_label" example="com.my.vpn.app">%2$s</xliff:g>)
+ </string>
</resources>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
index 48adb9ba3f63..f74cc2f93916 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
@@ -43,10 +43,52 @@ public class ConfirmDialog extends AlertActivity
implements DialogInterface.OnClickListener, ImageGetter {
private static final String TAG = "VpnConfirm";
+ // Usually the label represents the app name, 150 code points might be enough to display the app
+ // name, and 150 code points won't cover the warning message from VpnDialog.
+ static final int MAX_VPN_LABEL_LENGTH = 150;
+
private String mPackage;
private IConnectivityManager mService;
+ private View mView;
+
+ /**
+ * This function will use the string resource to combine the VPN label and the package name.
+ *
+ * If the VPN label violates the length restriction, the first 30 code points of VPN label and
+ * the package name will be returned. Or return the VPN label and the package name directly if
+ * the VPN label doesn't violate the length restriction.
+ *
+ * The result will be something like,
+ * - ThisIsAVeryLongVpnAppNameWhich... (com.vpn.app)
+ * if the VPN label violates the length restriction.
+ * or
+ * - VpnLabelWith&lt;br&gt;HtmlTag (com.vpn.app)
+ * if the VPN label doesn't violate the length restriction.
+ *
+ */
+ private String getSimplifiedLabel(String vpnLabel, String packageName) {
+ if (vpnLabel.codePointCount(0, vpnLabel.length()) > 30) {
+ return getString(R.string.sanitized_vpn_label_with_ellipsis,
+ vpnLabel.substring(0, vpnLabel.offsetByCodePoints(0, 30)),
+ packageName);
+ }
+
+ return getString(R.string.sanitized_vpn_label, vpnLabel, packageName);
+ }
+
+ protected String getSanitizedVpnLabel(String vpnLabel, String packageName) {
+ final String sanitizedVpnLabel = Html.escapeHtml(vpnLabel);
+ final boolean exceedMaxVpnLabelLength = sanitizedVpnLabel.codePointCount(0,
+ sanitizedVpnLabel.length()) > MAX_VPN_LABEL_LENGTH;
+ if (exceedMaxVpnLabelLength || !vpnLabel.equals(sanitizedVpnLabel)) {
+ return getSimplifiedLabel(sanitizedVpnLabel, packageName);
+ }
+
+ return sanitizedVpnLabel;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -69,15 +111,16 @@ public class ConfirmDialog extends AlertActivity
finish();
return;
}
- View view = View.inflate(this, R.layout.confirm, null);
- ((TextView) view.findViewById(R.id.warning)).setText(
- Html.fromHtml(getString(R.string.warning, getVpnLabel()),
- this, null /* tagHandler */));
+ mView = View.inflate(this, R.layout.confirm, null);
+ ((TextView) mView.findViewById(R.id.warning)).setText(
+ Html.fromHtml(getString(R.string.warning, getSanitizedVpnLabel(
+ getVpnLabel().toString(), mPackage)),
+ this /* imageGetter */, null /* tagHandler */));
mAlertParams.mTitle = getText(R.string.prompt);
mAlertParams.mPositiveButtonText = getText(android.R.string.ok);
mAlertParams.mPositiveButtonListener = this;
mAlertParams.mNegativeButtonText = getText(android.R.string.cancel);
- mAlertParams.mView = view;
+ mAlertParams.mView = mView;
setupAlert();
getWindow().setCloseOnTouchOutside(false);

View File

@ -0,0 +1,99 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A1s=20Kurucz?= <kurucz@google.com>
Date: Fri, 21 Apr 2023 09:45:07 +0000
Subject: [PATCH] Truncate ShortcutInfo Id
Creating Conversation with a ShortcutId longer than 65_535 (max unsigned short), we did not save the conversation settings into the notification_policy.xml due to a restriction in FastDataOutput.
This put us to a state where the user changing the importance or turning off the notifications for the given conversation had no effect on notification behavior.
Fixes: 273729476
Test: atest ShortcutManagerTest2
Test: Create a test app which creates a Conversation with a long shortcutId. Go to the Conversation Settings and turn off Notifications. Post a new Notification to this Conversation and see if it is displayed.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f31df6234091b5b1de258a01dd4b2d8e5415ee2e)
Merged-In: I2617de6f9e8a7dbfd8fbeff589a7d592f00d87c5
Change-Id: I2617de6f9e8a7dbfd8fbeff589a7d592f00d87c5
---
.../java/android/content/pm/ShortcutInfo.java | 20 ++++++++++++++++---
.../server/pm/ShortcutManagerTest2.java | 10 ++++++++++
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 58aacc2c36c7..a50b321f6827 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -236,6 +236,12 @@ public final class ShortcutInfo implements Parcelable {
*/
public static final int DISABLED_REASON_OTHER_RESTORE_ISSUE = 103;
+ /**
+ * The maximum length of Shortcut ID. IDs will be truncated at this limit.
+ * @hide
+ */
+ public static final int MAX_ID_LENGTH = 1000;
+
/** @hide */
@IntDef(prefix = { "DISABLED_REASON_" }, value = {
DISABLED_REASON_NOT_DISABLED,
@@ -408,8 +414,7 @@ public final class ShortcutInfo implements Parcelable {
private ShortcutInfo(Builder b) {
mUserId = b.mContext.getUserId();
-
- mId = Preconditions.checkStringNotEmpty(b.mId, "Shortcut ID must be provided");
+ mId = getSafeId(Preconditions.checkStringNotEmpty(b.mId, "Shortcut ID must be provided"));
// Note we can't do other null checks here because SM.updateShortcuts() takes partial
// information.
@@ -511,6 +516,14 @@ public final class ShortcutInfo implements Parcelable {
return ret;
}
+ @NonNull
+ private static String getSafeId(@NonNull String id) {
+ if (id.length() > MAX_ID_LENGTH) {
+ return id.substring(0, MAX_ID_LENGTH);
+ }
+ return id;
+ }
+
/**
* Throws if any of the mandatory fields is not set.
*
@@ -2009,7 +2022,8 @@ public final class ShortcutInfo implements Parcelable {
final ClassLoader cl = getClass().getClassLoader();
mUserId = source.readInt();
- mId = source.readString();
+ mId = getSafeId(Preconditions.checkStringNotEmpty(source.readString(),
+ "Shortcut ID must be provided"));
mPackageName = source.readString();
mActivity = source.readParcelable(cl);
mFlags = source.readInt();
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index fd3678dae0c4..18970322d854 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -53,6 +53,7 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
+import java.util.Collections;
import java.util.Locale;
/**
@@ -223,6 +224,15 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
});
}
+ public void testShortcutIdTruncated() {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(),
+ String.join("", Collections.nCopies(Short.MAX_VALUE, "s"))).build();
+
+ assertTrue(
+ "id must be truncated to MAX_ID_LENGTH",
+ si.getId().length() <= ShortcutInfo.MAX_ID_LENGTH);
+ }
+
public void testShortcutInfoParcel() {
setCaller(CALLING_PACKAGE_1, USER_10);
ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext)

View File

@ -0,0 +1,148 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ioana Alexandru <aioana@google.com>
Date: Thu, 27 Apr 2023 14:55:28 +0000
Subject: [PATCH] Verify URI permissions for notification shortcutIcon.
Bug: 277593270
Test: atest NotificationManagerServiceTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:47e661cbf37e1dedf676f482ac07ffc433c92d0b)
Merged-In: I1efaa1301bca36895ad4322a919d7421156a60df
Change-Id: I1efaa1301bca36895ad4322a919d7421156a60df
---
core/java/android/app/Notification.java | 24 +++++++++
.../NotificationManagerServiceTest.java | 51 ++++++++++++++++++-
2 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3e75c52bf893..5b9e1ea6daf1 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -18,6 +18,7 @@ package android.app;
import static android.annotation.Dimension.DP;
import static android.graphics.drawable.Icon.TYPE_BITMAP;
+import static android.graphics.drawable.Icon.TYPE_URI;
import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast;
@@ -2434,6 +2435,14 @@ public class Notification implements Parcelable
}
}
+ private static void visitIconUri(@NonNull Consumer<Uri> visitor, @Nullable Icon icon) {
+ if (icon == null) return;
+ final int iconType = icon.getType();
+ if (iconType == TYPE_URI) {
+ visitor.accept(icon.getUri());
+ }
+ }
+
/**
* Note all {@link Uri} that are referenced internally, with the expectation
* that Uri permission grants will need to be issued to ensure the recipient
@@ -2449,7 +2458,18 @@ public class Notification implements Parcelable
if (bigContentView != null) bigContentView.visitUris(visitor);
if (headsUpContentView != null) headsUpContentView.visitUris(visitor);
+ visitIconUri(visitor, mSmallIcon);
+ visitIconUri(visitor, mLargeIcon);
+
+ if (actions != null) {
+ for (Action action : actions) {
+ visitIconUri(visitor, action.getIcon());
+ }
+ }
+
if (extras != null) {
+ visitIconUri(visitor, extras.getParcelable(EXTRA_LARGE_ICON_BIG));
+
visitor.accept(extras.getParcelable(EXTRA_AUDIO_CONTENTS_URI));
if (extras.containsKey(EXTRA_BACKGROUND_IMAGE_URI)) {
visitor.accept(Uri.parse(extras.getString(EXTRA_BACKGROUND_IMAGE_URI)));
@@ -2473,6 +2493,10 @@ public class Notification implements Parcelable
}
}
}
+
+ if (mBubbleMetadata != null) {
+ visitIconUri(visitor, mBubbleMetadata.getIcon());
+ }
}
/**
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 6c1620751866..da4a2420b924 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3414,6 +3414,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testVisitUris() throws Exception {
final Uri audioContents = Uri.parse("content://com.example/audio");
final Uri backgroundImage = Uri.parse("content://com.example/background");
+ final Icon smallIcon = Icon.createWithContentUri("content://media/small/icon");
+ final Icon largeIcon = Icon.createWithContentUri("content://media/large/icon");
Bundle extras = new Bundle();
extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents);
@@ -3421,7 +3423,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
Notification n = new Notification.Builder(mContext, "a")
.setContentTitle("notification with uris")
- .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setSmallIcon(smallIcon)
+ .setLargeIcon(largeIcon)
.addExtras(extras)
.build();
@@ -3429,6 +3432,52 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
n.visitUris(visitor);
verify(visitor, times(1)).accept(eq(audioContents));
verify(visitor, times(1)).accept(eq(backgroundImage));
+ verify(visitor, times(1)).accept(eq(smallIcon.getUri()));
+ verify(visitor, times(1)).accept(eq(largeIcon.getUri()));
+ }
+
+ @Test
+ public void testVisitUris_messagingStyle() {
+ final Icon personIcon1 = Icon.createWithContentUri("content://media/person1");
+ final Icon personIcon2 = Icon.createWithContentUri("content://media/person2");
+ final Icon personIcon3 = Icon.createWithContentUri("content://media/person3");
+ final Person person1 = new Person.Builder()
+ .setName("Messaging Person 1")
+ .setIcon(personIcon1)
+ .build();
+ final Person person2 = new Person.Builder()
+ .setName("Messaging Person 2")
+ .setIcon(personIcon2)
+ .build();
+ final Person person3 = new Person.Builder()
+ .setName("Messaging Person 3")
+ .setIcon(personIcon3)
+ .build();
+ Icon shortcutIcon = Icon.createWithContentUri("content://media/shortcut");
+
+ Notification.Builder builder = new Notification.Builder(mContext, "a")
+ .setCategory(Notification.CATEGORY_MESSAGE)
+ .setContentTitle("new message!")
+ .setContentText("Conversation Notification")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon);
+ Notification.MessagingStyle.Message message1 = new Notification.MessagingStyle.Message(
+ "Marco?", System.currentTimeMillis(), person2);
+ Notification.MessagingStyle.Message message2 = new Notification.MessagingStyle.Message(
+ "Polo!", System.currentTimeMillis(), person3);
+ Notification.MessagingStyle style = new Notification.MessagingStyle(person1)
+ .addMessage(message1)
+ .addMessage(message2)
+ .setShortcutIcon(shortcutIcon);
+ builder.setStyle(style);
+ Notification n = builder.build();
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ n.visitUris(visitor);
+
+ verify(visitor, times(1)).accept(eq(shortcutIcon.getUri()));
+ verify(visitor, times(1)).accept(eq(personIcon1.getUri()));
+ verify(visitor, times(1)).accept(eq(personIcon2.getUri()));
+ verify(visitor, times(1)).accept(eq(personIcon3.getUri()));
}
@Test

View File

@ -0,0 +1,243 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pavel Grafov <pgrafov@google.com>
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 | 92 ++++++++++++++++++-
2 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 5e263b0d05b6..bff9bfdf185d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9075,7 +9075,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.
* <p>
* 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 b2e23da08e2d..56b2cb8f3a0b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -278,6 +278,7 @@ import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.time.LocalDate;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -287,6 +288,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Queue;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -351,6 +353,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
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 = TimeUnit.DAYS.toMillis(1);
private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
@@ -9042,6 +9053,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
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 (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
@@ -9262,6 +9279,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null");
if (packageList != null) {
+ for (String pkg : (List<String>) packageList) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
int userId = UserHandle.getCallingUserId();
List<AccessibilityServiceInfo> enabledServices = null;
long id = mInjector.binderClearCallingIdentity();
@@ -9450,6 +9471,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final int callingUserId = mInjector.userHandleGetCallingUserId();
if (packageList != null) {
+ for (String pkg : (List<String>) packageList) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get()
.getEnabledInputMethodListAsUser(callingUserId);
if (enabledImes != null) {
@@ -10424,6 +10449,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ enforceMaxStringLength(accountType, "account type");
+
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10709,6 +10736,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throws SecurityException {
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkNotNull(packages, "packages is null");
+ for (String pkg : packages) {
+ enforceMaxPackageNameLength(pkg);
+ }
synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(who);
@@ -12223,6 +12253,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ message = truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH);
+
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who,
@@ -12256,6 +12288,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
+
+ message = truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH);
+
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
@@ -12393,6 +12428,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
+ text = truncateIfLonger(text, MAX_ORG_NAME_LENGTH);
+
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -12604,9 +12641,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throw new IllegalArgumentException("ids must not be null");
}
for (String id : ids) {
- if (TextUtils.isEmpty(id)) {
- throw new IllegalArgumentException("ids must not contain empty string");
- }
+ Preconditions.checkArgument(!TextUtils.isEmpty(id), "ids must not have empty string");
+ enforceMaxStringLength(id, "affiliation id");
}
final Set<String> affiliationIds = new ArraySet<>(ids);
@@ -13728,6 +13764,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(admin, "Admin cannot be null.");
Preconditions.checkNotNull(target, "Target cannot be null.");
+ if (bundle != null) {
+ enforceMaxStringLength(bundle, "bundle");
+ }
enforceProfileOrDeviceOwner(admin);
@@ -14505,4 +14544,51 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return DevicePolicyConstants.loadFromString(
mInjector.settingsGlobalGetString(Global.DEVICE_POLICY_CONSTANTS));
}
+
+ /**
+ * 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<PersistableBundle> 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);
+ }
+ }
+ }
+ }
}

View File

@ -0,0 +1,129 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Mikhail <michaelmikhil@google.com>
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 | 52 +++++++++++++++----
1 file changed, 43 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 e2087e6ca822..5ebbfe92dc20 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -17,6 +17,8 @@
package com.android.server.media;
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,11 +50,13 @@ import android.os.Process;
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;
import com.android.server.LocalServices;
+import com.android.server.uri.UriGrantsManagerInternal;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -64,6 +68,10 @@ import java.util.List;
*/
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);
/**
@@ -85,6 +93,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private final SessionStub mSession;
private final SessionCb mSessionCb;
private final MediaSessionService mService;
+ private final UriGrantsManagerInternal mUgmInternal;
private final Context mContext;
private final Object mLock = new Object();
@@ -142,6 +151,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+ mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
}
/**
@@ -870,21 +880,45 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription)
throws RemoteException {
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;
mDuration = duration;
mMetadataDescription = metadataDescription;
+ 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 {
+ mUgmInternal.checkGrantUriPermission(getUid(),
+ getPackageName(),
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ ContentProvider.getUserIdFromUri(uri, getUserId()));
+ } catch (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) throws RemoteException {
int oldState = mPlaybackState == null

View File

@ -0,0 +1,159 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pranav Madapurmath <pmadapurmath@google.com>
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
---
.../android/telecom/ParcelableConference.java | 12 ++++-
.../java/android/telecom/StatusHints.java | 52 ++++++++++++++++++-
2 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java
index ede05943772e..4759acf612a9 100644
--- a/telecomm/java/android/telecom/ParcelableConference.java
+++ b/telecomm/java/android/telecom/ParcelableConference.java
@@ -21,11 +21,11 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.telecom.IVideoProvider;
+
import java.util.ArrayList;
import java.util.List;
-import com.android.internal.telecom.IVideoProvider;
-
/**
* A parcelable representation of a conference connection.
* @hide
@@ -155,6 +155,14 @@ public final class ParcelableConference implements Parcelable {
return mAddressPresentation;
}
+ public String getCallerDisplayName() {
+ return mCallerDisplayName;
+ }
+
+ public int getCallerDisplayNamePresentation() {
+ return mCallerDisplayNamePresentation;
+ }
+
public static final @android.annotation.NonNull Parcelable.Creator<ParcelableConference> CREATOR =
new Parcelable.Creator<ParcelableConference> () {
@Override
diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java
index 762c93a49022..17cd1156b023 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,29 @@ 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) {
+ 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);

View File

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aishwarya Mallampati <amallampati@google.com>
Date: Tue, 1 Nov 2022 17:04:35 +0000
Subject: [PATCH] DO NOT MERGE Grant carrier privileges if package has carrier
config access.
TelephonyManager#hasCarrierPrivileges internally uses
SubscriptionManager#canManageSubscription to decide whether to grant
carrier privilege status to an app or not.
SubscriptionManager#canManageSubscription returns true if caller APK's
certificate matches with one of the mNativeAccessRules or
mCarrierConfigAccessRules. This over-grants carrier privilege status
to apps that only has mNativeAccessRules.
Carrier privilege status should
be granted to the caller APK only if it's certificate matches with one
of mCarrierConfigAccessRules.
Replaced SubscriptionManager#canManageSubscription with
PhoneInterfaceManager#hasCarrierConfigAccess which returns true only if
caller APK certificates matches with one of mCarrierConfigAccessRules of
the given subscription.
Bug: 226593252
Test: Manual Testing as explained in b/226593252#comment51
atest CtsTelephonyTestCases
Flashed build on raven-userdebug and performed basic
funtionality tests
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e46bce078fef9dba500a7411e843f7f00a7a33c2)
Merged-In: I662064529d2a9348f395fe3b541366de8bc2fe7d
Change-Id: I662064529d2a9348f395fe3b541366de8bc2fe7d
---
telephony/java/android/telephony/SubscriptionInfo.java | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 471edad80bc6..eb7c00a9fc78 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
@@ -658,6 +659,15 @@ public class SubscriptionInfo implements Parcelable {
return merged.isEmpty() ? null : merged;
}
+ /**
+ * @hide
+ * @return mCarrierConfigAccessRules associated with this subscription.
+ */
+ public @NonNull List<UiccAccessRule> getCarrierConfigAccessRules() {
+ return mCarrierConfigAccessRules == null ? Collections.emptyList() :
+ Arrays.asList(mCarrierConfigAccessRules);
+ }
+
/**
* Returns the card string if the calling app has been granted the READ_PRIVILEGED_PHONE_STATE
* permission, has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or

View File

@ -0,0 +1,109 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= <matiashe@google.com>
Date: Thu, 15 Jun 2023 18:31:34 +0200
Subject: [PATCH] Forbid granting access to NLSes with too-long component names
This makes the limitation, which was previously only checked on the Settings UI, enforced everywhere.
Fixes: 260570119
Fixes: 286043036
Test: atest + manually
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc71156a29427c8b228129f5b1368392f297835b)
Merged-In: I4c25d80978cb37a8fa1531f5045259d25ac64692
Change-Id: I4c25d80978cb37a8fa1531f5045259d25ac64692
---
.../java/android/app/NotificationManager.java | 6 ++++
.../NotificationManagerService.java | 5 ++++
.../android/server/vr/VrManagerService.java | 6 +++-
.../NotificationManagerServiceTest.java | 28 +++++++++++++++++++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index b81a86331ca0..3f0fff4f40dd 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -378,6 +378,12 @@ public class NotificationManager {
*/
public static final int IMPORTANCE_MAX = 5;
+ /**
+ * Maximum length of the component name of a registered NotificationListenerService.
+ * @hide
+ */
+ public static int MAX_SERVICE_COMPONENT_NAME_LENGTH = 500;
+
@UnsupportedAppUsage
private static INotificationManager sService;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7ae80d927aaa..d056eac37039 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4161,6 +4161,11 @@ public class NotificationManagerService extends SystemService {
boolean granted) {
Preconditions.checkNotNull(listener);
checkCallerIsSystemOrShell();
+ if (granted && listener.flattenToString().length()
+ > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
+ throw new IllegalArgumentException(
+ "Component name too long: " + listener.flattenToString());
+ }
final long identity = Binder.clearCallingIdentity();
try {
if (mAllowedManagedServicePackages.test(
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 45689ce73c9f..7eeba02542e4 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -1045,7 +1045,11 @@ public class VrManagerService extends SystemService
for (ComponentName c : possibleServices) {
if (Objects.equals(c.getPackageName(), pkg)) {
- nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
+ try {
+ nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
+ } catch (Exception e) {
+ Slog.w(TAG, "Could not grant NLS access to package " + pkg, e);
+ }
}
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index f3a9ef1eb63e..34550bb52a52 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2403,6 +2403,34 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
any(), anyInt(), anyBoolean(), anyBoolean());
}
+ @Test
+ public void testSetListenerAccessForUser_grantWithNameTooLong_throws() throws Exception {
+ UserHandle user = UserHandle.of(mContext.getUserId() + 10);
+ ComponentName c = new ComponentName("com.example.package",
+ com.google.common.base.Strings.repeat("Blah", 150));
+
+ try {
+ mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(),
+ /* enabled= */ true);
+ fail("Should've thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Good!
+ }
+ }
+
+ @Test
+ public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception {
+ UserHandle user = UserHandle.of(mContext.getUserId() + 10);
+ ComponentName c = new ComponentName("com.example.package",
+ com.google.common.base.Strings.repeat("Blah", 150));
+
+ mBinderService.setNotificationListenerAccessGrantedForUser(
+ c, user.getIdentifier(), /* enabled= */ false);
+
+ verify(mListeners).setPackageOrComponentEnabled(
+ c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false);
+ }
+
@Test
public void testSetAssistantAccessForUser() throws Exception {
UserHandle user = UserHandle.of(10);

Some files were not shown because too many files have changed in this diff Show More