Switch to upstream ASB patchsets

Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
Tad 2023-10-08 22:06:56 -04:00
parent 7b54b4459c
commit bf565cd578
No known key found for this signature in database
GPG Key ID: B286E9F57A07424B
120 changed files with 21 additions and 16243 deletions

View File

@ -1,359 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Vincent Rabaud <vrabaud@google.com>
Date: Thu, 7 Sep 2023 21:16:03 +0200
Subject: [PATCH] Fix OOB write in BuildHuffmanTable.
First, BuildHuffmanTable is called to check if the data is valid.
If it is and the table is not big enough, more memory is allocated.
This will make sure that valid (but unoptimized because of unbalanced
codes) streams are still decodable.
Bug: chromium:1479274
Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
(cherry picked from commit 902bc9190331343b2017211debcec8d2ab87e17a)
(cherry picked from commit 2af26267cdfcb63a88e5c74a85927a12d6ca1d76)
---
src/dec/vp8l_dec.c | 46 ++++++++++---------
src/dec/vp8li_dec.h | 2 +-
src/utils/huffman_utils.c | 97 +++++++++++++++++++++++++++++++--------
src/utils/huffman_utils.h | 27 +++++++++--
4 files changed, 129 insertions(+), 43 deletions(-)
diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
index 93615d4e..0d38314d 100644
--- a/src/dec/vp8l_dec.c
+++ b/src/dec/vp8l_dec.c
@@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
int symbol;
int max_symbol;
int prev_code_len = DEFAULT_CODE_LENGTH;
- HuffmanCode table[1 << LENGTHS_TABLE_BITS];
+ HuffmanTables tables;
- if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
- code_length_code_lengths,
- NUM_CODE_LENGTH_CODES)) {
+ if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
+ !VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
+ code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
goto End;
}
@@ -277,7 +277,7 @@ static int ReadHuffmanCodeLengths(
int code_len;
if (max_symbol-- == 0) break;
VP8LFillBitWindow(br);
- p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
+ p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
code_len = p->value;
if (code_len < kCodeLengthLiterals) {
@@ -300,6 +300,7 @@ static int ReadHuffmanCodeLengths(
ok = 1;
End:
+ VP8LHuffmanTablesDeallocate(&tables);
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return ok;
}
@@ -307,7 +308,8 @@ static int ReadHuffmanCodeLengths(
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
// tree.
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
- int* const code_lengths, HuffmanCode* const table) {
+ int* const code_lengths,
+ HuffmanTables* const table) {
int ok = 0;
int size = 0;
VP8LBitReader* const br = &dec->br_;
@@ -362,8 +364,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
- HuffmanCode* huffman_tables = NULL;
- HuffmanCode* huffman_table = NULL;
+ HuffmanTables* huffman_tables = &hdr->huffman_tables_;
int num_htree_groups = 1;
int num_htree_groups_max = 1;
int max_alphabet_size = 0;
@@ -372,6 +373,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int* mapping = NULL;
int ok = 0;
+ // Check the table has been 0 initialized (through InitMetadata).
+ assert(huffman_tables->root.start == NULL);
+ assert(huffman_tables->curr_segment == NULL);
+
if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
const int huffman_precision = VP8LReadBits(br, 3) + 2;
@@ -434,16 +439,15 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
sizeof(*code_lengths));
- huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
- sizeof(*huffman_tables));
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
- if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
+ if (htree_groups == NULL || code_lengths == NULL ||
+ !VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
+ huffman_tables)) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
- huffman_table = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, just make sure the
// coefficients are valid but do not store them.
@@ -468,19 +472,20 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
- htrees[j] = huffman_table;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
+ size =
+ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
+ htrees[j] = huffman_tables->curr_segment->curr_table;
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
- is_trivial_literal = (huffman_table->bits == 0);
+ is_trivial_literal = (htrees[j]->bits == 0);
}
- total_size += huffman_table->bits;
- huffman_table += size;
+ total_size += htrees[j]->bits;
+ huffman_tables->curr_segment->curr_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
@@ -515,14 +520,13 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
- hdr->huffman_tables_ = huffman_tables;
Error:
WebPSafeFree(code_lengths);
WebPSafeFree(mapping);
if (!ok) {
WebPSafeFree(huffman_image);
- WebPSafeFree(huffman_tables);
+ VP8LHuffmanTablesDeallocate(huffman_tables);
VP8LHtreeGroupsFree(htree_groups);
}
return ok;
@@ -1354,7 +1358,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
assert(hdr != NULL);
WebPSafeFree(hdr->huffman_image_);
- WebPSafeFree(hdr->huffman_tables_);
+ VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
VP8LHtreeGroupsFree(hdr->htree_groups_);
VP8LColorCacheClear(&hdr->color_cache_);
VP8LColorCacheClear(&hdr->saved_color_cache_);
@@ -1670,7 +1674,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
// Sanity checks.
if (dec == NULL) return 0;
- assert(dec->hdr_.huffman_tables_ != NULL);
+ assert(dec->hdr_.huffman_tables_.root.start != NULL);
assert(dec->hdr_.htree_groups_ != NULL);
assert(dec->hdr_.num_htree_groups_ > 0);
diff --git a/src/dec/vp8li_dec.h b/src/dec/vp8li_dec.h
index 72b2e861..32540a4b 100644
--- a/src/dec/vp8li_dec.h
+++ b/src/dec/vp8li_dec.h
@@ -51,7 +51,7 @@ typedef struct {
uint32_t* huffman_image_;
int num_htree_groups_;
HTreeGroup* htree_groups_;
- HuffmanCode* huffman_tables_;
+ HuffmanTables huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
diff --git a/src/utils/huffman_utils.c b/src/utils/huffman_utils.c
index 0cba0fbb..9efd6283 100644
--- a/src/utils/huffman_utils.c
+++ b/src/utils/huffman_utils.c
@@ -177,21 +177,24 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
if (num_open < 0) {
return 0;
}
- if (root_table == NULL) continue;
for (; count[len] > 0; --count[len]) {
HuffmanCode code;
if ((key & mask) != low) {
- table += table_size;
+ if (root_table != NULL) table += table_size;
table_bits = NextTableBitSize(count, len, root_bits);
table_size = 1 << table_bits;
total_size += table_size;
low = key & mask;
- root_table[low].bits = (uint8_t)(table_bits + root_bits);
- root_table[low].value = (uint16_t)((table - root_table) - low);
+ if (root_table != NULL) {
+ root_table[low].bits = (uint8_t)(table_bits + root_bits);
+ root_table[low].value = (uint16_t)((table - root_table) - low);
+ }
+ }
+ if (root_table != NULL) {
+ code.bits = (uint8_t)(len - root_bits);
+ code.value = (uint16_t)sorted[symbol++];
+ ReplicateValue(&table[key >> root_bits], step, table_size, code);
}
- code.bits = (uint8_t)(len - root_bits);
- code.value = (uint16_t)sorted[symbol++];
- ReplicateValue(&table[key >> root_bits], step, table_size, code);
key = GetNextKey(key, len);
}
}
@@ -211,25 +214,83 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
// Cut-off value for switching between heap and stack allocation.
#define SORTED_SIZE_CUTOFF 512
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size) {
- int total_size;
+ const int total_size =
+ BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL);
assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
- if (root_table == NULL) {
- total_size = BuildHuffmanTable(NULL, root_bits,
- code_lengths, code_lengths_size, NULL);
- } else if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
+ if (total_size == 0 || root_table == NULL) return total_size;
+
+ if (root_table->curr_segment->curr_table + total_size >=
+ root_table->curr_segment->start + root_table->curr_segment->size) {
+ // If 'root_table' does not have enough memory, allocate a new segment.
+ // The available part of root_table->curr_segment is left unused because we
+ // need a contiguous buffer.
+ const int segment_size = root_table->curr_segment->size;
+ struct HuffmanTablesSegment* next =
+ (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next));
+ if (next == NULL) return 0;
+ // Fill the new segment.
+ // We need at least 'total_size' but if that value is small, it is better to
+ // allocate a big chunk to prevent more allocations later. 'segment_size' is
+ // therefore chosen (any other arbitrary value could be chosen).
+ next->size = total_size > segment_size ? total_size : segment_size;
+ next->start =
+ (HuffmanCode*)WebPSafeMalloc(next->size, sizeof(*next->start));
+ if (next->start == NULL) {
+ WebPSafeFree(next);
+ return 0;
+ }
+ next->curr_table = next->start;
+ next->next = NULL;
+ // Point to the new segment.
+ root_table->curr_segment->next = next;
+ root_table->curr_segment = next;
+ }
+ if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
// use local stack-allocated array.
uint16_t sorted[SORTED_SIZE_CUTOFF];
- total_size = BuildHuffmanTable(root_table, root_bits,
- code_lengths, code_lengths_size, sorted);
- } else { // rare case. Use heap allocation.
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
+ } else { // rare case. Use heap allocation.
uint16_t* const sorted =
(uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
if (sorted == NULL) return 0;
- total_size = BuildHuffmanTable(root_table, root_bits,
- code_lengths, code_lengths_size, sorted);
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
WebPSafeFree(sorted);
}
return total_size;
}
+
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) {
+ // Have 'segment' point to the first segment for now, 'root'.
+ HuffmanTablesSegment* const root = &huffman_tables->root;
+ huffman_tables->curr_segment = root;
+ // Allocate root.
+ root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start));
+ if (root->start == NULL) return 0;
+ root->curr_table = root->start;
+ root->next = NULL;
+ root->size = size;
+ return 1;
+}
+
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) {
+ HuffmanTablesSegment *current, *next;
+ if (huffman_tables == NULL) return;
+ // Free the root node.
+ current = &huffman_tables->root;
+ next = current->next;
+ WebPSafeFree(current->start);
+ current->start = NULL;
+ current->next = NULL;
+ current = next;
+ // Free the following nodes.
+ while (current != NULL) {
+ next = current->next;
+ WebPSafeFree(current->start);
+ WebPSafeFree(current);
+ current = next;
+ }
+}
diff --git a/src/utils/huffman_utils.h b/src/utils/huffman_utils.h
index 13b7ad1a..98415c53 100644
--- a/src/utils/huffman_utils.h
+++ b/src/utils/huffman_utils.h
@@ -43,6 +43,29 @@ typedef struct {
// or non-literal symbol otherwise
} HuffmanCode32;
+// Contiguous memory segment of HuffmanCodes.
+typedef struct HuffmanTablesSegment {
+ HuffmanCode* start;
+ // Pointer to where we are writing into the segment. Starts at 'start' and
+ // cannot go beyond 'start' + 'size'.
+ HuffmanCode* curr_table;
+ // Pointer to the next segment in the chain.
+ struct HuffmanTablesSegment* next;
+ int size;
+} HuffmanTablesSegment;
+
+// Chained memory segments of HuffmanCodes.
+typedef struct HuffmanTables {
+ HuffmanTablesSegment root;
+ // Currently processed segment. At first, this is 'root'.
+ HuffmanTablesSegment* curr_segment;
+} HuffmanTables;
+
+// Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on
+// memory allocation error, 1 otherwise.
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables);
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables);
+
#define HUFFMAN_PACKED_BITS 6
#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS)
@@ -78,9 +101,7 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
// the huffman table.
// Returns built table size or 0 in case of error (invalid tree or
// memory error).
-// If root_table is NULL, it returns 0 if a lookup cannot be built, something
-// > 0 otherwise (but not the table size).
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size);
#ifdef __cplusplus

View File

@ -1,38 +0,0 @@
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 003a547..c363880 100644
--- a/libSBRdec/src/lpp_tran.h
+++ b/libSBRdec/src/lpp_tran.h
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -175,7 +175,7 @@ typedef struct {
UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/
UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different inverse filtering levels */
- PATCH_PARAM patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */
+ PATCH_PARAM patchParam[MAX_NUM_PATCHES + 1]; /*!< new parameter set for patching */
WHITENING_FACTORS whFactors; /*!< the pole moving factors for certain whitening levels as indicated
in the bitstream depending on the crossover frequency */
UCHAR overlap; /*!< Overlap size */

View File

@ -1,51 +0,0 @@
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
Change-Id: Ia584ab1f2633a84e5896c09113513c582ce95dad
---
src/base/ftobjs.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 9006b598b..4e1d32aa0 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2118,6 +2118,14 @@
FT_Module* cur;
FT_Module* limit;
+ /* only use lower 31 bits together with sign bit */
+ if ( face_index > 0 )
+ face_index &= 0x7FFFFFFFL;
+ else
+ {
+ face_index &= 0x7FFFFFFFL;
+ face_index = -face_index;
+ }
/* test for valid `library' delayed to `FT_Stream_New' */
@@ -2953,6 +2961,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

@ -1,38 +0,0 @@
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 003a547..c363880 100644
--- a/libSBRdec/src/lpp_tran.h
+++ b/libSBRdec/src/lpp_tran.h
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -175,7 +175,7 @@ typedef struct {
UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/
UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different inverse filtering levels */
- PATCH_PARAM patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */
+ PATCH_PARAM patchParam[MAX_NUM_PATCHES + 1]; /*!< new parameter set for patching */
WHITENING_FACTORS whFactors; /*!< the pole moving factors for certain whitening levels as indicated
in the bitstream depending on the crossover frequency */
UCHAR overlap; /*!< Overlap size */

View File

@ -1,50 +0,0 @@
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 8d07e35ae..fda7e21de 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2345,6 +2345,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 )
@@ -3200,6 +3209,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

@ -1,367 +0,0 @@
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 | 8 ++-
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 | 68 +++++++++++--------
src/truetype/ttobjs.h | 6 +-
10 files changed, 98 insertions(+), 55 deletions(-)
diff --git a/include/freetype/internal/services/svmetric.h b/include/freetype/internal/services/svmetric.h
index abaacddbb..2e8a2e6b3 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;
};
@@ -103,7 +107,8 @@ FT_BEGIN_HEADER
tsb_adjust_, \
bsb_adjust_, \
vorg_adjust_, \
- metrics_adjust_ ) \
+ metrics_adjust_, \
+ size_reset_ ) \
static const FT_Service_MetricsVariationsRec class_ = \
{ \
hadvance_adjust_, \
@@ -114,6 +119,7 @@ FT_BEGIN_HEADER
bsb_adjust_, \
vorg_adjust_, \
- metrics_adjust_ \
+ metrics_adjust_, \
+ size_reset_ \
};
#else /* FT_CONFIG_OPTION_PIC */
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 10dd336a8..422a680de 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1437,8 +1437,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 */
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -933,7 +933,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 );
@@ -943,7 +944,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 ) );
@@ -962,7 +964,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
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -710,8 +710,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;
--- 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" ));
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -229,7 +229,7 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_Service_MetricsVariations var =
- (FT_Service_MetricsVariations)face->var;
+ (FT_Service_MetricsVariations)face->tt_var;
#endif
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -304,7 +304,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
{
@@ -356,7 +356,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 */
@@ -516,7 +516,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 */
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -1283,15 +1283,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;
}
@@ -1352,6 +1351,9 @@
/* adjust all derived values */
{
+ FT_Service_MetricsVariations var =
+ (FT_Service_MetricsVariations)face->face_var;
+
FT_Face root = &face->root;
@@ -1378,11 +1380,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 );
}
}
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -1234,37 +1234,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;
@@ -1291,12 +1283,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 )
{
--- 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

@ -1,32 +0,0 @@
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

@ -1,145 +0,0 @@
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 09339743db5c..43d18df3a10d 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
@@ -42,10 +42,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);
@@ -68,15 +110,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

@ -1,84 +0,0 @@
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 533d72590f0a..d5f6ebe8c2e9 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();
}

View File

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aaron Liu <aaronjli@google.com>
Date: Tue, 28 Mar 2023 13:15:04 -0700
Subject: [PATCH] DO NOT MERGE Dismiss keyguard when simpin auth'd and...
security method is none. This is mostly to fix the case where we auth
sim pin in the set up wizard and it goes straight to keyguard instead of
the setup wizard activity.
This works with the prevent bypass keyguard flag because the device
should be noe secure in this case.
Fixes: 222446076
Test: turn locked sim on, which opens the sim pin screen. Auth the
screen and observe that keyguard is not shown.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:48fa9bef3451e4a358c941af5b230f99881c5cb6)
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
Change-Id: If4360dd6ae2e5f79b43eaf1a29687ac9cc4b6101
---
.../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 6a71cf84759c..bb205956e932 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -351,7 +351,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;
} else {

View File

@ -1,99 +0,0 @@
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 ea476b0abf33..cddad1798219 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -214,6 +214,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,
@@ -380,8 +386,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.
@@ -463,6 +468,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.
*
@@ -1851,7 +1864,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 fcdadaccd2ac..464f563640c1 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.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
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

@ -1,128 +0,0 @@
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 | 65 +++++++++++++++++++
2 files changed, 71 insertions(+)
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 4865dab6056a..10053dddb0fb 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -543,6 +543,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 70cf097f42a3..7d2e07ecbd71 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -19,6 +19,10 @@ package android.widget;
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.PendingIntent;
import android.content.Context;
@@ -26,6 +30,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;
@@ -46,6 +52,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.
@@ -444,4 +451,62 @@ public class RemoteViewsTest {
}
return found[0];
}
+
+
+ @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

@ -1,109 +0,0 @@
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 83630f4c3693..51411c9e208e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3615,6 +3615,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 0aafab66dabd..d23501a86b79 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2092,7 +2092,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 f522b20f7ccd..44761a523abb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6810,8 +6810,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);
@@ -6826,7 +6838,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;
}
@@ -6851,6 +6863,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

@ -1,60 +0,0 @@
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 | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 21bc17172b1f..d8e7d0199615 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,6 +17,7 @@
package android.app;
import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
+import static android.graphics.drawable.Icon.TYPE_URI;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
@@ -2329,6 +2330,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 /*|| iconType == TYPE_URI_ADAPTIVE_BITMAP*/) {
+ 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
@@ -2344,7 +2353,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));
visitor.accept(extras.getParcelable(EXTRA_BACKGROUND_IMAGE_URI));
}

View File

@ -1,51 +0,0 @@
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 bac481c8e478..f0d389c15228 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -586,6 +586,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() {
@@ -1341,7 +1348,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");
// note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes

View File

@ -1,242 +0,0 @@
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 | 91 ++++++++++++++++++-
2 files changed, 90 insertions(+), 4 deletions(-)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 485ce78c3320..28b7ccb7b946 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8100,7 +8100,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 d7539e11bea9..2fd54b4981af 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -250,6 +250,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;
@@ -260,6 +261,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
+import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -325,6 +327,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
@@ -8284,6 +8295,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,
@@ -8486,6 +8503,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();
@@ -8668,6 +8689,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int callingUserId = mInjector.userHandleGetCallingUserId();
if (packageList != null) {
+ for (String pkg : (List<String>) packageList) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
// InputMethodManager fetches input methods for current user.
// So this can only be set when calling user is the current user
// or parent is current user in case of managed profiles.
@@ -9608,6 +9633,7 @@ 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);
@@ -9871,6 +9897,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);
@@ -11249,6 +11278,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()) {
@@ -11280,6 +11312,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,
@@ -11408,6 +11442,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);
@@ -11572,9 +11608,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);
@@ -12740,6 +12775,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);
@@ -13194,4 +13232,51 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static String getManagedProvisioningPackage(Context context) {
return context.getResources().getString(R.string.config_managed_provisioning_package);
}
+
+ /**
+ * 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

@ -1,70 +0,0 @@
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 10053dddb0fb..b36d27fc3b3b 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1672,6 +1672,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 7d2e07ecbd71..1123988e9512 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -474,6 +474,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

@ -1,29 +0,0 @@
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 ++++
1 file changed, 4 insertions(+)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index d8e7d0199615..b2daecc659cc 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2346,6 +2346,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);

View File

@ -1,125 +0,0 @@
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 | 54 +++++++++++++++----
1 file changed, 45 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 442354bbb6b9..01d09178f7dd 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -16,7 +16,11 @@
package com.android.server.media;
+import android.app.ActivityManager;
+import android.app.IActivityManager;
import android.app.PendingIntent;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
@@ -49,6 +53,7 @@ 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;
@@ -64,6 +69,10 @@ import java.util.ArrayList;
*/
public class MediaSessionRecord implements IBinder.DeathRecipient {
private static final String TAG = "MediaSessionRecord";
+ private static final String[] ART_URIS = new String[] {
+ MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
+ MediaMetadata.METADATA_KEY_ART_URI,
+ MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI};
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
/**
@@ -83,6 +92,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private final SessionStub mSession;
private final SessionCb mSessionCb;
private final MediaSessionService mService;
+ final IActivityManager mAm;
private final Context mContext;
private final Object mLock = new Object();
@@ -133,6 +143,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();
+ mAm = ActivityManager.getService();
}
/**
@@ -792,19 +803,44 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public void setMetadata(MediaMetadata metadata) {
synchronized (mLock) {
- MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata)
- .build();
- // This is to guarantee that the underlying bundle is unparceled
- // before we set it to prevent concurrent reads from throwing an
- // exception
- if (temp != null) {
- temp.size();
- }
- mMetadata = temp;
+ mMetadata = sanitizeMediaMetadata(metadata);
}
mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
}
+
+ private MediaMetadata sanitizeMediaMetadata(MediaMetadata metadata) {
+ if (metadata == null) {
+ return null;
+ }
+ MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder(metadata);
+ for (String key: ART_URIS) {
+ String uriString = metadata.getString(key);
+ if (TextUtils.isEmpty(uriString)) {
+ continue;
+ }
+ Uri uri = Uri.parse(uriString);
+ if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ continue;
+ }
+ try {
+ mAm.checkGrantUriPermission(getUid(),
+ getPackageName(),
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ ContentProvider.getUserIdFromUri(uri, getUserId()));
+ } catch (RemoteException | SecurityException e) {
+ metadataBuilder.putString(key, null);
+ }
+ }
+ MediaMetadata sanitizedMetadata = metadataBuilder.build();
+ // sanitizedMetadata.size() guarantees that the underlying bundle is unparceled
+ // before we set it to prevent concurrent reads from throwing an
+ // exception
+ sanitizedMetadata.size();
+ return sanitizedMetadata;
+ }
+
@Override
public void setPlaybackState(PlaybackState state) {
int oldState = mPlaybackState == null

View File

@ -1,55 +0,0 @@
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 f0d389c15228..820c7eac715a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -935,9 +935,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()
@@ -949,8 +949,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
@@ -1792,7 +1792,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

@ -1,126 +0,0 @@
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
---
.../java/android/telecom/StatusHints.java | 53 ++++++++++++++++++-
1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java
index 453f408bedba..c75bd2781f9f 100644
--- a/telecomm/java/android/telecom/StatusHints.java
+++ b/telecomm/java/android/telecom/StatusHints.java
@@ -16,14 +16,19 @@
package android.telecom;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.util.Objects;
@@ -33,7 +38,7 @@ import java.util.Objects;
public final class StatusHints implements Parcelable {
private final CharSequence mLabel;
- private final Icon mIcon;
+ private Icon mIcon;
private final Bundle mExtras;
/**
@@ -48,10 +53,30 @@ public final class StatusHints implements Parcelable {
public StatusHints(CharSequence label, Icon icon, Bundle extras) {
mLabel = label;
- mIcon = icon;
+ mIcon = validateAccountIconUserBoundary(icon, Binder.getCallingUserHandle());
mExtras = extras;
}
+ /**
+ * @param icon
+ * @hide
+ */
+ @VisibleForTesting
+ public StatusHints(@Nullable Icon icon) {
+ mLabel = null;
+ mExtras = null;
+ mIcon = icon;
+ }
+
+ /**
+ *
+ * @param icon
+ * @hide
+ */
+ public void setIcon(@Nullable Icon icon) {
+ mIcon = icon;
+ }
+
/**
* @return A package used to load the icon.
*
@@ -112,6 +137,30 @@ public final class StatusHints implements Parcelable {
return 0;
}
+ /**
+ * Validates the StatusHints image icon to see if it's not in the calling user space.
+ * Invalidates the icon if so, otherwise returns back the original icon.
+ *
+ * @param icon
+ * @return icon (validated)
+ * @hide
+ */
+ public static Icon validateAccountIconUserBoundary(Icon icon, UserHandle callingUserHandle) {
+ // Refer to Icon#getUriString for context. The URI string is invalid for icons of
+ // incompatible types.
+ if (icon != null && (icon.getType() == Icon.TYPE_URI
+ /*|| icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP*/)) {
+ String encodedUser = icon.getUri().getEncodedUserInfo();
+ // If there is no encoded user, the URI is calling into the calling user space
+ if (encodedUser != null) {
+ int userId = Integer.parseInt(encodedUser);
+ // Do not try to save the icon if the user id isn't in the calling user space.
+ if (userId != callingUserHandle.getIdentifier()) return null;
+ }
+ }
+ return icon;
+ }
+
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeCharSequence(mLabel);

View File

@ -1,109 +0,0 @@
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 f6dc5d15f385..32f40a805502 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -308,6 +308,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;
+
private static INotificationManager sService;
/** @hide */
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0ac51524a648..ca0ec012fb60 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3540,6 +3540,11 @@ public class NotificationManagerService extends SystemService {
boolean granted) throws RemoteException {
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(listener.getPackageName())) {
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index faa197e984cf..87f66de5c704 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -1055,7 +1055,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 9592e1905b54..e073e6767da6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2021,6 +2021,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);

View File

@ -1,28 +0,0 @@
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 36732273ab6f..ec15113c2c78 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -4827,6 +4827,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

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Devin Moore <devinmoore@google.com>
Date: Tue, 25 Apr 2023 00:17:13 +0000
Subject: [PATCH] Allow sensors list to be empty
Test: atest VtsHalSensorManagerV1_0TargetTest
Bug: 278013275
Bug: 269014004
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:49600b10aa5675d4e7e985203d69f252ead13e45)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7057a9f08d98bfec8ffbabcf00f2885d3909c6c9)
Merged-In: I091f57de9570b0ace3a8da76f16fe0e83f0aa624
Change-Id: I091f57de9570b0ace3a8da76f16fe0e83f0aa624
---
libs/sensor/SensorManager.cpp | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index d7210b10e0..35802db95c 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -172,11 +172,8 @@ status_t SensorManager::assertStateLocked() {
mSensors = mSensorServer->getSensorList(mOpPackageName);
size_t count = mSensors.size();
- if (count == 0) {
- ALOGE("Failed to get Sensor list");
- mSensorServer.clear();
- return UNKNOWN_ERROR;
- }
+ // If count is 0, mSensorList will be non-null. This is old
+ // existing behavior and callers expect this.
mSensorList =
static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
LOG_ALWAYS_FATAL_IF(mSensorList == NULL, "mSensorList NULL");

View File

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Thu, 1 Jun 2023 13:44:28 -0700
Subject: [PATCH] Ensure that SecureNFC setting cannot be bypassed
Bug: 268038643
Test: ctsverifier
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d6d8f79fd8d605b3cb460895a8e3a11bcf0c22b0)
Merged-In: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
Change-Id: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
---
src/com/android/nfc/NfcService.java | 6 ++++++
src/com/android/nfc/cardemulation/HostEmulationManager.java | 5 +++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 059d1826..a92e0456 100644
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -830,6 +830,12 @@ public class NfcService implements DeviceHostListener {
}
}
+ public boolean isSecureNfcEnabled() {
+ synchronized (NfcService.this) {
+ return mIsSecureNfcEnabled;
+ }
+ }
+
final class NfcAdapterService extends INfcAdapter.Stub {
/**
* An interface for vendor specific extensions
diff --git a/src/com/android/nfc/cardemulation/HostEmulationManager.java b/src/com/android/nfc/cardemulation/HostEmulationManager.java
index 0a5ce363..739b3ffd 100644
--- a/src/com/android/nfc/cardemulation/HostEmulationManager.java
+++ b/src/com/android/nfc/cardemulation/HostEmulationManager.java
@@ -169,8 +169,9 @@ public class HostEmulationManager {
// Resolve to default
// Check if resolvedService requires unlock
ApduServiceInfo defaultServiceInfo = resolveInfo.defaultService;
- if (defaultServiceInfo.requiresUnlock() &&
- mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
+ if ((defaultServiceInfo.requiresUnlock()
+ || NfcService.getInstance().isSecureNfcEnabled())
+ && mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
// Just ignore all future APDUs until next tap
mState = STATE_W4_DEACTIVATE;
launchTapAgain(resolveInfo.defaultService, resolveInfo.category);

View File

@ -1,209 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Taran Singh <tarandeep@google.com>
Date: Fri, 19 May 2023 23:17:47 +0000
Subject: [PATCH] DO NOT MERGE: Prevent non-system IME from becoming device
admin
Currently selected IME can inject KeyEvent on DeviceAdminAdd screen to
activate itself as device admin and cause various DoS attacks.
This CL ensures KeyEvent on "Activate" button can only come from system
apps.
Bug: 280793427
Test: atest DeviceAdminActivationTest
(cherry picked from commit 70a501d02e0a6aefd874767a15378ba998759373)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0ee3b96e59f3e5699c919af3642130fb33cd263b)
Merged-In: I6470d1684d707f4b1e86f8b456be0b4e0af5f188
Change-Id: I6470d1684d707f4b1e86f8b456be0b4e0af5f188
---
src/com/android/settings/DeviceAdminAdd.java | 120 ++++++++++---------
1 file changed, 64 insertions(+), 56 deletions(-)
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index fb21deb661..10d170ab6b 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -49,6 +49,8 @@ import android.text.TextUtils.TruncateAt;
import android.util.EventLog;
import android.util.Log;
import android.view.Display;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -133,7 +135,7 @@ public class DeviceAdminAdd extends Activity {
mAppOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
PackageManager packageManager = getPackageManager();
- if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
finish();
return;
@@ -143,7 +145,7 @@ public class DeviceAdminAdd extends Activity {
EXTRA_CALLED_FROM_SUPPORT_DIALOG, false);
String action = getIntent().getAction();
- ComponentName who = (ComponentName)getIntent().getParcelableExtra(
+ ComponentName who = (ComponentName) getIntent().getParcelableExtra(
DevicePolicyManager.EXTRA_DEVICE_ADMIN);
if (who == null) {
String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
@@ -201,7 +203,7 @@ public class DeviceAdminAdd extends Activity {
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
int count = avail == null ? 0 : avail.size();
boolean found = false;
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
ResolveInfo ri = avail.get(i);
if (ai.packageName.equals(ri.activityInfo.packageName)
&& ai.name.equals(ri.activityInfo.name)) {
@@ -284,12 +286,12 @@ public class DeviceAdminAdd extends Activity {
setContentView(R.layout.device_admin_add);
- mAdminIcon = (ImageView)findViewById(R.id.admin_icon);
- mAdminName = (TextView)findViewById(R.id.admin_name);
- mAdminDescription = (TextView)findViewById(R.id.admin_description);
+ mAdminIcon = (ImageView) findViewById(R.id.admin_icon);
+ mAdminName = (TextView) findViewById(R.id.admin_name);
+ mAdminDescription = (TextView) findViewById(R.id.admin_description);
mProfileOwnerWarning = (TextView) findViewById(R.id.profile_owner_warning);
- mAddMsg = (TextView)findViewById(R.id.add_msg);
+ mAddMsg = (TextView) findViewById(R.id.add_msg);
mAddMsgExpander = (ImageView) findViewById(R.id.add_msg_expander);
final View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
@@ -312,7 +314,7 @@ public class DeviceAdminAdd extends Activity {
mAddMsgExpander.setVisibility(hideMsgExpander ? View.GONE : View.VISIBLE);
if (hideMsgExpander) {
mAddMsg.setOnClickListener(null);
- ((View)mAddMsgExpander.getParent()).invalidate();
+ ((View) mAddMsgExpander.getParent()).invalidate();
}
mAddMsg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
@@ -330,7 +332,7 @@ public class DeviceAdminAdd extends Activity {
mCancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER,
- mDeviceAdmin.getActivityInfo().applicationInfo.uid);
+ mDeviceAdmin.getActivityInfo().applicationInfo.uid);
finish();
}
});
@@ -350,58 +352,64 @@ public class DeviceAdminAdd extends Activity {
final View restrictedAction = findViewById(R.id.restricted_action);
restrictedAction.setFilterTouchesWhenObscured(true);
- restrictedAction.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (!mActionButton.isEnabled()) {
- showPolicyTransparencyDialogIfRequired();
- return;
- }
- if (mAdding) {
- addAndFinish();
- } else if (isManagedProfile(mDeviceAdmin)
- && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
- final int userId = UserHandle.myUserId();
- UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- UserManager um = UserManager.get(DeviceAdminAdd.this);
- um.removeUser(userId);
- finish();
- }
+
+ final View.OnClickListener restrictedActionClickListener = v -> {
+ if (!mActionButton.isEnabled()) {
+ showPolicyTransparencyDialogIfRequired();
+ return;
+ }
+ if (mAdding) {
+ addAndFinish();
+ } else if (isManagedProfile(mDeviceAdmin)
+ && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
+ final int userId = UserHandle.myUserId();
+ UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ UserManager um = UserManager.get(DeviceAdminAdd.this);
+ um.removeUser(userId);
+ finish();
}
- ).show();
- } else if (mUninstalling) {
- mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
- finish();
- } else if (!mWaitingForRemoveMsg) {
- try {
- // Don't allow the admin to put a dialog up in front
- // of us while we interact with the user.
- ActivityManager.getService().stopAppSwitches();
- } catch (RemoteException e) {
- }
- mWaitingForRemoveMsg = true;
- mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
- new RemoteCallback(new RemoteCallback.OnResultListener() {
- @Override
- public void onResult(Bundle result) {
- CharSequence msg = result != null
- ? result.getCharSequence(
- DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
- : null;
- continueRemoveAction(msg);
- }
- }, mHandler));
- // Don't want to wait too long.
- getWindow().getDecorView().getHandler().postDelayed(new Runnable() {
- @Override public void run() {
- continueRemoveAction(null);
}
- }, 2*1000);
+ ).show();
+ } else if (mUninstalling) {
+ mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
+ finish();
+ } else if (!mWaitingForRemoveMsg) {
+ try {
+ // Don't allow the admin to put a dialog up in front
+ // of us while we interact with the user.
+ ActivityManager.getService().stopAppSwitches();
+ } catch (RemoteException e) {
}
+ mWaitingForRemoveMsg = true;
+ mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
+ new RemoteCallback(new RemoteCallback.OnResultListener() {
+ @Override
+ public void onResult(Bundle result) {
+ CharSequence msg = result != null
+ ? result.getCharSequence(
+ DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
+ : null;
+ continueRemoveAction(msg);
+ }
+ }, mHandler));
+ // Don't want to wait too long.
+ getWindow().getDecorView().getHandler().postDelayed(
+ () -> continueRemoveAction(null), 2 * 1000);
+ }
+ };
+ restrictedAction.setOnKeyListener((view, keyCode, keyEvent) -> {
+ if ((keyEvent.getFlags() & KeyEvent.FLAG_FROM_SYSTEM) == 0) {
+ Log.e(TAG, "Can not activate device-admin with KeyEvent from non-system app.");
+ // Consume event to suppress click.
+ return true;
}
+ // Fallback to view click handler.
+ return false;
});
+ restrictedAction.setOnClickListener(restrictedActionClickListener);
}
/**

View File

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pinyao Ting <pinyaoting@google.com>
Date: Thu, 1 Jun 2023 18:12:44 -0700
Subject: [PATCH] Fix permission issue in legacy shortcut
When building legacy shortcut, Launcher calls
PackageManager#resolveActivity to retrieve necessary permission to
launch the intent.
However, when the source app wraps an arbitrary intent within
Intent#createChooser, the existing logic will fail because launching
Chooser doesn't require additional permission.
This CL fixes the security vulnerability by performing the permission
check against the intent that is wrapped within.
Bug: 270152142
Test: manual
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c53818a16b4322a823497726ac7e7a44501b4442)
Merged-In: If35344c08975e35085c7c2b9b814a3c457a144b0
Change-Id: If35344c08975e35085c7c2b9b814a3c457a144b0
---
.../android/launcher3/util/PackageManagerHelper.java | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 0b3b632c02..4eac947fd0 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -116,6 +116,18 @@ public class PackageManagerHelper {
* any permissions
*/
public boolean hasPermissionForActivity(Intent intent, String srcPackage) {
+ // b/270152142
+ if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
+ final Bundle extras = intent.getExtras();
+ if (extras == null) {
+ return true;
+ }
+ // If given intent is ACTION_CHOOSER, verify srcPackage has permission over EXTRA_INTENT
+ intent = (Intent) extras.getParcelable(Intent.EXTRA_INTENT);
+ if (intent == null) {
+ return true;
+ }
+ }
ResolveInfo target = mPm.resolveActivity(intent, 0);
if (target == null) {
// Not a valid target

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aishwarya Mallampati <amallampati@google.com>
Date: Wed, 10 May 2023 21:54:43 +0000
Subject: [PATCH] Update file permissions using canonical path
Bug: 264880895
Bug: 264880689
Test: atest android.telephonyprovider.cts.MmsPartTest
atest CtsTelephonyTestCases
Sanity check - sending and receiving sms and mms manually
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6743638a096c32627f398efd2ea78f08b8a2db8c)
Merged-In: I8dd888ea31ec07c9f0de38eb8e8170d3ed255686
Change-Id: I8dd888ea31ec07c9f0de38eb8e8170d3ed255686
---
src/com/android/providers/telephony/MmsProvider.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index 6ba775ba..7546c246 100644
--- a/src/com/android/providers/telephony/MmsProvider.java
+++ b/src/com/android/providers/telephony/MmsProvider.java
@@ -819,15 +819,16 @@ public class MmsProvider extends ContentProvider {
String path = getContext().getDir(PARTS_DIR_NAME, 0).getPath() + '/' +
uri.getPathSegments().get(1);
try {
+ File canonicalFile = new File(path).getCanonicalFile();
String partsDirPath = getContext().getDir(PARTS_DIR_NAME, 0).getCanonicalPath();
- if (!new File(path).getCanonicalPath().startsWith(partsDirPath)) {
+ if (!canonicalFile.getPath().startsWith(partsDirPath + '/')) {
EventLog.writeEvent(0x534e4554, "240685104",
Binder.getCallingUid(), (TAG + " update: path " + path +
" does not start with " + partsDirPath));
return 0;
}
// Reset the file permission back to read for everyone but me.
- Os.chmod(path, 0644);
+ Os.chmod(canonicalFile.getPath(), 0644);
if (LOCAL_LOGV) {
Log.d(TAG, "MmsProvider.update chmod is successful for path: " + path);
}

View File

@ -1,706 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pranav Madapurmath <pmadapurmath@google.com>
Date: Thu, 25 May 2023 20:49:21 +0000
Subject: [PATCH] Resolve StatusHints image exploit across user.
Because of the INTERACT_ACROSS_USERS permission, an app that implements
a ConnectionService can upload an image icon belonging to another user
by setting it in the StatusHints. Validating the construction of the
StatusHints on the calling user would prevent a malicious app from
registering a connection service with the embedded image icon from a
different user.
From additional feedback, this CL also addresses potential
vulnerabilities in an app being able to directly invoke the binder for a
means to manipulate the contents of the bundle that are passed with it.
The targeted points of entry are in ConnectionServiceWrapper for the
following APIs: handleCreateConnectionComplete, setStatusHints,
addConferenceCall, and addExistingConnection.
Fixes: 280797684
Test: Manual (verified that original exploit is no longer an issue).
Test: Unit test for validating image in StatusHints constructor.
Test: Unit tests to address vulnerabilities via the binder.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:49d19dd265bee669b230efa29bf98c83650efea6)
Merged-In: Ie1f6a8866d31d5f1099dd0630cf8e9ee782d389c
Change-Id: Ie1f6a8866d31d5f1099dd0630cf8e9ee782d389c
---
.../telecom/ConnectionServiceWrapper.java | 32 ++++
.../server/telecom/tests/BasicCallTests.java | 165 +++++++++++++++++-
.../server/telecom/tests/CallExtrasTest.java | 6 +-
.../tests/ConnectionServiceFixture.java | 21 ++-
.../telecom/tests/TelecomSystemTest.java | 63 +++++--
.../server/telecom/tests/VideoCallTests.java | 16 +-
6 files changed, 264 insertions(+), 39 deletions(-)
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 6dd9a3a08..1b86842af 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -19,6 +19,7 @@ package com.android.server.telecom;
import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -73,10 +74,17 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection, Session.Info sessionInfo) {
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("handleCreateConnectionComplete %s", callId);
+ // Check status hints image for cross user access
+ if (connection.getStatusHints() != null) {
+ Icon icon = connection.getStatusHints().getIcon();
+ connection.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, callingUserHandle));
+ }
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection);
@@ -415,6 +423,15 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
public void addConferenceCall(String callId, ParcelableConference parcelableConference,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL);
+
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
+ // Check status hints image for cross user access
+ if (parcelableConference.getStatusHints() != null) {
+ Icon icon = parcelableConference.getStatusHints().getIcon();
+ parcelableConference.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, callingUserHandle));
+ }
+
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -637,10 +654,17 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
public void setStatusHints(String callId, StatusHints statusHints,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, "CSW.sSH");
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("setStatusHints %s %s", callId, statusHints);
+ // Check status hints image for cross user access
+ if (statusHints != null) {
+ Icon icon = statusHints.getIcon();
+ statusHints.setIcon(StatusHints.validateAccountIconUserBoundary(
+ icon, callingUserHandle));
+ }
Call call = mCallIdMapper.getCall(callId);
if (call != null) {
call.setStatusHints(statusHints);
@@ -819,6 +843,14 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
} else {
connectIdToCheck = callId;
}
+
+ // Check status hints image for cross user access
+ if (connection.getStatusHints() != null) {
+ Icon icon = connection.getStatusHints().getIcon();
+ connection.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, userHandle));
+ }
+
// Check to see if this Connection has already been added.
Call alreadyAddedConnection = mCallsManager
.getAlreadyAddedConnection(connectIdToCheck);
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index e304d3416..190604a75 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -16,9 +16,12 @@
package com.android.server.telecom.tests;
+import static com.android.server.telecom.tests.ConnectionServiceFixture.STATUS_HINTS_EXTRA;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
@@ -34,6 +37,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.IContentProvider;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
@@ -50,12 +55,15 @@ import android.telecom.Log;
import android.telecom.ParcelableCall;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.support.test.filters.FlakyTest;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.telecom.IInCallAdapter;
import com.android.internal.telephony.CallerInfo;
@@ -179,7 +187,7 @@ public class BasicCallTests extends TelecomSystemTest {
@Test
public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -208,7 +216,7 @@ public class BasicCallTests extends TelecomSystemTest {
@Test
public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -236,7 +244,7 @@ public class BasicCallTests extends TelecomSystemTest {
@Test
public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -629,13 +637,13 @@ public class BasicCallTests extends TelecomSystemTest {
@MediumTest
@Test
public void testBasicConferenceCall() throws Exception {
- makeConferenceCall();
+ makeConferenceCall(null, null);
}
@MediumTest
@Test
public void testAddCallToConference1() throws Exception {
- ParcelableCall conferenceCall = makeConferenceCall();
+ ParcelableCall conferenceCall = makeConferenceCall(null, null);
IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
// testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
@@ -653,7 +661,7 @@ public class BasicCallTests extends TelecomSystemTest {
@MediumTest
@Test
public void testAddCallToConference2() throws Exception {
- ParcelableCall conferenceCall = makeConferenceCall();
+ ParcelableCall conferenceCall = makeConferenceCall(null, null);
IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
mInCallServiceFixtureX.getInCallAdapter()
@@ -909,7 +917,7 @@ public class BasicCallTests extends TelecomSystemTest {
public void testOutgoingCallSelectPhoneAccountVideo() throws Exception {
startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
null, mConnectionServiceFixtureA,
- Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
+ Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
assert(call.isVideoCallingSupported());
@@ -932,7 +940,7 @@ public class BasicCallTests extends TelecomSystemTest {
public void testOutgoingCallSelectPhoneAccountNoVideo() throws Exception {
startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
null, mConnectionServiceFixtureA,
- Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
+ Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
assert(call.isVideoCallingSupported());
@@ -1134,4 +1142,145 @@ public class BasicCallTests extends TelecomSystemTest {
assertTrue(muteValues.get(0));
assertFalse(muteValues.get(1));
}
+
+ /**
+ * Verifies that StatusHints image is validated in ConnectionServiceWrapper#addConferenceCall
+ * when the image doesn't belong to the calling user. Simulates a scenario where an app
+ * could manipulate the contents of the bundle and send it via the binder to upload an image
+ * from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_addConferenceCall() throws Exception {
+ Intent callIntent1 = new Intent();
+ // Stub intent for call2
+ Intent callIntent2 = new Intent();
+ Bundle callExtras1 = new Bundle();
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ // Load StatusHints extra into TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS to be processed
+ // as the call extras. This will be leveraged in ConnectionServiceFixture to set the
+ // StatusHints for the given connection.
+ StatusHints statusHints = new StatusHints(icon);
+ assertNotNull(statusHints.getIcon());
+ callExtras1.putParcelable(STATUS_HINTS_EXTRA, statusHints);
+ callIntent1.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras1);
+
+ // Start conference call to invoke ConnectionServiceWrapper#addConferenceCall.
+ // Note that the calling user would be User 0.
+ ParcelableCall conferenceCall = makeConferenceCall(callIntent1, callIntent2);
+
+ // Ensure that StatusHints was set.
+ assertNotNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
+ .getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
+ .getStatusHints().getIcon());
+ }
+
+ /**
+ * Verifies that StatusHints image is validated in
+ * ConnectionServiceWrapper#handleCreateConnectionComplete when the image doesn't belong to the
+ * calling user. Simulates a scenario where an app could manipulate the contents of the
+ * bundle and send it via the binder to upload an image from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_handleCreateConnectionComplete() throws Exception {
+ Bundle extras = new Bundle();
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ // Load the bundle with the test extra in order to simulate an app directly invoking the
+ // binder on ConnectionServiceWrapper#handleCreateConnectionComplete.
+ StatusHints statusHints = new StatusHints(icon);
+ assertNotNull(statusHints.getIcon());
+ extras.putParcelable(STATUS_HINTS_EXTRA, statusHints);
+
+ // Start incoming call with StatusHints extras
+ // Note that the calling user in ConnectionServiceWrapper#handleCreateConnectionComplete
+ // would be User 0.
+ IdPair ids = startIncomingPhoneCallWithExtras("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, extras);
+
+ // Ensure that StatusHints was set.
+ assertNotNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints().getIcon());
+ }
+
+ /**
+ * Verifies that StatusHints image is validated in ConnectionServiceWrapper#setStatusHints
+ * when the image doesn't belong to the calling user. Simulates a scenario where an app
+ * could manipulate the contents of the bundle and send it via the binder to upload an image
+ * from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_setStatusHints() throws Exception {
+ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ // Modify existing connection with StatusHints image exploit
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ StatusHints statusHints = new StatusHints(icon);
+ assertNotNull(statusHints.getIcon());
+ ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
+ .mConnectionById.get(outgoing.mConnectionId);
+ connectionInfo.statusHints = statusHints;
+
+ // Invoke ConnectionServiceWrapper#setStatusHints.
+ // Note that the calling user would be User 0.
+ mConnectionServiceFixtureA.sendSetStatusHints(outgoing.mConnectionId);
+ waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
+ TEST_TIMEOUT);
+
+ // Ensure that StatusHints was set.
+ assertNotNull(mInCallServiceFixtureX.getCall(outgoing.mCallId).getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mInCallServiceFixtureX.getCall(outgoing.mCallId)
+ .getStatusHints().getIcon());
+ }
+
+ /**
+ * Verifies that StatusHints image is validated in
+ * ConnectionServiceWrapper#addExistingConnection when the image doesn't belong to the calling
+ * user. Simulates a scenario where an app could manipulate the contents of the bundle and
+ * send it via the binder to upload an image from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_addExistingConnection() throws Exception {
+ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ Connection existingConnection = mConnectionServiceFixtureA.mLatestConnection;
+
+ // Modify existing connection with StatusHints image exploit
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ StatusHints modifiedStatusHints = new StatusHints(icon);
+ assertNotNull(modifiedStatusHints.getIcon());
+ ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
+ .mConnectionById.get(outgoing.mConnectionId);
+ connectionInfo.statusHints = modifiedStatusHints;
+
+ // Invoke ConnectionServiceWrapper#addExistingConnection.
+ // Note that the calling user would be User 0.
+ mConnectionServiceFixtureA.sendAddExistingConnection(outgoing.mConnectionId);
+ waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
+ TEST_TIMEOUT);
+
+ // Ensure that StatusHints was set. Due to test setup, the ParcelableConnection object that
+ // is passed into sendAddExistingConnection is instantiated on invocation. The call's
+ // StatusHints are not updated at the time of completion, so instead, we can verify that
+ // the ParcelableConnection object was modified.
+ assertNotNull(mConnectionServiceFixtureA.mLatestParcelableConnection.getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mConnectionServiceFixtureA.mLatestParcelableConnection
+ .getStatusHints().getIcon());
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
index 44578c519..219a81e63 100644
--- a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
@@ -357,7 +357,7 @@ public class CallExtrasTest extends TelecomSystemTest {
@LargeTest
@Test
public void testConferenceSetExtras() throws Exception {
- ParcelableCall call = makeConferenceCall();
+ ParcelableCall call = makeConferenceCall(null, null);
String conferenceId = call.getId();
Conference conference = mConnectionServiceFixtureA.mLatestConference;
@@ -400,7 +400,7 @@ public class CallExtrasTest extends TelecomSystemTest {
@LargeTest
@Test
public void testConferenceExtraOperations() throws Exception {
- ParcelableCall call = makeConferenceCall();
+ ParcelableCall call = makeConferenceCall(null, null);
String conferenceId = call.getId();
Conference conference = mConnectionServiceFixtureA.mLatestConference;
assertNotNull(conference);
@@ -436,7 +436,7 @@ public class CallExtrasTest extends TelecomSystemTest {
@LargeTest
@Test
public void testConferenceICS() throws Exception {
- ParcelableCall call = makeConferenceCall();
+ ParcelableCall call = makeConferenceCall(null, null);
String conferenceId = call.getId();
Conference conference = mConnectionServiceFixtureA.mLatestConference;
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 3154b7d0d..f91863fbe 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -67,6 +67,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
static int INVALID_VIDEO_STATE = -1;
public CountDownLatch mExtrasLock = new CountDownLatch(1);
static int NOT_SPECIFIED = 0;
+ public static final String STATUS_HINTS_EXTRA = "updateStatusHints";
/**
* Implementation of ConnectionService that performs no-ops for tasks normally meant for
@@ -101,6 +102,11 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
if (mProperties != NOT_SPECIFIED) {
fakeConnection.setConnectionProperties(mProperties);
}
+ // Testing for StatusHints image icon cross user access
+ if (request.getExtras() != null) {
+ fakeConnection.setStatusHints(
+ request.getExtras().getParcelable(STATUS_HINTS_EXTRA));
+ }
return fakeConnection;
}
@@ -117,6 +123,11 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
if (mProperties != NOT_SPECIFIED) {
fakeConnection.setConnectionProperties(mProperties);
}
+ // Testing for StatusHints image icon cross user access
+ if (request.getExtras() != null) {
+ fakeConnection.setStatusHints(
+ request.getExtras().getParcelable(STATUS_HINTS_EXTRA));
+ }
return fakeConnection;
}
@@ -133,6 +144,12 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
Conference fakeConference = new FakeConference();
fakeConference.addConnection(cxn1);
fakeConference.addConnection(cxn2);
+ if (cxn1.getStatusHints() != null || cxn2.getStatusHints() != null) {
+ // For testing purposes, pick one of the status hints that isn't null.
+ StatusHints statusHints = cxn1.getStatusHints() != null
+ ? cxn1.getStatusHints() : cxn2.getStatusHints();
+ fakeConference.setStatusHints(statusHints);
+ }
mLatestConference = fakeConference;
addConference(fakeConference);
} else {
@@ -438,6 +455,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
public String mLatestConnectionId;
public Connection mLatestConnection;
+ public ParcelableConnection mLatestParcelableConnection;
public Conference mLatestConference;
public final Set<IConnectionServiceAdapter> mConnectionServiceAdapters = new HashSet<>();
public final Map<String, ConnectionInfo> mConnectionById = new HashMap<>();
@@ -672,7 +690,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
}
private ParcelableConnection parcelable(ConnectionInfo c) {
- return new ParcelableConnection(
+ mLatestParcelableConnection = new ParcelableConnection(
c.request.getAccountHandle(),
c.state,
c.capabilities,
@@ -692,5 +710,6 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
c.disconnectCause,
c.conferenceableConnectionIds,
c.extras);
+ return mLatestParcelableConnection;
}
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 4cf76444a..c98b7e699 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -374,12 +374,13 @@ public class TelecomSystemTest extends TelecomTestCase {
super.tearDown();
}
- protected ParcelableCall makeConferenceCall() throws Exception {
- IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212",
- mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ protected ParcelableCall makeConferenceCall(
+ Intent callIntentExtras1, Intent callIntentExtras2) throws Exception {
+ IdPair callId1 = startAndMakeActiveOutgoingCallWithExtras("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras1);
- IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213",
- mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ IdPair callId2 = startAndMakeActiveOutgoingCallWithExtras("650-555-1213",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras2);
IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
@@ -582,17 +583,17 @@ public class TelecomSystemTest extends TelecomTestCase {
throws Exception {
return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
- initiatingUser, VideoProfile.STATE_AUDIO_ONLY);
+ initiatingUser, VideoProfile.STATE_AUDIO_ONLY, null);
}
protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
- int videoState) throws Exception {
+ int videoState, Intent callIntentExtras) throws Exception {
int startingNumConnections = connectionServiceFixture.mConnectionById.size();
int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
startOutgoingPhoneCallPendingCreateConnection(number, phoneAccountHandle,
- connectionServiceFixture, initiatingUser, videoState);
+ connectionServiceFixture, initiatingUser, videoState, callIntentExtras);
verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
.createConnectionComplete(anyString(), any());
@@ -631,7 +632,7 @@ public class TelecomSystemTest extends TelecomTestCase {
mIsEmergencyCall = true;
// Call will not use the ordered broadcaster, since it is an Emergency Call
startOutgoingPhoneCallWaitForBroadcaster(number, phoneAccountHandle,
- connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/);
+ connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/, null);
return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
phoneAccountHandle, connectionServiceFixture);
@@ -640,7 +641,7 @@ public class TelecomSystemTest extends TelecomTestCase {
protected void startOutgoingPhoneCallWaitForBroadcaster(String number,
PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
- int videoState, boolean isEmergency) throws Exception {
+ int videoState, boolean isEmergency, Intent actionCallIntent) throws Exception {
reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
mInCallServiceFixtureY.getTestDouble());
@@ -653,7 +654,9 @@ public class TelecomSystemTest extends TelecomTestCase {
boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
- Intent actionCallIntent = new Intent();
+ if (actionCallIntent == null) {
+ actionCallIntent = new Intent();
+ }
actionCallIntent.setData(Uri.parse("tel:" + number));
actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
if(isEmergency) {
@@ -699,9 +702,9 @@ public class TelecomSystemTest extends TelecomTestCase {
protected String startOutgoingPhoneCallPendingCreateConnection(String number,
PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
- int videoState) throws Exception {
+ int videoState, Intent callIntentExtras) throws Exception {
startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle,
- connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/);
+ connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/, callIntentExtras);
ArgumentCaptor<Intent> newOutgoingCallIntent =
ArgumentCaptor.forClass(Intent.class);
@@ -798,14 +801,24 @@ public class TelecomSystemTest extends TelecomTestCase {
PhoneAccountHandle phoneAccountHandle,
final ConnectionServiceFixture connectionServiceFixture) throws Exception {
return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
- connectionServiceFixture);
+ connectionServiceFixture, null);
+ }
+
+ protected IdPair startIncomingPhoneCallWithExtras(
+ String number,
+ PhoneAccountHandle phoneAccountHandle,
+ final ConnectionServiceFixture connectionServiceFixture,
+ Bundle extras) throws Exception {
+ return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
+ connectionServiceFixture, extras);
}
protected IdPair startIncomingPhoneCall(
String number,
PhoneAccountHandle phoneAccountHandle,
int videoState,
- final ConnectionServiceFixture connectionServiceFixture) throws Exception {
+ final ConnectionServiceFixture connectionServiceFixture,
+ Bundle extras) throws Exception {
reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
mInCallServiceFixtureY.getTestDouble());
@@ -822,7 +835,9 @@ public class TelecomSystemTest extends TelecomTestCase {
new IncomingCallAddedListener(incomingCallAddedLatch);
mTelecomSystem.getCallsManager().addListener(callAddedListener);
- Bundle extras = new Bundle();
+ if (extras == null) {
+ extras = new Bundle();
+ }
extras.putParcelable(
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null));
@@ -916,7 +931,16 @@ public class TelecomSystemTest extends TelecomTestCase {
PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture) throws Exception {
return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
- VideoProfile.STATE_AUDIO_ONLY);
+ VideoProfile.STATE_AUDIO_ONLY, null);
+ }
+
+ protected IdPair startAndMakeActiveOutgoingCallWithExtras(
+ String number,
+ PhoneAccountHandle phoneAccountHandle,
+ ConnectionServiceFixture connectionServiceFixture,
+ Intent callIntentExtras) throws Exception {
+ return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
+ VideoProfile.STATE_AUDIO_ONLY, callIntentExtras);
}
// A simple outgoing call, verifying that the appropriate connection service is contacted,
@@ -924,9 +948,10 @@ public class TelecomSystemTest extends TelecomTestCase {
protected IdPair startAndMakeActiveOutgoingCall(
String number,
PhoneAccountHandle phoneAccountHandle,
- ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception {
+ ConnectionServiceFixture connectionServiceFixture, int videoState,
+ Intent callIntentExtras) throws Exception {
IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
- Process.myUserHandle(), videoState);
+ Process.myUserHandle(), videoState, callIntentExtras);
connectionServiceFixture.sendSetDialing(ids.mConnectionId);
if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
index 97e71d18b..84beedc0f 100644
--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -105,7 +105,7 @@ public class VideoCallTests extends TelecomSystemTest {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
verifyAudioRoute(CallAudioState.ROUTE_SPEAKER);
}
@@ -121,7 +121,7 @@ public class VideoCallTests extends TelecomSystemTest {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
- VideoProfile.STATE_TX_ENABLED);
+ VideoProfile.STATE_TX_ENABLED, null);
verifyAudioRoute(CallAudioState.ROUTE_SPEAKER);
}
@@ -137,7 +137,7 @@ public class VideoCallTests extends TelecomSystemTest {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
- VideoProfile.STATE_AUDIO_ONLY);
+ VideoProfile.STATE_AUDIO_ONLY, null);
verifyAudioRoute(CallAudioState.ROUTE_EARPIECE);
}
@@ -165,7 +165,7 @@ public class VideoCallTests extends TelecomSystemTest {
@Test
public void testIncomingVideoCallMissedCheckVideoHistory() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -182,7 +182,7 @@ public class VideoCallTests extends TelecomSystemTest {
@Test
public void testIncomingVideoCallRejectedCheckVideoHistory() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -201,7 +201,7 @@ public class VideoCallTests extends TelecomSystemTest {
public void testOutgoingVideoCallCanceledCheckVideoHistory() throws Exception {
IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
mConnectionServiceFixtureA, Process.myUserHandle(),
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -219,7 +219,7 @@ public class VideoCallTests extends TelecomSystemTest {
public void testOutgoingVideoCallRejectedCheckVideoHistory() throws Exception {
IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
mConnectionServiceFixtureA, Process.myUserHandle(),
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -237,7 +237,7 @@ public class VideoCallTests extends TelecomSystemTest {
public void testOutgoingVideoCallAnsweredAsAudio() throws Exception {
IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
mConnectionServiceFixtureA, Process.myUserHandle(),
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();

View File

@ -1,138 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ashish Kumar <akgaurav@google.com>
Date: Fri, 26 May 2023 14:18:46 +0000
Subject: [PATCH] RESTRICT AUTOMERGE Fixed leak of cross user data in multiple
settings.
- Any app is allowed to receive GET_CONTENT intent. Using this, an user puts back in the intent an uri with data of another user.
- Telephony service has INTERACT_ACROSS_USER permission. Using this, it reads and shows the deta to the evil user.
Fix: When telephony service gets the intent result, it checks if the uri is from the current user or not.
Bug: b/256591023 , b/256819787
Test: The malicious behaviour was not being reproduced. Unable to import contact from other users data.
Test2: Able to import contact from the primary user or uri with no user id
(These settings are not available for secondary users)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:36e10a6d0d7b9efc543f8004729fa85751f4f70d)
Merged-In: I1e3a643f17948153aecc1d0df9ffd9619ad678c1
Change-Id: I1e3a643f17948153aecc1d0df9ffd9619ad678c1
---
.../android/phone/GsmUmtsCallForwardOptions.java | 12 ++++++++++++
.../phone/settings/VoicemailSettingsActivity.java | 14 ++++++++++++++
.../phone/settings/fdn/EditFdnContactScreen.java | 13 +++++++++++++
3 files changed, 39 insertions(+)
diff --git a/src/com/android/phone/GsmUmtsCallForwardOptions.java b/src/com/android/phone/GsmUmtsCallForwardOptions.java
index 77cc6cca6..aa1c797d4 100644
--- a/src/com/android/phone/GsmUmtsCallForwardOptions.java
+++ b/src/com/android/phone/GsmUmtsCallForwardOptions.java
@@ -5,9 +5,12 @@ import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Phone;
import android.app.ActionBar;
+import android.content.ContentProvider;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.telephony.CarrierConfigManager;
@@ -156,6 +159,15 @@ public class GsmUmtsCallForwardOptions extends TimeConsumingPreferenceActivity {
}
Cursor cursor = null;
try {
+ // check if the URI returned by the user belongs to the user
+ final int currentUser = UserHandle.getUserId(Process.myUid());
+ if (currentUser
+ != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) {
+
+ Log.w(LOG_TAG, "onActivityResult: Contact data of different user, "
+ + "cannot access");
+ return;
+ }
cursor = getContentResolver().query(data.getData(),
NUM_PROJECTION, null, null, null);
if ((cursor == null) || (!cursor.moveToFirst())) {
diff --git a/src/com/android/phone/settings/VoicemailSettingsActivity.java b/src/com/android/phone/settings/VoicemailSettingsActivity.java
index 0f58d195b..af9a746ed 100644
--- a/src/com/android/phone/settings/VoicemailSettingsActivity.java
+++ b/src/com/android/phone/settings/VoicemailSettingsActivity.java
@@ -17,6 +17,7 @@
package com.android.phone.settings;
import android.app.Dialog;
+import android.content.ContentProvider;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
@@ -25,6 +26,8 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceActivity;
@@ -522,6 +525,17 @@ public class VoicemailSettingsActivity extends PreferenceActivity
Cursor cursor = null;
try {
+ // check if the URI returned by the user belongs to the user
+ final int currentUser = UserHandle.getUserId(Process.myUid());
+ if (currentUser
+ != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) {
+
+ if (DBG) {
+ log("onActivityResult: Contact data of different user, "
+ + "cannot access");
+ }
+ return;
+ }
cursor = getContentResolver().query(data.getData(),
new String[] { CommonDataKinds.Phone.NUMBER }, null, null, null);
if ((cursor == null) || (!cursor.moveToFirst())) {
diff --git a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
index 921e947e4..e733e82bb 100644
--- a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
+++ b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
@@ -18,9 +18,12 @@ package com.android.phone.settings.fdn;
import static android.view.Window.PROGRESS_VISIBILITY_OFF;
import static android.view.Window.PROGRESS_VISIBILITY_ON;
+import static android.app.Activity.RESULT_OK;
+
import android.app.Activity;
import android.content.AsyncQueryHandler;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
@@ -29,6 +32,8 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Process;
+import android.os.UserHandle;
import android.provider.Contacts.PeopleColumns;
import android.provider.Contacts.PhonesColumns;
import android.provider.ContactsContract.CommonDataKinds;
@@ -154,6 +159,14 @@ public class EditFdnContactScreen extends Activity {
}
Cursor cursor = null;
try {
+ // check if the URI returned by the user belongs to the user
+ final int currentUser = UserHandle.getUserId(Process.myUid());
+ if (currentUser
+ != ContentProvider.getUserIdFromUri(intent.getData(), currentUser)) {
+ Log.w(LOG_TAG, "onActivityResult: Contact data of different user, "
+ + "cannot access");
+ return;
+ }
cursor = getContentResolver().query(intent.getData(),
NUM_PROJECTION, null, null, null);
if ((cursor == null) || (!cursor.moveToFirst())) {

View File

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: tyiu <tyiu@google.com>
Date: Tue, 28 Mar 2023 18:40:51 +0000
Subject: [PATCH] Fix gatt_end_operation buffer overflow
Added boundary check for gatt_end_operation to prevent writing out of
boundary.
Since response of the GATT server is handled in
gatt_client_handle_server_rsp() and gatt_process_read_rsp(), the maximum
lenth that can be passed into the handlers is bounded by
GATT_MAX_MTU_SIZE, which is set to 517, which is greater than
GATT_MAX_ATTR_LEN which is set to 512. The fact that there is no spec
that gaurentees MTU response to be less than or equal to 512 bytes can
cause a buffer overflow when performing memcpy without length check.
Bug: 261068592
Test: No test since not affecting behavior
Tag: #security
Ignore-AOSP-First: security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dd7298e982e4bbf0138a490562679c9a4a755200)
Merged-In: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873
Change-Id: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873
---
stack/gatt/gatt_utils.cc | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc
index 9e8d3b930..52891efc4 100644
--- a/stack/gatt/gatt_utils.cc
+++ b/stack/gatt/gatt_utils.cc
@@ -1193,6 +1193,13 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) {
cb_data.att_value.handle = p_clcb->s_handle;
cb_data.att_value.len = p_clcb->counter;
+ if (cb_data.att_value.len > GATT_MAX_ATTR_LEN) {
+ LOG(WARNING) << __func__
+ << StringPrintf(" Large cb_data.att_value, size=%d",
+ cb_data.att_value.len);
+ cb_data.att_value.len = GATT_MAX_ATTR_LEN;
+ }
+
if (p_data && p_clcb->counter)
memcpy(cb_data.att_value.value, p_data, cb_data.att_value.len);
}

View File

@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hui Peng <phui@google.com>
Date: Tue, 16 May 2023 21:24:07 +0000
Subject: [PATCH] Fix an integer overflow bug in avdt_msg_asmbl
This is a backport of
Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
to rvc-dev
Bug: 280633699
Test: manual
Ignore-AOSP-First: security
Tag: #security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:26347d4bdba646bbba4d27337d2888a04de42639)
Merged-In: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
Change-Id: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
---
stack/avdt/avdt_msg.cc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index 453e18642..3576b74e6 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -1261,14 +1261,14 @@ BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
* NOTE: The buffer is allocated above at the beginning of the
* reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
*/
- uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
+ size_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
/* adjust offset and len of fragment for header byte */
p_buf->offset += AVDT_LEN_TYPE_CONT;
p_buf->len -= AVDT_LEN_TYPE_CONT;
/* verify length */
- if ((p_ccb->p_rx_msg->offset + p_buf->len) > buf_len) {
+ if (((size_t) p_ccb->p_rx_msg->offset + (size_t) p_buf->len) > buf_len) {
/* won't fit; free everything */
AVDT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
osi_free_and_reset((void**)&p_ccb->p_rx_msg);

View File

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Fri, 19 May 2023 19:17:16 +0000
Subject: [PATCH] Fix integer overflow in build_read_multi_rsp
Local variables tracking structure size in build_read_multi_rsp are of
uint16 type but accept a full uint16 range from function arguments while
appending a fixed-length offset. This can lead to an integer overflow
and unexpected behavior.
Change the locals to size_t, and add a check during reasssignment.
Bug: 273966636
Test: atest bluetooth_test_gd_unit, net_test_stack_btm
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:53f64274cbf2268ad6db5af9c61ceead9ef64fb0)
Merged-In: Iff252f0dd06aac9776e8548631e0b700b3ed85b9
Change-Id: Iff252f0dd06aac9776e8548631e0b700b3ed85b9
---
stack/gatt/gatt_sr.cc | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/stack/gatt/gatt_sr.cc b/stack/gatt/gatt_sr.cc
index b9921fee6..d4e3c046b 100644
--- a/stack/gatt/gatt_sr.cc
+++ b/stack/gatt/gatt_sr.cc
@@ -113,7 +113,8 @@ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb) {
******************************************************************************/
static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
tGATTS_RSP* p_msg, uint16_t mtu) {
- uint16_t ii, total_len, len;
+ uint16_t ii;
+ size_t total_len, len;
uint8_t* p;
bool is_overflow = false;
@@ -168,16 +169,22 @@ static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
len = p_rsp->attr_value.len - (total_len - mtu);
is_overflow = true;
VLOG(1) << StringPrintf(
- "multi read overflow available len=%d val_len=%d", len,
+ "multi read overflow available len=%zu val_len=%d", len,
p_rsp->attr_value.len);
} else {
len = p_rsp->attr_value.len;
}
if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) {
- memcpy(p, p_rsp->attr_value.value, len);
- if (!is_overflow) p += len;
- p_buf->len += len;
+ // check for possible integer overflow
+ if (p_buf->len + len <= UINT16_MAX) {
+ memcpy(p, p_rsp->attr_value.value, len);
+ if (!is_overflow) p += len;
+ p_buf->len += len;
+ } else {
+ p_cmd->status = GATT_NOT_FOUND;
+ break;
+ }
} else {
p_cmd->status = GATT_NOT_FOUND;
break;

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Thu, 27 Apr 2023 20:43:58 +0000
Subject: [PATCH] Fix potential abort in btu_av_act.cc
Partner analysis shows that bta_av_rc_msg does not respect handling
established for a null browse packet, instead dispatching the null
pointer to bta_av_rc_free_browse_msg. Strictly speaking this does
not cause a UAF, as osi_free_and_reset will find the null and abort,
but it will lead to improper program termination.
Handle the case instead.
Bug: 269253349
Test: atest bluetooth_test_gd_unit
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:91f6d6215c101acc99a7397c5fb5a12fe6d7b8e9)
Merged-In: I4df7045798b663fbefd7434288dc9383216171a7
Change-Id: I4df7045798b663fbefd7434288dc9383216171a7
---
bta/av/bta_av_act.cc | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/bta/av/bta_av_act.cc b/bta/av/bta_av_act.cc
index 112645ecf..0cd7b5d00 100644
--- a/bta/av/bta_av_act.cc
+++ b/bta/av/bta_av_act.cc
@@ -997,7 +997,10 @@ void bta_av_rc_msg(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) {
av.remote_cmd.rc_handle = p_data->rc_msg.handle;
(*p_cb->p_cback)(evt, &av);
/* If browsing message, then free the browse message buffer */
- bta_av_rc_free_browse_msg(p_cb, p_data);
+ if (p_data->rc_msg.opcode == AVRC_OP_BROWSE &&
+ p_data->rc_msg.msg.browse.p_browse_pkt != NULL) {
+ bta_av_rc_free_browse_msg(p_cb, p_data);
+ }
}
}

View File

@ -1,80 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Qiyu Hu <qiyuh@google.com>
Date: Wed, 13 Jun 2018 08:08:17 -0700
Subject: [PATCH] Fix reliable write.
We cannot simply assume the write is terminated in reliable write. When
the reliable write value is longer than MTU allows, the current
implementation can only send whatever MTU allows and naively set the
status to GATT_SUCCESS, in the name of "application should verify handle
offset and value are matched or not". That's why MTU negotiation is a
workaround as people mention in b/37031096, which just fits all the write
value into a single request.
This also blocks our test on CtsVerifier.
Bug: 37031096
Test: Manual test and confirm that we don't simply send partial value
Change-Id: I907877608f4672f24c002e630e58bf9133937a5e
---
stack/gatt/gatt_cl.cc | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index f8d5bab92..16a7171f6 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -297,7 +297,7 @@ void gatt_send_queue_write_cancel(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
tGATT_VALUE* p_rsp_value) {
tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
- bool exec = false;
+ bool terminate = false;
tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
VLOG(1) << __func__;
@@ -310,19 +310,18 @@ bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
/* data does not match */
p_clcb->status = GATT_ERROR;
flag = GATT_PREP_WRITE_CANCEL;
- exec = true;
+ terminate = true;
} else /* response checking is good */
{
p_clcb->status = GATT_SUCCESS;
/* update write offset and check if end of attribute value */
- if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) exec = true;
+ if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) terminate = true;
}
}
- if (exec) {
+ if (terminate && p_clcb->op_subtype != GATT_WRITE_PREPARE) {
gatt_send_queue_write_cancel(tcb, p_clcb, flag);
- return true;
}
- return false;
+ return terminate;
}
/** Send prepare write */
@@ -587,15 +586,15 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
memcpy(value.value, p, value.len);
+ if (!gatt_check_write_long_terminate(tcb, p_clcb, &value)) {
+ gatt_send_prepare_write(tcb, p_clcb);
+ return;
+ }
+
if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
- p_clcb->status = GATT_SUCCESS;
/* application should verify handle offset
and value are matched or not */
-
gatt_end_operation(p_clcb, p_clcb->status, &value);
- } else if (p_clcb->op_subtype == GATT_WRITE) {
- if (!gatt_check_write_long_terminate(tcb, p_clcb, &value))
- gatt_send_prepare_write(tcb, p_clcb);
}
}
/*******************************************************************************

View File

@ -1,44 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Thu, 1 Jun 2023 23:57:58 +0000
Subject: [PATCH] Fix UAF in gatt_cl.cc
gatt_cl.cc accesses a header field after the buffer holding it may have
been freed.
Track the relevant state as a local variable instead.
Bug: 274617156
Test: atest: bluetooth, validated against fuzzer
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d7a7f7f3311202065de4b2c17b49994053dd1244)
Merged-In: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
Change-Id: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
---
stack/gatt/gatt_cl.cc | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index 16a7171f6..5e4837020 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -586,12 +586,17 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
memcpy(value.value, p, value.len);
+ bool subtype_is_write_prepare = (p_clcb->op_subtype == GATT_WRITE_PREPARE);
+
if (!gatt_check_write_long_terminate(tcb, p_clcb, &value)) {
gatt_send_prepare_write(tcb, p_clcb);
return;
}
- if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
+ // We now know that we have not terminated, or else we would have returned
+ // early. We free the buffer only if the subtype is not equal to
+ // GATT_WRITE_PREPARE, so checking here is adequate to prevent UAF.
+ if (subtype_is_write_prepare) {
/* application should verify handle offset
and value are matched or not */
gatt_end_operation(p_clcb, p_clcb->status, &value);

View File

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Tue, 2 May 2023 14:20:57 -0700
Subject: [PATCH] OOBW in rw_i93_send_to_upper()
Bug: 271849189
Test: tag r/w
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc9d09e1698725712628d394bf9be4c9003579e8)
Merged-In: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
Change-Id: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
---
src/nfc/tags/rw_i93.cc | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
index acf28a6..232a4dd 100644
--- a/src/nfc/tags/rw_i93.cc
+++ b/src/nfc/tags/rw_i93.cc
@@ -507,6 +507,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) {
case I93_CMD_GET_MULTI_BLK_SEC:
case I93_CMD_EXT_GET_MULTI_BLK_SEC:
+ if (UINT16_MAX - length < NFC_HDR_SIZE) {
+ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED;
+ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+ rw_cb.tcb.i93.sent_cmd = 0;
+
+ event = RW_I93_CMD_CMPL_EVT;
+ break;
+ }
+
/* forward tag data or security status */
p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE));

View File

@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Khaled Abdelmohsen <khelmy@google.com>
Date: Mon, 24 Feb 2020 16:59:21 +0000
Subject: [PATCH] Create source stamp verifier
Bug: 148005911
Test: gradlew test
Change-Id: I7008c9567ad5e8b63e7f6ba192d38b10c5c9a2dc
Merged-In: I7008c9567ad5e8b63e7f6ba192d38b10c5c9a2dc
(cherry picked from commit a3970357d65d59b70c6ccf2c5c55000cb4310953)
---
.../internal/apk/ApkSigningBlockUtils.java | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java b/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
index 2330f6d..f15597b 100644
--- a/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
+++ b/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
@@ -998,6 +998,20 @@ public class ApkSigningBlockUtils {
return false;
}
+ public boolean containsWarnings() {
+ if (!mWarnings.isEmpty()) {
+ return true;
+ }
+ if (!signers.isEmpty()) {
+ for (SignerInfo signer : signers) {
+ if (signer.containsWarnings()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public void addError(ApkVerifier.Issue msg, Object... parameters) {
mErrors.add(new ApkVerifier.IssueWithParams(msg, parameters));
}
@@ -1042,6 +1056,10 @@ public class ApkSigningBlockUtils {
return !mErrors.isEmpty();
}
+ public boolean containsWarnings() {
+ return !mWarnings.isEmpty();
+ }
+
public List<ApkVerifier.IssueWithParams> getErrors() {
return mErrors;
}

View File

@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Tue, 2 May 2023 14:20:57 -0700
Subject: [PATCH] OOBW in rw_i93_send_to_upper()
Bug: 271849189
Test: tag r/w
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc9d09e1698725712628d394bf9be4c9003579e8)
Merged-In: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
Change-Id: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
Change-Id: Ia10491e388a495a164462c73ced7ea1965808860
---
src/nfc/tags/rw_i93.cc | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
index 62c5b54c..13ccaf0e 100755
--- a/src/nfc/tags/rw_i93.cc
+++ b/src/nfc/tags/rw_i93.cc
@@ -472,6 +472,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) {
case I93_CMD_GET_MULTI_BLK_SEC:
case I93_CMD_EXT_GET_MULTI_BLK_SEC:
+ if (UINT16_MAX - length < NFC_HDR_SIZE) {
+ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED;
+ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+ rw_cb.tcb.i93.sent_cmd = 0;
+
+ event = RW_I93_CMD_CMPL_EVT;
+ break;
+ }
+
/* forward tag data or security status */
p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE));

View File

@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Thu, 1 Jun 2023 13:44:28 -0700
Subject: [PATCH] Ensure that SecureNFC setting cannot be bypassed
Bug: 268038643
Test: ctsverifier
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d6d8f79fd8d605b3cb460895a8e3a11bcf0c22b0)
Merged-In: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
Change-Id: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
Change-Id: Ib0baa833fe31c72825889b729c83a1d70a5a6a72
---
src/com/android/nfc/NfcService.java | 6 ++++++
src/com/android/nfc/cardemulation/HostEmulationManager.java | 5 +++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 28a1b92c..63cbed97 100644
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -1768,6 +1768,12 @@ public class NfcService implements DeviceHostListener {
}
}
+ public boolean isSecureNfcEnabled() {
+ synchronized (NfcService.this) {
+ return mIsSecureNfcEnabled;
+ }
+ }
+
final class NfcAdapterService extends INfcAdapter.Stub {
@Override
public boolean enable() throws RemoteException {
diff --git a/src/com/android/nfc/cardemulation/HostEmulationManager.java b/src/com/android/nfc/cardemulation/HostEmulationManager.java
index 91001582..ad4a3bd7 100644
--- a/src/com/android/nfc/cardemulation/HostEmulationManager.java
+++ b/src/com/android/nfc/cardemulation/HostEmulationManager.java
@@ -209,8 +209,9 @@ public class HostEmulationManager {
// Resolve to default
// Check if resolvedService requires unlock
NQApduServiceInfo defaultServiceInfo = resolveInfo.defaultService;
- if (defaultServiceInfo.requiresUnlock() &&
- mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
+ if ((defaultServiceInfo.requiresUnlock()
+ || NfcService.getInstance().isSecureNfcEnabled())
+ && mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
// Just ignore all future APDUs until next tap
mState = STATE_W4_DEACTIVATE;
launchTapAgain(resolveInfo.defaultService, resolveInfo.category);

View File

@ -1,38 +0,0 @@
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

@ -1,50 +0,0 @@
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

@ -1,386 +0,0 @@
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

@ -1,32 +0,0 @@
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

@ -1,233 +0,0 @@
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
Change-Id: Id95fc30cb9f22276114ecef543d7a7e9e0c3459b
---
.../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 9095b5d927a2..f88d6f6ca25a 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

@ -1,145 +0,0 @@
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

@ -1,84 +0,0 @@
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

@ -1,85 +0,0 @@
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

@ -1,42 +0,0 @@
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 f88d6f6ca25a..1fe66c0163b1 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -642,6 +642,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

@ -1,38 +0,0 @@
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

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aaron Liu <aaronjli@google.com>
Date: Tue, 28 Mar 2023 13:15:04 -0700
Subject: [PATCH] DO NOT MERGE Dismiss keyguard when simpin auth'd and...
security method is none. This is mostly to fix the case where we auth
sim pin in the set up wizard and it goes straight to keyguard instead of
the setup wizard activity.
This works with the prevent bypass keyguard flag because the device
should be noe secure in this case.
Fixes: 222446076
Test: turn locked sim on, which opens the sim pin screen. Auth the
screen and observe that keyguard is not shown.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:48fa9bef3451e4a358c941af5b230f99881c5cb6)
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
Change-Id: If4360dd6ae2e5f79b43eaf1a29687ac9cc4b6101
---
.../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 89514a52d0bd..bd555e7360d8 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

@ -1,30 +0,0 @@
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

@ -1,99 +0,0 @@
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

@ -1,127 +0,0 @@
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

@ -1,109 +0,0 @@
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..b4e2e2b9cac9 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;
}
@@ -4224,6 +4236,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

@ -1,54 +0,0 @@
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

@ -1,104 +0,0 @@
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 b4e2e2b9cac9..4f3dd3449fae 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

@ -1,93 +0,0 @@
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 | 20 +++++++++++++++++++
.../NotificationManagerServiceTest.java | 7 ++++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3e75c52bf893..8f0b36cf2a87 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 /*|| iconType == TYPE_URI_ADAPTIVE_BITMAP*/) {
+ 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)));
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..a7a6f7a59ac3 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,8 @@ 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

View File

@ -1,51 +0,0 @@
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

@ -1,242 +0,0 @@
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 | 91 ++++++++++++++++++-
2 files changed, 90 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..682ea6edf726 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,7 @@ 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 +10735,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 +12252,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 +12287,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 +12427,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 +12640,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 +13763,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 +14543,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

@ -1,70 +0,0 @@
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

@ -1,61 +0,0 @@
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 8f0b36cf2a87..8da2611d3fe9 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 a7a6f7a59ac3..578626482581 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 testSetNotificationPolicy_preP_setOldFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);

View File

@ -1,129 +0,0 @@
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

@ -1,55 +0,0 @@
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

@ -1,146 +0,0 @@
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 | 8 +++
.../java/android/telecom/StatusHints.java | 53 ++++++++++++++++++-
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java
index ede05943772e..b2f8ac8cb0ec 100644
--- a/telecomm/java/android/telecom/ParcelableConference.java
+++ b/telecomm/java/android/telecom/ParcelableConference.java
@@ -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..761eab81eb62 100644
--- a/telecomm/java/android/telecom/StatusHints.java
+++ b/telecomm/java/android/telecom/StatusHints.java
@@ -16,14 +16,19 @@
package android.telecom;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.util.Objects;
@@ -33,7 +38,7 @@ import java.util.Objects;
public final class StatusHints implements Parcelable {
private final CharSequence mLabel;
- private final Icon mIcon;
+ private Icon mIcon;
private final Bundle mExtras;
/**
@@ -48,10 +53,30 @@ public final class StatusHints implements Parcelable {
public StatusHints(CharSequence label, Icon icon, Bundle extras) {
mLabel = label;
- mIcon = icon;
+ mIcon = validateAccountIconUserBoundary(icon, Binder.getCallingUserHandle());
mExtras = extras;
}
+ /**
+ * @param icon
+ * @hide
+ */
+ @VisibleForTesting
+ public StatusHints(@Nullable Icon icon) {
+ mLabel = null;
+ mExtras = null;
+ mIcon = icon;
+ }
+
+ /**
+ *
+ * @param icon
+ * @hide
+ */
+ public void setIcon(@Nullable Icon icon) {
+ mIcon = icon;
+ }
+
/**
* @return A package used to load the icon.
*
@@ -112,6 +137,30 @@ public final class StatusHints implements Parcelable {
return 0;
}
+ /**
+ * Validates the StatusHints image icon to see if it's not in the calling user space.
+ * Invalidates the icon if so, otherwise returns back the original icon.
+ *
+ * @param icon
+ * @return icon (validated)
+ * @hide
+ */
+ public static Icon validateAccountIconUserBoundary(Icon icon, UserHandle callingUserHandle) {
+ // Refer to Icon#getUriString for context. The URI string is invalid for icons of
+ // incompatible types.
+ if (icon != null && (icon.getType() == Icon.TYPE_URI
+ /*|| icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP*/)) {
+ String encodedUser = icon.getUri().getEncodedUserInfo();
+ // If there is no encoded user, the URI is calling into the calling user space
+ if (encodedUser != null) {
+ int userId = Integer.parseInt(encodedUser);
+ // Do not try to save the icon if the user id isn't in the calling user space.
+ if (userId != callingUserHandle.getIdentifier()) return null;
+ }
+ }
+ return icon;
+ }
+
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeCharSequence(mLabel);

View File

@ -1,61 +0,0 @@
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

@ -1,109 +0,0 @@
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 578626482581..dbd65c776307 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);

View File

@ -1,28 +0,0 @@
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

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Devin Moore <devinmoore@google.com>
Date: Tue, 25 Apr 2023 00:17:13 +0000
Subject: [PATCH] Allow sensors list to be empty
Test: atest VtsHalSensorManagerV1_0TargetTest
Bug: 278013275
Bug: 269014004
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:49600b10aa5675d4e7e985203d69f252ead13e45)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7057a9f08d98bfec8ffbabcf00f2885d3909c6c9)
Merged-In: I091f57de9570b0ace3a8da76f16fe0e83f0aa624
Change-Id: I091f57de9570b0ace3a8da76f16fe0e83f0aa624
---
libs/sensor/SensorManager.cpp | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index 180a0ebd85..7f927d026e 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -172,11 +172,8 @@ status_t SensorManager::assertStateLocked() {
mSensors = mSensorServer->getSensorList(mOpPackageName);
size_t count = mSensors.size();
- if (count == 0) {
- ALOGE("Failed to get Sensor list");
- mSensorServer.clear();
- return UNKNOWN_ERROR;
- }
+ // If count is 0, mSensorList will be non-null. This is old
+ // existing behavior and callers expect this.
mSensorList =
static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
LOG_ALWAYS_FATAL_IF(mSensorList == nullptr, "mSensorList NULL");

View File

@ -1,237 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Nate(Qiang) Jiang" <qiangjiang@google.com>
Date: Wed, 12 Apr 2023 18:38:15 +0000
Subject: [PATCH] DO NOT MERGE: Limit the number of Passpoint per App
Reject the suggestion passpoint with ServiceFriendlyNames
Bug: 274445194
Test: atest com.android.server.wifi
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b081fc592709895f0e745ad33b41174b3b2ad399)
Merged-In: I30606e9bb4eba54b5b9111de4982c0cfb565b3dc
Change-Id: I30606e9bb4eba54b5b9111de4982c0cfb565b3dc
Change-Id: I7df5e55e777189bdc11765d11cb5e428fe928faa
---
.../wifi/hotspot2/PasspointManager.java | 6 ++
.../wifi/hotspot2/PasspointManagerTest.java | 56 ++++++++++---------
2 files changed, 37 insertions(+), 25 deletions(-)
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index 0666943c3..8916976ea 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -374,6 +374,12 @@ public class PasspointManager {
Log.e(TAG, "UID " + uid + " not visible to the current user");
return false;
}
+ if (getPasspointProviderWithPackage(packageName).size()
+ >= WifiManager.NETWORK_SUGGESTIONS_MAX_PER_APP) {
+ Log.e(TAG, "packageName " + packageName + " has too many passpoint with exceed the "
+ + "limitation");
+ return false;
+ }
// For Hotspot 2.0 Release 1, the CA Certificate must be trusted by one of the pre-loaded
// public CAs in the system key store on the device. Since the provisioning method
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
index 618f1c3d5..2b02ed508 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
@@ -42,6 +42,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
@@ -178,6 +179,7 @@ public class PasspointManagerTest {
@Mock TelephonyManager mDataTelephonyManager;
@Mock SubscriptionManager mSubscriptionManager;
@Mock WifiPermissionsUtil mWifiPermissionsUtil;
+ @Mock ActivityManager mActivityManager;
Handler mHandler;
TestLooper mLooper;
@@ -203,6 +205,7 @@ public class PasspointManagerTest {
any(PasspointManager.class), any(WifiMetrics.class)))
.thenReturn(mPasspointProvisioner);
when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+ when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl);
when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true);
mLooper = new TestLooper();
@@ -268,11 +271,6 @@ public class PasspointManagerTest {
homeSp.setFqdn(fqdn);
homeSp.setFriendlyName(friendlyName);
config.setHomeSp(homeSp);
- Map<String, String> friendlyNames = new HashMap<>();
- friendlyNames.put("en", friendlyName);
- friendlyNames.put("kr", friendlyName + 1);
- friendlyNames.put("jp", friendlyName + 2);
- config.setServiceFriendlyNames(friendlyNames);
Credential credential = new Credential();
credential.setRealm(TEST_REALM);
credential.setCaCertificate(FakeKeys.CA_CERT0);
@@ -315,8 +313,16 @@ public class PasspointManagerTest {
* @return {@link PasspointProvider}
*/
private PasspointProvider addTestProvider(String fqdn, String friendlyName,
- String packageName) {
+ String packageName,
+ boolean addServiceFriendlyNames) {
PasspointConfiguration config = createTestConfigWithUserCredential(fqdn, friendlyName);
+ if (addServiceFriendlyNames) {
+ Map<String, String> friendlyNames = new HashMap<>();
+ friendlyNames.put("en", friendlyName);
+ friendlyNames.put("kr", friendlyName + 1);
+ friendlyNames.put("jp", friendlyName + 2);
+ config.setServiceFriendlyNames(friendlyNames);
+ }
PasspointProvider provider = createMockProvider(config);
when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
eq(mSimAccessor), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE))).thenReturn(
@@ -738,7 +744,7 @@ public class PasspointManagerTest {
*/
@Test
public void matchProviderWithAnqpCacheMissed() throws Exception {
- addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(null);
assertNull(mManager.matchProvider(createTestScanResult()));
@@ -754,7 +760,7 @@ public class PasspointManagerTest {
*/
@Test
public void matchProviderAsHomeProvider() throws Exception {
- PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
ANQPData entry = new ANQPData(mClock, null);
when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
@@ -773,7 +779,7 @@ public class PasspointManagerTest {
*/
@Test
public void matchProviderAsRoamingProvider() throws Exception {
- PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
ANQPData entry = new ANQPData(mClock, null);
when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
@@ -792,7 +798,7 @@ public class PasspointManagerTest {
*/
@Test
public void matchProviderWithNoMatch() throws Exception {
- PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
ANQPData entry = new ANQPData(mClock, null);
when(mAnqpCache.getEntry(TEST_ANQP_KEY)).thenReturn(entry);
@@ -852,16 +858,16 @@ public class PasspointManagerTest {
InformationElementUtil.class).startMocking();
try {
PasspointProvider providerHome = addTestProvider(TEST_FQDN + 0, TEST_FRIENDLY_NAME,
- TEST_PACKAGE);
+ TEST_PACKAGE, false);
WifiConfiguration homeWifiConfiguration = new WifiConfiguration();
homeWifiConfiguration.FQDN = TEST_FQDN + 0;
homeWifiConfiguration.isHomeProviderNetwork = true;
PasspointProvider providerRoaming = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME,
- TEST_PACKAGE);
+ TEST_PACKAGE, false);
WifiConfiguration roamingWifiConfiguration = new WifiConfiguration();
roamingWifiConfiguration.FQDN = TEST_FQDN + 1;
PasspointProvider providerNone = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
- TEST_PACKAGE);
+ TEST_PACKAGE, false);
ANQPData entry = new ANQPData(mClock, null);
InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
vsa.anqpDomainID = TEST_ANQP_DOMAIN_ID2;
@@ -905,15 +911,15 @@ public class PasspointManagerTest {
*/
@Test
public void getWifiConfigsForPasspointProfiles() {
- PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
WifiConfiguration wifiConfiguration1 = new WifiConfiguration();
wifiConfiguration1.FQDN = TEST_FQDN;
PasspointProvider provider2 = addTestProvider(TEST_FQDN + 1, TEST_FRIENDLY_NAME,
- TEST_PACKAGE);
+ TEST_PACKAGE, false);
WifiConfiguration wifiConfiguration2 = new WifiConfiguration();
wifiConfiguration2.FQDN = TEST_FQDN + 1;
PasspointProvider provider3 = addTestProvider(TEST_FQDN + 2, TEST_FRIENDLY_NAME,
- TEST_PACKAGE);
+ TEST_PACKAGE, false);
WifiConfiguration wifiConfiguration3 = new WifiConfiguration();
wifiConfiguration3.FQDN = TEST_FQDN + 2;
lenient().when(provider1.getWifiConfig()).thenReturn(wifiConfiguration1);
@@ -1114,9 +1120,9 @@ public class PasspointManagerTest {
*/
@Test
public void getMatchingPasspointConfigsForOsuProvidersWithMatch() {
- PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider1 = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, true);
PasspointProvider provider2 = addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2,
- TEST_PACKAGE);
+ TEST_PACKAGE, true);
List<OsuProvider> osuProviders = new ArrayList<>();
Map<String, String> friendlyNames = new HashMap<>();
@@ -1143,8 +1149,8 @@ public class PasspointManagerTest {
*/
@Test
public void getMatchingPasspointConfigsForOsuProvidersWitNoMatch() {
- addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
- addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE);
+ addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
+ addTestProvider(TEST_FQDN2, TEST_FRIENDLY_NAME2, TEST_PACKAGE, false);
List<OsuProvider> osuProviders = new ArrayList<>();
@@ -1444,7 +1450,7 @@ public class PasspointManagerTest {
*/
@Test
public void providerNetworkConnectedFirstTime() throws Exception {
- PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
when(provider.getHasEverConnected()).thenReturn(false);
mManager.onPasspointNetworkConnected(TEST_FQDN);
verify(provider).setHasEverConnected(eq(true));
@@ -1459,7 +1465,7 @@ public class PasspointManagerTest {
*/
@Test
public void providerNetworkConnectedNotFirstTime() throws Exception {
- PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
when(provider.getHasEverConnected()).thenReturn(true);
mManager.onPasspointNetworkConnected(TEST_FQDN);
verify(provider, never()).setHasEverConnected(anyBoolean());
@@ -1473,7 +1479,7 @@ public class PasspointManagerTest {
*/
@Test
public void updateMetrics() {
- PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
ArgumentCaptor<Map<String, PasspointProvider>> argCaptor = ArgumentCaptor.forClass(
Map.class);
// Provider have not provided a successful network connection.
@@ -1601,7 +1607,7 @@ public class PasspointManagerTest {
*/
@Test
public void verifyHasProviderForCarrierWithNoMatch() {
- addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
assertFalse(mManager.hasCarrierProvider(TEST_MCC_MNC));
}
@@ -1688,7 +1694,7 @@ public class PasspointManagerTest {
WifiConfiguration currentConfiguration = WifiConfigurationTestUtil.createPasspointNetwork();
currentConfiguration.FQDN = TEST_FQDN;
when(mClientModeImpl.getCurrentWifiConfiguration()).thenReturn(currentConfiguration);
- addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE);
+ addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME, TEST_PACKAGE, false);
verify(mAppOpsManager).startWatchingMode(eq(OPSTR_CHANGE_WIFI_STATE), eq(TEST_PACKAGE),
mAppOpChangedListenerCaptor.capture());

View File

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Thu, 1 Jun 2023 13:44:28 -0700
Subject: [PATCH] Ensure that SecureNFC setting cannot be bypassed
Bug: 268038643
Test: ctsverifier
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d6d8f79fd8d605b3cb460895a8e3a11bcf0c22b0)
Merged-In: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
Change-Id: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
---
src/com/android/nfc/NfcService.java | 6 ++++++
src/com/android/nfc/cardemulation/HostEmulationManager.java | 5 +++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 46a5d88e..0e02cd03 100644
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -851,6 +851,12 @@ public class NfcService implements DeviceHostListener {
}
}
+ public boolean isSecureNfcEnabled() {
+ synchronized (NfcService.this) {
+ return mIsSecureNfcEnabled;
+ }
+ }
+
final class NfcAdapterService extends INfcAdapter.Stub {
/**
* An interface for vendor specific extensions
diff --git a/src/com/android/nfc/cardemulation/HostEmulationManager.java b/src/com/android/nfc/cardemulation/HostEmulationManager.java
index df701f2f..a45c5f50 100644
--- a/src/com/android/nfc/cardemulation/HostEmulationManager.java
+++ b/src/com/android/nfc/cardemulation/HostEmulationManager.java
@@ -175,8 +175,9 @@ public class HostEmulationManager {
// Resolve to default
// Check if resolvedService requires unlock
ApduServiceInfo defaultServiceInfo = resolveInfo.defaultService;
- if (defaultServiceInfo.requiresUnlock() &&
- mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
+ if ((defaultServiceInfo.requiresUnlock()
+ || NfcService.getInstance().isSecureNfcEnabled())
+ && mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
// Just ignore all future APDUs until next tap
mState = STATE_W4_DEACTIVATE;
launchTapAgain(resolveInfo.defaultService, resolveInfo.category);

View File

@ -1,209 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Taran Singh <tarandeep@google.com>
Date: Fri, 19 May 2023 23:17:47 +0000
Subject: [PATCH] DO NOT MERGE: Prevent non-system IME from becoming device
admin
Currently selected IME can inject KeyEvent on DeviceAdminAdd screen to
activate itself as device admin and cause various DoS attacks.
This CL ensures KeyEvent on "Activate" button can only come from system
apps.
Bug: 280793427
Test: atest DeviceAdminActivationTest
(cherry picked from commit 70a501d02e0a6aefd874767a15378ba998759373)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0ee3b96e59f3e5699c919af3642130fb33cd263b)
Merged-In: I6470d1684d707f4b1e86f8b456be0b4e0af5f188
Change-Id: I6470d1684d707f4b1e86f8b456be0b4e0af5f188
---
.../deviceadmin/DeviceAdminAdd.java | 120 ++++++++++--------
1 file changed, 64 insertions(+), 56 deletions(-)
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
index 786efd1ef4..56ba17ccc6 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
@@ -50,6 +50,8 @@ import android.text.method.ScrollingMovementMethod;
import android.util.EventLog;
import android.util.Log;
import android.view.Display;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -138,7 +140,7 @@ public class DeviceAdminAdd extends Activity {
mAppOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
PackageManager packageManager = getPackageManager();
- if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
finish();
return;
@@ -148,7 +150,7 @@ public class DeviceAdminAdd extends Activity {
EXTRA_CALLED_FROM_SUPPORT_DIALOG, false);
String action = getIntent().getAction();
- ComponentName who = (ComponentName)getIntent().getParcelableExtra(
+ ComponentName who = (ComponentName) getIntent().getParcelableExtra(
DevicePolicyManager.EXTRA_DEVICE_ADMIN);
if (who == null) {
String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
@@ -206,7 +208,7 @@ public class DeviceAdminAdd extends Activity {
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
int count = avail == null ? 0 : avail.size();
boolean found = false;
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
ResolveInfo ri = avail.get(i);
if (ai.packageName.equals(ri.activityInfo.packageName)
&& ai.name.equals(ri.activityInfo.name)) {
@@ -337,12 +339,12 @@ public class DeviceAdminAdd extends Activity {
}
setContentView(R.layout.device_admin_add);
- mAdminIcon = (ImageView)findViewById(R.id.admin_icon);
- mAdminName = (TextView)findViewById(R.id.admin_name);
- mAdminDescription = (TextView)findViewById(R.id.admin_description);
+ mAdminIcon = (ImageView) findViewById(R.id.admin_icon);
+ mAdminName = (TextView) findViewById(R.id.admin_name);
+ mAdminDescription = (TextView) findViewById(R.id.admin_description);
mProfileOwnerWarning = (TextView) findViewById(R.id.profile_owner_warning);
- mAddMsg = (TextView)findViewById(R.id.add_msg);
+ mAddMsg = (TextView) findViewById(R.id.add_msg);
mAddMsgExpander = (ImageView) findViewById(R.id.add_msg_expander);
final View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
@@ -365,7 +367,7 @@ public class DeviceAdminAdd extends Activity {
mAddMsgExpander.setVisibility(hideMsgExpander ? View.GONE : View.VISIBLE);
if (hideMsgExpander) {
mAddMsg.setOnClickListener(null);
- ((View)mAddMsgExpander.getParent()).invalidate();
+ ((View) mAddMsgExpander.getParent()).invalidate();
}
mAddMsg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
@@ -383,7 +385,7 @@ public class DeviceAdminAdd extends Activity {
mCancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER,
- mDeviceAdmin.getActivityInfo().applicationInfo.uid);
+ mDeviceAdmin.getActivityInfo().applicationInfo.uid);
finish();
}
});
@@ -403,58 +405,64 @@ public class DeviceAdminAdd extends Activity {
final View restrictedAction = findViewById(R.id.restricted_action);
restrictedAction.setFilterTouchesWhenObscured(true);
- restrictedAction.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (!mActionButton.isEnabled()) {
- showPolicyTransparencyDialogIfRequired();
- return;
- }
- if (mAdding) {
- addAndFinish();
- } else if (isManagedProfile(mDeviceAdmin)
- && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
- final int userId = UserHandle.myUserId();
- UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- UserManager um = UserManager.get(DeviceAdminAdd.this);
- um.removeUser(userId);
- finish();
- }
+
+ final View.OnClickListener restrictedActionClickListener = v -> {
+ if (!mActionButton.isEnabled()) {
+ showPolicyTransparencyDialogIfRequired();
+ return;
+ }
+ if (mAdding) {
+ addAndFinish();
+ } else if (isManagedProfile(mDeviceAdmin)
+ && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
+ final int userId = UserHandle.myUserId();
+ UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ UserManager um = UserManager.get(DeviceAdminAdd.this);
+ um.removeUser(userId);
+ finish();
}
- ).show();
- } else if (mUninstalling) {
- mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
- finish();
- } else if (!mWaitingForRemoveMsg) {
- try {
- // Don't allow the admin to put a dialog up in front
- // of us while we interact with the user.
- ActivityManager.getService().stopAppSwitches();
- } catch (RemoteException e) {
- }
- mWaitingForRemoveMsg = true;
- mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
- new RemoteCallback(new RemoteCallback.OnResultListener() {
- @Override
- public void onResult(Bundle result) {
- CharSequence msg = result != null
- ? result.getCharSequence(
- DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
- : null;
- continueRemoveAction(msg);
- }
- }, mHandler));
- // Don't want to wait too long.
- getWindow().getDecorView().getHandler().postDelayed(new Runnable() {
- @Override public void run() {
- continueRemoveAction(null);
}
- }, 2*1000);
+ ).show();
+ } else if (mUninstalling) {
+ mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
+ finish();
+ } else if (!mWaitingForRemoveMsg) {
+ try {
+ // Don't allow the admin to put a dialog up in front
+ // of us while we interact with the user.
+ ActivityManager.getService().stopAppSwitches();
+ } catch (RemoteException e) {
}
+ mWaitingForRemoveMsg = true;
+ mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
+ new RemoteCallback(new RemoteCallback.OnResultListener() {
+ @Override
+ public void onResult(Bundle result) {
+ CharSequence msg = result != null
+ ? result.getCharSequence(
+ DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
+ : null;
+ continueRemoveAction(msg);
+ }
+ }, mHandler));
+ // Don't want to wait too long.
+ getWindow().getDecorView().getHandler().postDelayed(
+ () -> continueRemoveAction(null), 2 * 1000);
+ }
+ };
+ restrictedAction.setOnKeyListener((view, keyCode, keyEvent) -> {
+ if ((keyEvent.getFlags() & KeyEvent.FLAG_FROM_SYSTEM) == 0) {
+ Log.e(TAG, "Can not activate device-admin with KeyEvent from non-system app.");
+ // Consume event to suppress click.
+ return true;
}
+ // Fallback to view click handler.
+ return false;
});
+ restrictedAction.setOnClickListener(restrictedActionClickListener);
}
/**

View File

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pinyao Ting <pinyaoting@google.com>
Date: Thu, 1 Jun 2023 18:12:44 -0700
Subject: [PATCH] Fix permission issue in legacy shortcut
When building legacy shortcut, Launcher calls
PackageManager#resolveActivity to retrieve necessary permission to
launch the intent.
However, when the source app wraps an arbitrary intent within
Intent#createChooser, the existing logic will fail because launching
Chooser doesn't require additional permission.
This CL fixes the security vulnerability by performing the permission
check against the intent that is wrapped within.
Bug: 270152142
Test: manual
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c53818a16b4322a823497726ac7e7a44501b4442)
Merged-In: If35344c08975e35085c7c2b9b814a3c457a144b0
Change-Id: If35344c08975e35085c7c2b9b814a3c457a144b0
---
.../android/launcher3/util/PackageManagerHelper.java | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 78d1d3ca8f..f263331f8f 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -112,6 +112,18 @@ public class PackageManagerHelper {
* any permissions
*/
public boolean hasPermissionForActivity(Intent intent, String srcPackage) {
+ // b/270152142
+ if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
+ final Bundle extras = intent.getExtras();
+ if (extras == null) {
+ return true;
+ }
+ // If given intent is ACTION_CHOOSER, verify srcPackage has permission over EXTRA_INTENT
+ intent = (Intent) extras.getParcelable(Intent.EXTRA_INTENT);
+ if (intent == null) {
+ return true;
+ }
+ }
ResolveInfo target = mPm.resolveActivity(intent, 0);
if (target == null) {
// Not a valid target

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aishwarya Mallampati <amallampati@google.com>
Date: Wed, 10 May 2023 21:54:43 +0000
Subject: [PATCH] Update file permissions using canonical path
Bug: 264880895
Bug: 264880689
Test: atest android.telephonyprovider.cts.MmsPartTest
atest CtsTelephonyTestCases
Sanity check - sending and receiving sms and mms manually
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6743638a096c32627f398efd2ea78f08b8a2db8c)
Merged-In: I8dd888ea31ec07c9f0de38eb8e8170d3ed255686
Change-Id: I8dd888ea31ec07c9f0de38eb8e8170d3ed255686
---
src/com/android/providers/telephony/MmsProvider.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index 6ba775ba..7546c246 100644
--- a/src/com/android/providers/telephony/MmsProvider.java
+++ b/src/com/android/providers/telephony/MmsProvider.java
@@ -819,15 +819,16 @@ public class MmsProvider extends ContentProvider {
String path = getContext().getDir(PARTS_DIR_NAME, 0).getPath() + '/' +
uri.getPathSegments().get(1);
try {
+ File canonicalFile = new File(path).getCanonicalFile();
String partsDirPath = getContext().getDir(PARTS_DIR_NAME, 0).getCanonicalPath();
- if (!new File(path).getCanonicalPath().startsWith(partsDirPath)) {
+ if (!canonicalFile.getPath().startsWith(partsDirPath + '/')) {
EventLog.writeEvent(0x534e4554, "240685104",
Binder.getCallingUid(), (TAG + " update: path " + path +
" does not start with " + partsDirPath));
return 0;
}
// Reset the file permission back to read for everyone but me.
- Os.chmod(path, 0644);
+ Os.chmod(canonicalFile.getPath(), 0644);
if (LOCAL_LOGV) {
Log.d(TAG, "MmsProvider.update chmod is successful for path: " + path);
}

View File

@ -1,714 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pranav Madapurmath <pmadapurmath@google.com>
Date: Thu, 25 May 2023 20:49:21 +0000
Subject: [PATCH] Resolve StatusHints image exploit across user.
Because of the INTERACT_ACROSS_USERS permission, an app that implements
a ConnectionService can upload an image icon belonging to another user
by setting it in the StatusHints. Validating the construction of the
StatusHints on the calling user would prevent a malicious app from
registering a connection service with the embedded image icon from a
different user.
From additional feedback, this CL also addresses potential
vulnerabilities in an app being able to directly invoke the binder for a
means to manipulate the contents of the bundle that are passed with it.
The targeted points of entry are in ConnectionServiceWrapper for the
following APIs: handleCreateConnectionComplete, setStatusHints,
addConferenceCall, and addExistingConnection.
Fixes: 280797684
Test: Manual (verified that original exploit is no longer an issue).
Test: Unit test for validating image in StatusHints constructor.
Test: Unit tests to address vulnerabilities via the binder.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:49d19dd265bee669b230efa29bf98c83650efea6)
Merged-In: Ie1f6a8866d31d5f1099dd0630cf8e9ee782d389c
Change-Id: Ie1f6a8866d31d5f1099dd0630cf8e9ee782d389c
---
.../telecom/ConnectionServiceWrapper.java | 32 ++++
.../server/telecom/tests/BasicCallTests.java | 164 +++++++++++++++++-
.../server/telecom/tests/CallExtrasTest.java | 6 +-
.../tests/ConnectionServiceFixture.java | 21 ++-
.../telecom/tests/TelecomSystemTest.java | 66 ++++---
.../server/telecom/tests/VideoCallTests.java | 16 +-
6 files changed, 265 insertions(+), 40 deletions(-)
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 4621558d1..d06460784 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -19,6 +19,7 @@ package com.android.server.telecom;
import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -73,10 +74,17 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
ParcelableConnection connection, Session.Info sessionInfo) {
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("handleCreateConnectionComplete %s", callId);
+ // Check status hints image for cross user access
+ if (connection.getStatusHints() != null) {
+ Icon icon = connection.getStatusHints().getIcon();
+ connection.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, callingUserHandle));
+ }
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection);
@@ -435,6 +443,15 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
public void addConferenceCall(String callId, ParcelableConference parcelableConference,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL);
+
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
+ // Check status hints image for cross user access
+ if (parcelableConference.getStatusHints() != null) {
+ Icon icon = parcelableConference.getStatusHints().getIcon();
+ parcelableConference.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, callingUserHandle));
+ }
+
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -658,10 +675,17 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
public void setStatusHints(String callId, StatusHints statusHints,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, "CSW.sSH");
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("setStatusHints %s %s", callId, statusHints);
+ // Check status hints image for cross user access
+ if (statusHints != null) {
+ Icon icon = statusHints.getIcon();
+ statusHints.setIcon(StatusHints.validateAccountIconUserBoundary(
+ icon, callingUserHandle));
+ }
Call call = mCallIdMapper.getCall(callId);
if (call != null) {
call.setStatusHints(statusHints);
@@ -849,6 +873,14 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
} else {
connectIdToCheck = callId;
}
+
+ // Check status hints image for cross user access
+ if (connection.getStatusHints() != null) {
+ Icon icon = connection.getStatusHints().getIcon();
+ connection.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, userHandle));
+ }
+
// Check to see if this Connection has already been added.
Call alreadyAddedConnection = mCallsManager
.getAlreadyAddedConnection(connectIdToCheck);
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 95ca3f3be..7889d0487 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -16,8 +16,11 @@
package com.android.server.telecom.tests;
+import static com.android.server.telecom.tests.ConnectionServiceFixture.STATUS_HINTS_EXTRA;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.nullable;
@@ -35,6 +38,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.IContentProvider;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
@@ -51,12 +56,14 @@ import android.telecom.Log;
import android.telecom.ParcelableCall;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
import com.android.internal.telecom.IInCallAdapter;
import com.android.internal.telephony.CallerInfo;
@@ -180,7 +187,7 @@ public class BasicCallTests extends TelecomSystemTest {
@Test
public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -209,7 +216,7 @@ public class BasicCallTests extends TelecomSystemTest {
@Test
public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -237,7 +244,7 @@ public class BasicCallTests extends TelecomSystemTest {
@Test
public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -642,13 +649,13 @@ public class BasicCallTests extends TelecomSystemTest {
@MediumTest
@Test
public void testBasicConferenceCall() throws Exception {
- makeConferenceCall();
+ makeConferenceCall(null, null);
}
@MediumTest
@Test
public void testAddCallToConference1() throws Exception {
- ParcelableCall conferenceCall = makeConferenceCall();
+ ParcelableCall conferenceCall = makeConferenceCall(null, null);
IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
// testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
@@ -666,7 +673,7 @@ public class BasicCallTests extends TelecomSystemTest {
@MediumTest
@Test
public void testAddCallToConference2() throws Exception {
- ParcelableCall conferenceCall = makeConferenceCall();
+ ParcelableCall conferenceCall = makeConferenceCall(null, null);
IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
mInCallServiceFixtureX.getInCallAdapter()
@@ -922,7 +929,7 @@ public class BasicCallTests extends TelecomSystemTest {
public void testOutgoingCallSelectPhoneAccountVideo() throws Exception {
startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
null, mConnectionServiceFixtureA,
- Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
+ Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
assert(call.isVideoCallingSupportedByPhoneAccount());
@@ -945,7 +952,7 @@ public class BasicCallTests extends TelecomSystemTest {
public void testOutgoingCallSelectPhoneAccountNoVideo() throws Exception {
startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
null, mConnectionServiceFixtureA,
- Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
+ Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
assert(call.isVideoCallingSupportedByPhoneAccount());
@@ -1153,4 +1160,145 @@ public class BasicCallTests extends TelecomSystemTest {
assertTrue(muteValues.get(0));
assertFalse(muteValues.get(1));
}
+
+ /**
+ * Verifies that StatusHints image is validated in ConnectionServiceWrapper#addConferenceCall
+ * when the image doesn't belong to the calling user. Simulates a scenario where an app
+ * could manipulate the contents of the bundle and send it via the binder to upload an image
+ * from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_addConferenceCall() throws Exception {
+ Intent callIntent1 = new Intent();
+ // Stub intent for call2
+ Intent callIntent2 = new Intent();
+ Bundle callExtras1 = new Bundle();
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ // Load StatusHints extra into TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS to be processed
+ // as the call extras. This will be leveraged in ConnectionServiceFixture to set the
+ // StatusHints for the given connection.
+ StatusHints statusHints = new StatusHints(icon);
+ assertNotNull(statusHints.getIcon());
+ callExtras1.putParcelable(STATUS_HINTS_EXTRA, statusHints);
+ callIntent1.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras1);
+
+ // Start conference call to invoke ConnectionServiceWrapper#addConferenceCall.
+ // Note that the calling user would be User 0.
+ ParcelableCall conferenceCall = makeConferenceCall(callIntent1, callIntent2);
+
+ // Ensure that StatusHints was set.
+ assertNotNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
+ .getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId)
+ .getStatusHints().getIcon());
+ }
+
+ /**
+ * Verifies that StatusHints image is validated in
+ * ConnectionServiceWrapper#handleCreateConnectionComplete when the image doesn't belong to the
+ * calling user. Simulates a scenario where an app could manipulate the contents of the
+ * bundle and send it via the binder to upload an image from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_handleCreateConnectionComplete() throws Exception {
+ Bundle extras = new Bundle();
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ // Load the bundle with the test extra in order to simulate an app directly invoking the
+ // binder on ConnectionServiceWrapper#handleCreateConnectionComplete.
+ StatusHints statusHints = new StatusHints(icon);
+ assertNotNull(statusHints.getIcon());
+ extras.putParcelable(STATUS_HINTS_EXTRA, statusHints);
+
+ // Start incoming call with StatusHints extras
+ // Note that the calling user in ConnectionServiceWrapper#handleCreateConnectionComplete
+ // would be User 0.
+ IdPair ids = startIncomingPhoneCallWithExtras("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, extras);
+
+ // Ensure that StatusHints was set.
+ assertNotNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints().getIcon());
+ }
+
+ /**
+ * Verifies that StatusHints image is validated in ConnectionServiceWrapper#setStatusHints
+ * when the image doesn't belong to the calling user. Simulates a scenario where an app
+ * could manipulate the contents of the bundle and send it via the binder to upload an image
+ * from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_setStatusHints() throws Exception {
+ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+ // Modify existing connection with StatusHints image exploit
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ StatusHints statusHints = new StatusHints(icon);
+ assertNotNull(statusHints.getIcon());
+ ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
+ .mConnectionById.get(outgoing.mConnectionId);
+ connectionInfo.statusHints = statusHints;
+
+ // Invoke ConnectionServiceWrapper#setStatusHints.
+ // Note that the calling user would be User 0.
+ mConnectionServiceFixtureA.sendSetStatusHints(outgoing.mConnectionId);
+ waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
+ TEST_TIMEOUT);
+
+ // Ensure that StatusHints was set.
+ assertNotNull(mInCallServiceFixtureX.getCall(outgoing.mCallId).getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mInCallServiceFixtureX.getCall(outgoing.mCallId)
+ .getStatusHints().getIcon());
+ }
+
+ /**
+ * Verifies that StatusHints image is validated in
+ * ConnectionServiceWrapper#addExistingConnection when the image doesn't belong to the calling
+ * user. Simulates a scenario where an app could manipulate the contents of the bundle and
+ * send it via the binder to upload an image from another user.
+ *
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testValidateStatusHintsImage_addExistingConnection() throws Exception {
+ IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ Connection existingConnection = mConnectionServiceFixtureA.mLatestConnection;
+
+ // Modify existing connection with StatusHints image exploit
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ StatusHints modifiedStatusHints = new StatusHints(icon);
+ assertNotNull(modifiedStatusHints.getIcon());
+ ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA
+ .mConnectionById.get(outgoing.mConnectionId);
+ connectionInfo.statusHints = modifiedStatusHints;
+
+ // Invoke ConnectionServiceWrapper#addExistingConnection.
+ // Note that the calling user would be User 0.
+ mConnectionServiceFixtureA.sendAddExistingConnection(outgoing.mConnectionId);
+ waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
+ TEST_TIMEOUT);
+
+ // Ensure that StatusHints was set. Due to test setup, the ParcelableConnection object that
+ // is passed into sendAddExistingConnection is instantiated on invocation. The call's
+ // StatusHints are not updated at the time of completion, so instead, we can verify that
+ // the ParcelableConnection object was modified.
+ assertNotNull(mConnectionServiceFixtureA.mLatestParcelableConnection.getStatusHints());
+ // Ensure that the StatusHints image icon was disregarded.
+ assertNull(mConnectionServiceFixtureA.mLatestParcelableConnection
+ .getStatusHints().getIcon());
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
index b97f819e1..28986c374 100644
--- a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
@@ -359,7 +359,7 @@ public class CallExtrasTest extends TelecomSystemTest {
@LargeTest
@Test
public void testConferenceSetExtras() throws Exception {
- ParcelableCall call = makeConferenceCall();
+ ParcelableCall call = makeConferenceCall(null, null);
String conferenceId = call.getId();
Conference conference = mConnectionServiceFixtureA.mLatestConference;
@@ -403,7 +403,7 @@ public class CallExtrasTest extends TelecomSystemTest {
@FlakyTest(bugId = 117751305)
@Test
public void testConferenceExtraOperations() throws Exception {
- ParcelableCall call = makeConferenceCall();
+ ParcelableCall call = makeConferenceCall(null, null);
String conferenceId = call.getId();
Conference conference = mConnectionServiceFixtureA.mLatestConference;
assertNotNull(conference);
@@ -439,7 +439,7 @@ public class CallExtrasTest extends TelecomSystemTest {
@LargeTest
@Test
public void testConferenceICS() throws Exception {
- ParcelableCall call = makeConferenceCall();
+ ParcelableCall call = makeConferenceCall(null, null);
String conferenceId = call.getId();
Conference conference = mConnectionServiceFixtureA.mLatestConference;
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 9655476b4..c3561b64e 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -67,6 +67,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
static int INVALID_VIDEO_STATE = -1;
public CountDownLatch mExtrasLock = new CountDownLatch(1);
static int NOT_SPECIFIED = 0;
+ public static final String STATUS_HINTS_EXTRA = "updateStatusHints";
/**
* Implementation of ConnectionService that performs no-ops for tasks normally meant for
@@ -101,6 +102,11 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
if (mProperties != NOT_SPECIFIED) {
fakeConnection.setConnectionProperties(mProperties);
}
+ // Testing for StatusHints image icon cross user access
+ if (request.getExtras() != null) {
+ fakeConnection.setStatusHints(
+ request.getExtras().getParcelable(STATUS_HINTS_EXTRA));
+ }
return fakeConnection;
}
@@ -117,6 +123,11 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
if (mProperties != NOT_SPECIFIED) {
fakeConnection.setConnectionProperties(mProperties);
}
+ // Testing for StatusHints image icon cross user access
+ if (request.getExtras() != null) {
+ fakeConnection.setStatusHints(
+ request.getExtras().getParcelable(STATUS_HINTS_EXTRA));
+ }
return fakeConnection;
}
@@ -133,6 +144,12 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
Conference fakeConference = new FakeConference();
fakeConference.addConnection(cxn1);
fakeConference.addConnection(cxn2);
+ if (cxn1.getStatusHints() != null || cxn2.getStatusHints() != null) {
+ // For testing purposes, pick one of the status hints that isn't null.
+ StatusHints statusHints = cxn1.getStatusHints() != null
+ ? cxn1.getStatusHints() : cxn2.getStatusHints();
+ fakeConference.setStatusHints(statusHints);
+ }
mLatestConference = fakeConference;
addConference(fakeConference);
} else {
@@ -440,6 +457,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
public String mLatestConnectionId;
public Connection mLatestConnection;
+ public ParcelableConnection mLatestParcelableConnection;
public Conference mLatestConference;
public final Set<IConnectionServiceAdapter> mConnectionServiceAdapters = new HashSet<>();
public final Map<String, ConnectionInfo> mConnectionById = new HashMap<>();
@@ -678,7 +696,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
}
private ParcelableConnection parcelable(ConnectionInfo c) {
- return new ParcelableConnection(
+ mLatestParcelableConnection = new ParcelableConnection(
c.request.getAccountHandle(),
c.state,
c.capabilities,
@@ -698,5 +716,6 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
c.disconnectCause,
c.conferenceableConnectionIds,
c.extras);
+ return mLatestParcelableConnection;
}
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 82b17be42..717579046 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -382,12 +382,13 @@ public class TelecomSystemTest extends TelecomTestCase {
super.tearDown();
}
- protected ParcelableCall makeConferenceCall() throws Exception {
- IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212",
- mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ protected ParcelableCall makeConferenceCall(
+ Intent callIntentExtras1, Intent callIntentExtras2) throws Exception {
+ IdPair callId1 = startAndMakeActiveOutgoingCallWithExtras("650-555-1212",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras1);
- IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213",
- mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ IdPair callId2 = startAndMakeActiveOutgoingCallWithExtras("650-555-1213",
+ mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras2);
IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
@@ -570,7 +571,7 @@ public class TelecomSystemTest extends TelecomTestCase {
startOutgoingPhoneCallWaitForBroadcaster(number, null,
connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY,
- false /*isEmergency*/);
+ false /*isEmergency*/, null);
return mInCallServiceFixtureX.mLatestCallId;
}
@@ -600,17 +601,17 @@ public class TelecomSystemTest extends TelecomTestCase {
throws Exception {
return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
- initiatingUser, VideoProfile.STATE_AUDIO_ONLY);
+ initiatingUser, VideoProfile.STATE_AUDIO_ONLY, null);
}
protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
- int videoState) throws Exception {
+ int videoState, Intent callIntentExtras) throws Exception {
int startingNumConnections = connectionServiceFixture.mConnectionById.size();
int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
startOutgoingPhoneCallPendingCreateConnection(number, phoneAccountHandle,
- connectionServiceFixture, initiatingUser, videoState);
+ connectionServiceFixture, initiatingUser, videoState, callIntentExtras);
verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
.createConnectionComplete(anyString(), any());
@@ -649,7 +650,7 @@ public class TelecomSystemTest extends TelecomTestCase {
mIsEmergencyCall = true;
// Call will not use the ordered broadcaster, since it is an Emergency Call
startOutgoingPhoneCallWaitForBroadcaster(number, phoneAccountHandle,
- connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/);
+ connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/, null);
return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
phoneAccountHandle, connectionServiceFixture);
@@ -658,7 +659,7 @@ public class TelecomSystemTest extends TelecomTestCase {
protected void startOutgoingPhoneCallWaitForBroadcaster(String number,
PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
- int videoState, boolean isEmergency) throws Exception {
+ int videoState, boolean isEmergency, Intent actionCallIntent) throws Exception {
reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
mInCallServiceFixtureY.getTestDouble());
@@ -671,7 +672,9 @@ public class TelecomSystemTest extends TelecomTestCase {
boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
- Intent actionCallIntent = new Intent();
+ if (actionCallIntent == null) {
+ actionCallIntent = new Intent();
+ }
actionCallIntent.setData(Uri.parse("tel:" + number));
actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
if(isEmergency) {
@@ -716,9 +719,10 @@ public class TelecomSystemTest extends TelecomTestCase {
protected String startOutgoingPhoneCallPendingCreateConnection(String number,
PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
- int videoState) throws Exception {
+ int videoState, Intent callIntentExtras) throws Exception {
startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle,
- connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/);
+ connectionServiceFixture, initiatingUser,
+ videoState, false /*isEmergency*/, callIntentExtras);
waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
verifyAndProcessOutgoingCallBroadcast(phoneAccountHandle);
@@ -823,14 +827,24 @@ public class TelecomSystemTest extends TelecomTestCase {
PhoneAccountHandle phoneAccountHandle,
final ConnectionServiceFixture connectionServiceFixture) throws Exception {
return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
- connectionServiceFixture);
+ connectionServiceFixture, null);
+ }
+
+ protected IdPair startIncomingPhoneCallWithExtras(
+ String number,
+ PhoneAccountHandle phoneAccountHandle,
+ final ConnectionServiceFixture connectionServiceFixture,
+ Bundle extras) throws Exception {
+ return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
+ connectionServiceFixture, extras);
}
protected IdPair startIncomingPhoneCall(
String number,
PhoneAccountHandle phoneAccountHandle,
int videoState,
- final ConnectionServiceFixture connectionServiceFixture) throws Exception {
+ final ConnectionServiceFixture connectionServiceFixture,
+ Bundle extras) throws Exception {
reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
mInCallServiceFixtureY.getTestDouble());
@@ -847,7 +861,9 @@ public class TelecomSystemTest extends TelecomTestCase {
new IncomingCallAddedListener(incomingCallAddedLatch);
mTelecomSystem.getCallsManager().addListener(callAddedListener);
- Bundle extras = new Bundle();
+ if (extras == null) {
+ extras = new Bundle();
+ }
extras.putParcelable(
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null));
@@ -933,7 +949,16 @@ public class TelecomSystemTest extends TelecomTestCase {
PhoneAccountHandle phoneAccountHandle,
ConnectionServiceFixture connectionServiceFixture) throws Exception {
return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
- VideoProfile.STATE_AUDIO_ONLY);
+ VideoProfile.STATE_AUDIO_ONLY, null);
+ }
+
+ protected IdPair startAndMakeActiveOutgoingCallWithExtras(
+ String number,
+ PhoneAccountHandle phoneAccountHandle,
+ ConnectionServiceFixture connectionServiceFixture,
+ Intent callIntentExtras) throws Exception {
+ return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
+ VideoProfile.STATE_AUDIO_ONLY, callIntentExtras);
}
// A simple outgoing call, verifying that the appropriate connection service is contacted,
@@ -941,9 +966,10 @@ public class TelecomSystemTest extends TelecomTestCase {
protected IdPair startAndMakeActiveOutgoingCall(
String number,
PhoneAccountHandle phoneAccountHandle,
- ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception {
+ ConnectionServiceFixture connectionServiceFixture, int videoState,
+ Intent callIntentExtras) throws Exception {
IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
- Process.myUserHandle(), videoState);
+ Process.myUserHandle(), videoState, callIntentExtras);
connectionServiceFixture.sendSetDialing(ids.mConnectionId);
if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
index 97e71d18b..84beedc0f 100644
--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -105,7 +105,7 @@ public class VideoCallTests extends TelecomSystemTest {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
verifyAudioRoute(CallAudioState.ROUTE_SPEAKER);
}
@@ -121,7 +121,7 @@ public class VideoCallTests extends TelecomSystemTest {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
- VideoProfile.STATE_TX_ENABLED);
+ VideoProfile.STATE_TX_ENABLED, null);
verifyAudioRoute(CallAudioState.ROUTE_SPEAKER);
}
@@ -137,7 +137,7 @@ public class VideoCallTests extends TelecomSystemTest {
// Start an incoming video call.
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
- VideoProfile.STATE_AUDIO_ONLY);
+ VideoProfile.STATE_AUDIO_ONLY, null);
verifyAudioRoute(CallAudioState.ROUTE_EARPIECE);
}
@@ -165,7 +165,7 @@ public class VideoCallTests extends TelecomSystemTest {
@Test
public void testIncomingVideoCallMissedCheckVideoHistory() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -182,7 +182,7 @@ public class VideoCallTests extends TelecomSystemTest {
@Test
public void testIncomingVideoCallRejectedCheckVideoHistory() throws Exception {
IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
- VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+ VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -201,7 +201,7 @@ public class VideoCallTests extends TelecomSystemTest {
public void testOutgoingVideoCallCanceledCheckVideoHistory() throws Exception {
IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
mConnectionServiceFixtureA, Process.myUserHandle(),
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -219,7 +219,7 @@ public class VideoCallTests extends TelecomSystemTest {
public void testOutgoingVideoCallRejectedCheckVideoHistory() throws Exception {
IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
mConnectionServiceFixtureA, Process.myUserHandle(),
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();
@@ -237,7 +237,7 @@ public class VideoCallTests extends TelecomSystemTest {
public void testOutgoingVideoCallAnsweredAsAudio() throws Exception {
IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
mConnectionServiceFixtureA, Process.myUserHandle(),
- VideoProfile.STATE_BIDIRECTIONAL);
+ VideoProfile.STATE_BIDIRECTIONAL, null);
com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
.iterator().next();

View File

@ -1,132 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aishwarya Mallampati <amallampati@google.com>
Date: Fri, 28 Oct 2022 23:39:20 +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:213aba7e18ddadf800be981b802d8e242c61e0ad)
Merged-In: I6899de902e6e3ffda47b48d0ae806ac9c17ee2a6
Change-Id: I6899de902e6e3ffda47b48d0ae806ac9c17ee2a6
---
.../android/phone/PhoneInterfaceManager.java | 57 ++++++++++++++++---
1 file changed, 49 insertions(+), 8 deletions(-)
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index aad961f14..11b8909ac 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
import android.Manifest.permission;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -86,6 +87,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyScanManager;
+import android.telephony.UiccAccessRule;
import android.telephony.UiccCardInfo;
import android.telephony.UiccSlotInfo;
import android.telephony.UssdResponse;
@@ -4808,14 +4810,18 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
int uid = Binder.getCallingUid();
PackageManager pkgMgr = phone.getContext().getPackageManager();
String[] packages = pkgMgr.getPackagesForUid(uid);
+ if (packages == null) {
+ return privilegeFromSim;
+ }
final long identity = Binder.clearCallingIdentity();
try {
- SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
- SubscriptionManager subManager = (SubscriptionManager)
- phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ int subId = phone.getSubId();
+ SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
+ List<UiccAccessRule> carrierConfigAccessRules = subInfo.getCarrierConfigAccessRules();
+
for (String pkg : packages) {
- if (subManager.canManageSubscription(subInfo, pkg)) {
+ if (hasCarrierConfigAccess(pkg, pkgMgr, carrierConfigAccessRules)) {
return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
}
}
@@ -4834,16 +4840,51 @@ public class PhoneInterfaceManager extends ITelephony.Stub {
final long identity = Binder.clearCallingIdentity();
try {
- SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
- SubscriptionManager subManager = (SubscriptionManager)
- phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- return subManager.canManageSubscription(subInfo, pkgName)
+ int subId = phone.getSubId();
+ SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
+ List<UiccAccessRule> carrierConfigAccessRules = subInfo.getCarrierConfigAccessRules();
+
+ return hasCarrierConfigAccess(pkgName, phone.getContext().getPackageManager(),
+ carrierConfigAccessRules)
? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS : privilegeFromSim;
} finally {
Binder.restoreCallingIdentity(identity);
}
}
+ /**
+ * Check whether carrier privilege status can be granted to the provided app for this
+ * subscription based on the carrier config access rules of the subscription.
+ *
+ * @param packageName package name of the app to check
+ * @param packageManager package manager
+ * @param carrierConfigAccessRules carrier config access rules of the subscription
+ * @return true if the app is included in the mCarrierConfigAccessRules of this subscription.
+ */
+ private boolean hasCarrierConfigAccess(String packageName, PackageManager packageManager,
+ @NonNull List<UiccAccessRule> carrierConfigAccessRules) {
+ if ((packageName == null) || (carrierConfigAccessRules.isEmpty())) {
+ return false;
+ }
+
+ PackageInfo packageInfo;
+ try {
+ packageInfo = packageManager.getPackageInfo(packageName,
+ PackageManager.GET_SIGNING_CERTIFICATES);
+ } catch (PackageManager.NameNotFoundException e) {
+ logv("Unknown package: " + packageName);
+ return false;
+ }
+
+ for (UiccAccessRule rule : carrierConfigAccessRules) {
+ if (rule.getCarrierPrivilegeStatus(packageInfo)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public int getCarrierPrivilegeStatus(int subId) {
final Phone phone = getPhone(subId);

View File

@ -1,139 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ashish Kumar <akgaurav@google.com>
Date: Fri, 26 May 2023 14:18:46 +0000
Subject: [PATCH] RESTRICT AUTOMERGE Fixed leak of cross user data in multiple
settings.
- Any app is allowed to receive GET_CONTENT intent. Using this, an user puts back in the intent an uri with data of another user.
- Telephony service has INTERACT_ACROSS_USER permission. Using this, it reads and shows the deta to the evil user.
Fix: When telephony service gets the intent result, it checks if the uri is from the current user or not.
Bug: b/256591023 , b/256819787
Test: The malicious behaviour was not being reproduced. Unable to import contact from other users data.
Test2: Able to import contact from the primary user or uri with no user id
(These settings are not available for secondary users)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:36e10a6d0d7b9efc543f8004729fa85751f4f70d)
Merged-In: I1e3a643f17948153aecc1d0df9ffd9619ad678c1
Change-Id: I1e3a643f17948153aecc1d0df9ffd9619ad678c1
---
.../android/phone/GsmUmtsCallForwardOptions.java | 12 ++++++++++++
.../phone/settings/VoicemailSettingsActivity.java | 14 ++++++++++++++
.../phone/settings/fdn/EditFdnContactScreen.java | 13 +++++++++++++
3 files changed, 39 insertions(+)
diff --git a/src/com/android/phone/GsmUmtsCallForwardOptions.java b/src/com/android/phone/GsmUmtsCallForwardOptions.java
index b8ea8fd46..b353739f0 100644
--- a/src/com/android/phone/GsmUmtsCallForwardOptions.java
+++ b/src/com/android/phone/GsmUmtsCallForwardOptions.java
@@ -1,10 +1,13 @@
package com.android.phone;
import android.app.ActionBar;
+import android.content.ContentProvider;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.UserHandle;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.telephony.CarrierConfigManager;
@@ -184,6 +187,15 @@ public class GsmUmtsCallForwardOptions extends TimeConsumingPreferenceActivity {
}
Cursor cursor = null;
try {
+ // check if the URI returned by the user belongs to the user
+ final int currentUser = UserHandle.getUserId(Process.myUid());
+ if (currentUser
+ != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) {
+
+ Log.w(LOG_TAG, "onActivityResult: Contact data of different user, "
+ + "cannot access");
+ return;
+ }
cursor = getContentResolver().query(data.getData(),
NUM_PROJECTION, null, null, null);
if ((cursor == null) || (!cursor.moveToFirst())) {
diff --git a/src/com/android/phone/settings/VoicemailSettingsActivity.java b/src/com/android/phone/settings/VoicemailSettingsActivity.java
index 2efa81c1e..484834fbc 100644
--- a/src/com/android/phone/settings/VoicemailSettingsActivity.java
+++ b/src/com/android/phone/settings/VoicemailSettingsActivity.java
@@ -17,6 +17,7 @@
package com.android.phone.settings;
import android.app.Dialog;
+import android.content.ContentProvider;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
@@ -25,6 +26,8 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceActivity;
@@ -521,6 +524,17 @@ public class VoicemailSettingsActivity extends PreferenceActivity
Cursor cursor = null;
try {
+ // check if the URI returned by the user belongs to the user
+ final int currentUser = UserHandle.getUserId(Process.myUid());
+ if (currentUser
+ != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) {
+
+ if (DBG) {
+ log("onActivityResult: Contact data of different user, "
+ + "cannot access");
+ }
+ return;
+ }
cursor = getContentResolver().query(data.getData(),
new String[] { CommonDataKinds.Phone.NUMBER }, null, null, null);
if ((cursor == null) || (!cursor.moveToFirst())) {
diff --git a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
index c358e27c9..e68ab7e74 100644
--- a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
+++ b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
@@ -18,9 +18,12 @@ package com.android.phone.settings.fdn;
import static android.view.Window.PROGRESS_VISIBILITY_OFF;
import static android.view.Window.PROGRESS_VISIBILITY_ON;
+import static android.app.Activity.RESULT_OK;
+
import android.app.Activity;
import android.content.AsyncQueryHandler;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
@@ -29,6 +32,8 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Process;
+import android.os.UserHandle;
import android.provider.ContactsContract.CommonDataKinds;
import android.telephony.PhoneNumberUtils;
import android.text.Editable;
@@ -152,6 +157,14 @@ public class EditFdnContactScreen extends Activity {
}
Cursor cursor = null;
try {
+ // check if the URI returned by the user belongs to the user
+ final int currentUser = UserHandle.getUserId(Process.myUid());
+ if (currentUser
+ != ContentProvider.getUserIdFromUri(intent.getData(), currentUser)) {
+ Log.w(LOG_TAG, "onActivityResult: Contact data of different user, "
+ + "cannot access");
+ return;
+ }
cursor = getContentResolver().query(intent.getData(),
NUM_PROJECTION, null, null, null);
if ((cursor == null) || (!cursor.moveToFirst())) {

View File

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: tyiu <tyiu@google.com>
Date: Tue, 28 Mar 2023 18:40:51 +0000
Subject: [PATCH] Fix gatt_end_operation buffer overflow
Added boundary check for gatt_end_operation to prevent writing out of
boundary.
Since response of the GATT server is handled in
gatt_client_handle_server_rsp() and gatt_process_read_rsp(), the maximum
lenth that can be passed into the handlers is bounded by
GATT_MAX_MTU_SIZE, which is set to 517, which is greater than
GATT_MAX_ATTR_LEN which is set to 512. The fact that there is no spec
that gaurentees MTU response to be less than or equal to 512 bytes can
cause a buffer overflow when performing memcpy without length check.
Bug: 261068592
Test: No test since not affecting behavior
Tag: #security
Ignore-AOSP-First: security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dd7298e982e4bbf0138a490562679c9a4a755200)
Merged-In: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873
Change-Id: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873
---
stack/gatt/gatt_utils.cc | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc
index 2bd424000..013011778 100644
--- a/stack/gatt/gatt_utils.cc
+++ b/stack/gatt/gatt_utils.cc
@@ -1198,6 +1198,13 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) {
cb_data.att_value.handle = p_clcb->s_handle;
cb_data.att_value.len = p_clcb->counter;
+ if (cb_data.att_value.len > GATT_MAX_ATTR_LEN) {
+ LOG(WARNING) << __func__
+ << StringPrintf(" Large cb_data.att_value, size=%d",
+ cb_data.att_value.len);
+ cb_data.att_value.len = GATT_MAX_ATTR_LEN;
+ }
+
if (p_data && p_clcb->counter)
memcpy(cb_data.att_value.value, p_data, cb_data.att_value.len);
}

View File

@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hui Peng <phui@google.com>
Date: Tue, 16 May 2023 21:24:07 +0000
Subject: [PATCH] Fix an integer overflow bug in avdt_msg_asmbl
This is a backport of
Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
to rvc-dev
Bug: 280633699
Test: manual
Ignore-AOSP-First: security
Tag: #security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:26347d4bdba646bbba4d27337d2888a04de42639)
Merged-In: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
Change-Id: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
---
stack/avdt/avdt_msg.cc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index bf83d191e..3f8713c0b 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -1289,14 +1289,14 @@ BT_HDR* avdt_msg_asmbl(AvdtpCcb* p_ccb, BT_HDR* p_buf) {
* NOTE: The buffer is allocated above at the beginning of the
* reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
*/
- uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
+ size_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
/* adjust offset and len of fragment for header byte */
p_buf->offset += AVDT_LEN_TYPE_CONT;
p_buf->len -= AVDT_LEN_TYPE_CONT;
/* verify length */
- if ((p_ccb->p_rx_msg->offset + p_buf->len) > buf_len) {
+ if (((size_t) p_ccb->p_rx_msg->offset + (size_t) p_buf->len) > buf_len) {
/* won't fit; free everything */
AVDT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
osi_free_and_reset((void**)&p_ccb->p_rx_msg);

View File

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Fri, 19 May 2023 19:17:16 +0000
Subject: [PATCH] Fix integer overflow in build_read_multi_rsp
Local variables tracking structure size in build_read_multi_rsp are of
uint16 type but accept a full uint16 range from function arguments while
appending a fixed-length offset. This can lead to an integer overflow
and unexpected behavior.
Change the locals to size_t, and add a check during reasssignment.
Bug: 273966636
Test: atest bluetooth_test_gd_unit, net_test_stack_btm
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:53f64274cbf2268ad6db5af9c61ceead9ef64fb0)
Merged-In: Iff252f0dd06aac9776e8548631e0b700b3ed85b9
Change-Id: Iff252f0dd06aac9776e8548631e0b700b3ed85b9
---
stack/gatt/gatt_sr.cc | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/stack/gatt/gatt_sr.cc b/stack/gatt/gatt_sr.cc
index 94d81efa2..558d61fcc 100644
--- a/stack/gatt/gatt_sr.cc
+++ b/stack/gatt/gatt_sr.cc
@@ -114,7 +114,8 @@ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb) {
******************************************************************************/
static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
tGATTS_RSP* p_msg, uint16_t mtu) {
- uint16_t ii, total_len, len;
+ uint16_t ii;
+ size_t total_len, len;
uint8_t* p;
bool is_overflow = false;
@@ -169,16 +170,22 @@ static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
len = p_rsp->attr_value.len - (total_len - mtu);
is_overflow = true;
VLOG(1) << StringPrintf(
- "multi read overflow available len=%d val_len=%d", len,
+ "multi read overflow available len=%zu val_len=%d", len,
p_rsp->attr_value.len);
} else {
len = p_rsp->attr_value.len;
}
if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) {
- memcpy(p, p_rsp->attr_value.value, len);
- if (!is_overflow) p += len;
- p_buf->len += len;
+ // check for possible integer overflow
+ if (p_buf->len + len <= UINT16_MAX) {
+ memcpy(p, p_rsp->attr_value.value, len);
+ if (!is_overflow) p += len;
+ p_buf->len += len;
+ } else {
+ p_cmd->status = GATT_NOT_FOUND;
+ break;
+ }
} else {
p_cmd->status = GATT_NOT_FOUND;
break;

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Thu, 27 Apr 2023 20:43:58 +0000
Subject: [PATCH] Fix potential abort in btu_av_act.cc
Partner analysis shows that bta_av_rc_msg does not respect handling
established for a null browse packet, instead dispatching the null
pointer to bta_av_rc_free_browse_msg. Strictly speaking this does
not cause a UAF, as osi_free_and_reset will find the null and abort,
but it will lead to improper program termination.
Handle the case instead.
Bug: 269253349
Test: atest bluetooth_test_gd_unit
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:91f6d6215c101acc99a7397c5fb5a12fe6d7b8e9)
Merged-In: I4df7045798b663fbefd7434288dc9383216171a7
Change-Id: I4df7045798b663fbefd7434288dc9383216171a7
---
bta/av/bta_av_act.cc | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/bta/av/bta_av_act.cc b/bta/av/bta_av_act.cc
index 8809abed3..9f97b453a 100644
--- a/bta/av/bta_av_act.cc
+++ b/bta/av/bta_av_act.cc
@@ -1005,7 +1005,10 @@ void bta_av_rc_msg(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) {
av.remote_cmd.rc_handle = p_data->rc_msg.handle;
(*p_cb->p_cback)(evt, &av);
/* If browsing message, then free the browse message buffer */
- bta_av_rc_free_browse_msg(p_cb, p_data);
+ if (p_data->rc_msg.opcode == AVRC_OP_BROWSE &&
+ p_data->rc_msg.msg.browse.p_browse_pkt != NULL) {
+ bta_av_rc_free_browse_msg(p_cb, p_data);
+ }
}
}

View File

@ -1,44 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Thu, 1 Jun 2023 23:57:58 +0000
Subject: [PATCH] Fix UAF in gatt_cl.cc
gatt_cl.cc accesses a header field after the buffer holding it may have
been freed.
Track the relevant state as a local variable instead.
Bug: 274617156
Test: atest: bluetooth, validated against fuzzer
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d7a7f7f3311202065de4b2c17b49994053dd1244)
Merged-In: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
Change-Id: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
---
stack/gatt/gatt_cl.cc | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index db41c5f9f..f7f11b7a9 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -586,12 +586,17 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
memcpy(value.value, p, value.len);
+ bool subtype_is_write_prepare = (p_clcb->op_subtype == GATT_WRITE_PREPARE);
+
if (!gatt_check_write_long_terminate(tcb, p_clcb, &value)) {
gatt_send_prepare_write(tcb, p_clcb);
return;
}
- if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
+ // We now know that we have not terminated, or else we would have returned
+ // early. We free the buffer only if the subtype is not equal to
+ // GATT_WRITE_PREPARE, so checking here is adequate to prevent UAF.
+ if (subtype_is_write_prepare) {
/* application should verify handle offset
and value are matched or not */
gatt_end_operation(p_clcb, p_clcb->status, &value);

View File

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Tue, 2 May 2023 14:20:57 -0700
Subject: [PATCH] OOBW in rw_i93_send_to_upper()
Bug: 271849189
Test: tag r/w
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc9d09e1698725712628d394bf9be4c9003579e8)
Merged-In: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
Change-Id: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
---
src/nfc/tags/rw_i93.cc | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
index 1483cdc..1f48c27 100644
--- a/src/nfc/tags/rw_i93.cc
+++ b/src/nfc/tags/rw_i93.cc
@@ -516,6 +516,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) {
case I93_CMD_GET_MULTI_BLK_SEC:
case I93_CMD_EXT_GET_MULTI_BLK_SEC:
+ if (UINT16_MAX - length < NFC_HDR_SIZE) {
+ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED;
+ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+ rw_cb.tcb.i93.sent_cmd = 0;
+
+ event = RW_I93_CMD_CMPL_EVT;
+ break;
+ }
+
/* forward tag data or security status */
p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE));

View File

@ -1,57 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Tue, 2 May 2023 14:20:57 -0700
Subject: [PATCH] OOBW in rw_i93_send_to_upper()
Bug: 271849189
Test: tag r/w
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc9d09e1698725712628d394bf9be4c9003579e8)
Merged-In: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
Change-Id: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1
Change-Id: Ia10491e388a495a164462c73ced7ea1965808860
---
SN100x/src/nfc/tags/rw_i93.cc | 9 +++++++++
src/nfc/tags/rw_i93.cc | 9 +++++++++
2 files changed, 18 insertions(+)
diff --git a/SN100x/src/nfc/tags/rw_i93.cc b/SN100x/src/nfc/tags/rw_i93.cc
index 9eb4458f..5bf497ad 100755
--- a/SN100x/src/nfc/tags/rw_i93.cc
+++ b/SN100x/src/nfc/tags/rw_i93.cc
@@ -467,6 +467,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) {
case I93_CMD_GET_MULTI_BLK_SEC:
case I93_CMD_EXT_GET_MULTI_BLK_SEC:
+ if (UINT16_MAX - length < NFC_HDR_SIZE) {
+ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED;
+ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+ rw_cb.tcb.i93.sent_cmd = 0;
+
+ event = RW_I93_CMD_CMPL_EVT;
+ break;
+ }
+
/* forward tag data or security status */
p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE));
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
index a648bb9a..a9c220d6 100644
--- a/src/nfc/tags/rw_i93.cc
+++ b/src/nfc/tags/rw_i93.cc
@@ -528,6 +528,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) {
case I93_CMD_GET_MULTI_BLK_SEC:
case I93_CMD_EXT_GET_MULTI_BLK_SEC:
+ if (UINT16_MAX - length < NFC_HDR_SIZE) {
+ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED;
+ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+ rw_cb.tcb.i93.sent_cmd = 0;
+
+ event = RW_I93_CMD_CMPL_EVT;
+ break;
+ }
+
/* forward tag data or security status */
p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE));

View File

@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alisher Alikhodjaev <alisher@google.com>
Date: Thu, 1 Jun 2023 13:44:28 -0700
Subject: [PATCH] Ensure that SecureNFC setting cannot be bypassed
Bug: 268038643
Test: ctsverifier
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d6d8f79fd8d605b3cb460895a8e3a11bcf0c22b0)
Merged-In: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
Change-Id: Ic408b3ef9e35b646b728f9b76a0ba8922ed6e25f
Change-Id: Ib0baa833fe31c72825889b729c83a1d70a5a6a72
---
src/com/android/nfc/NfcService.java | 6 ++++++
src/com/android/nfc/cardemulation/HostEmulationManager.java | 5 +++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 0f12d2e9..d41ea4f2 100644
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -1134,6 +1134,12 @@ public class NfcService implements DeviceHostListener {
}
}
+ public boolean isSecureNfcEnabled() {
+ synchronized (NfcService.this) {
+ return mIsSecureNfcEnabled;
+ }
+ }
+
final class NfcAdapterService extends INfcAdapter.Stub {
@Override
public boolean enable() throws RemoteException {
diff --git a/src/com/android/nfc/cardemulation/HostEmulationManager.java b/src/com/android/nfc/cardemulation/HostEmulationManager.java
index 6af4e0d7..b2670ec2 100644
--- a/src/com/android/nfc/cardemulation/HostEmulationManager.java
+++ b/src/com/android/nfc/cardemulation/HostEmulationManager.java
@@ -177,8 +177,9 @@ public class HostEmulationManager {
// Resolve to default
// Check if resolvedService requires unlock
NfcApduServiceInfo defaultServiceInfo = resolveInfo.defaultService;
- if (defaultServiceInfo.requiresUnlock() &&
- mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
+ if ((defaultServiceInfo.requiresUnlock()
+ || NfcService.getInstance().isSecureNfcEnabled())
+ && mKeyguard.isKeyguardLocked() && mKeyguard.isKeyguardSecure()) {
// Just ignore all future APDUs until next tap
mState = STATE_W4_DEACTIVATE;
launchTapAgain(resolveInfo.defaultService, resolveInfo.category);

View File

@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: tyiu <tyiu@google.com>
Date: Tue, 28 Mar 2023 18:40:51 +0000
Subject: [PATCH] Fix gatt_end_operation buffer overflow
Added boundary check for gatt_end_operation to prevent writing out of
boundary.
Since response of the GATT server is handled in
gatt_client_handle_server_rsp() and gatt_process_read_rsp(), the maximum
lenth that can be passed into the handlers is bounded by
GATT_MAX_MTU_SIZE, which is set to 517, which is greater than
GATT_MAX_ATTR_LEN which is set to 512. The fact that there is no spec
that gaurentees MTU response to be less than or equal to 512 bytes can
cause a buffer overflow when performing memcpy without length check.
Bug: 261068592
Test: No test since not affecting behavior
Tag: #security
Ignore-AOSP-First: security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dd7298e982e4bbf0138a490562679c9a4a755200)
Merged-In: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873
Change-Id: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873
---
stack/gatt/gatt_utils.cc | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc
index 291cd1062..eb2a12dbc 100644
--- a/stack/gatt/gatt_utils.cc
+++ b/stack/gatt/gatt_utils.cc
@@ -1198,6 +1198,13 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) {
cb_data.att_value.handle = p_clcb->s_handle;
cb_data.att_value.len = p_clcb->counter;
+ if (cb_data.att_value.len > GATT_MAX_ATTR_LEN) {
+ LOG(WARNING) << __func__
+ << StringPrintf(" Large cb_data.att_value, size=%d",
+ cb_data.att_value.len);
+ cb_data.att_value.len = GATT_MAX_ATTR_LEN;
+ }
+
if (p_data && p_clcb->counter)
memcpy(cb_data.att_value.value, p_data, cb_data.att_value.len);
}

View File

@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hui Peng <phui@google.com>
Date: Tue, 16 May 2023 21:24:07 +0000
Subject: [PATCH] Fix an integer overflow bug in avdt_msg_asmbl
This is a backport of
Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
to rvc-dev
Bug: 280633699
Test: manual
Ignore-AOSP-First: security
Tag: #security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:26347d4bdba646bbba4d27337d2888a04de42639)
Merged-In: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
Change-Id: Iaa4d603921fc4ffb8cfb5783f99ec0963affd6a2
---
stack/avdt/avdt_msg.cc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index af8d7014e..a98d59d4b 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -1293,14 +1293,14 @@ BT_HDR* avdt_msg_asmbl(tAVDT_CCB* p_ccb, BT_HDR* p_buf) {
* NOTE: The buffer is allocated above at the beginning of the
* reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
*/
- uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
+ size_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
/* adjust offset and len of fragment for header byte */
p_buf->offset += AVDT_LEN_TYPE_CONT;
p_buf->len -= AVDT_LEN_TYPE_CONT;
/* verify length */
- if ((p_ccb->p_rx_msg->offset + p_buf->len) > buf_len) {
+ if (((size_t) p_ccb->p_rx_msg->offset + (size_t) p_buf->len) > buf_len) {
/* won't fit; free everything */
AVDT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
osi_free_and_reset((void**)&p_ccb->p_rx_msg);

View File

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Fri, 19 May 2023 19:17:16 +0000
Subject: [PATCH] Fix integer overflow in build_read_multi_rsp
Local variables tracking structure size in build_read_multi_rsp are of
uint16 type but accept a full uint16 range from function arguments while
appending a fixed-length offset. This can lead to an integer overflow
and unexpected behavior.
Change the locals to size_t, and add a check during reasssignment.
Bug: 273966636
Test: atest bluetooth_test_gd_unit, net_test_stack_btm
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:53f64274cbf2268ad6db5af9c61ceead9ef64fb0)
Merged-In: Iff252f0dd06aac9776e8548631e0b700b3ed85b9
Change-Id: Iff252f0dd06aac9776e8548631e0b700b3ed85b9
---
stack/gatt/gatt_sr.cc | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/stack/gatt/gatt_sr.cc b/stack/gatt/gatt_sr.cc
index 0f32cde37..ee5059b92 100644
--- a/stack/gatt/gatt_sr.cc
+++ b/stack/gatt/gatt_sr.cc
@@ -114,7 +114,8 @@ void gatt_dequeue_sr_cmd(tGATT_TCB& tcb) {
******************************************************************************/
static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
tGATTS_RSP* p_msg, uint16_t mtu) {
- uint16_t ii, total_len, len;
+ uint16_t ii;
+ size_t total_len, len;
uint8_t* p;
bool is_overflow = false;
@@ -169,16 +170,22 @@ static bool process_read_multi_rsp(tGATT_SR_CMD* p_cmd, tGATT_STATUS status,
len = p_rsp->attr_value.len - (total_len - mtu);
is_overflow = true;
VLOG(1) << StringPrintf(
- "multi read overflow available len=%d val_len=%d", len,
+ "multi read overflow available len=%zu val_len=%d", len,
p_rsp->attr_value.len);
} else {
len = p_rsp->attr_value.len;
}
if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) {
- memcpy(p, p_rsp->attr_value.value, len);
- if (!is_overflow) p += len;
- p_buf->len += len;
+ // check for possible integer overflow
+ if (p_buf->len + len <= UINT16_MAX) {
+ memcpy(p, p_rsp->attr_value.value, len);
+ if (!is_overflow) p += len;
+ p_buf->len += len;
+ } else {
+ p_cmd->status = GATT_NOT_FOUND;
+ break;
+ }
} else {
p_cmd->status = GATT_NOT_FOUND;
break;

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Thu, 27 Apr 2023 20:43:58 +0000
Subject: [PATCH] Fix potential abort in btu_av_act.cc
Partner analysis shows that bta_av_rc_msg does not respect handling
established for a null browse packet, instead dispatching the null
pointer to bta_av_rc_free_browse_msg. Strictly speaking this does
not cause a UAF, as osi_free_and_reset will find the null and abort,
but it will lead to improper program termination.
Handle the case instead.
Bug: 269253349
Test: atest bluetooth_test_gd_unit
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:91f6d6215c101acc99a7397c5fb5a12fe6d7b8e9)
Merged-In: I4df7045798b663fbefd7434288dc9383216171a7
Change-Id: I4df7045798b663fbefd7434288dc9383216171a7
---
bta/av/bta_av_act.cc | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/bta/av/bta_av_act.cc b/bta/av/bta_av_act.cc
index ea823ad75..9582b7897 100644
--- a/bta/av/bta_av_act.cc
+++ b/bta/av/bta_av_act.cc
@@ -1310,7 +1310,10 @@ void bta_av_rc_msg(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) {
return;
}
/* If browsing message, then free the browse message buffer */
- bta_av_rc_free_browse_msg(p_cb, p_data);
+ if (p_data->rc_msg.opcode == AVRC_OP_BROWSE &&
+ p_data->rc_msg.msg.browse.p_browse_pkt != NULL) {
+ bta_av_rc_free_browse_msg(p_cb, p_data);
+ }
}
}

View File

@ -1,44 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Thu, 1 Jun 2023 23:57:58 +0000
Subject: [PATCH] Fix UAF in gatt_cl.cc
gatt_cl.cc accesses a header field after the buffer holding it may have
been freed.
Track the relevant state as a local variable instead.
Bug: 274617156
Test: atest: bluetooth, validated against fuzzer
Tag: #security
Ignore-AOSP-First: Security
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d7a7f7f3311202065de4b2c17b49994053dd1244)
Merged-In: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
Change-Id: I085ecfa1a9ba098ecbfecbd3cb3e263ae13f9724
---
stack/gatt/gatt_cl.cc | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index 98186daed..ff4ac8aea 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -592,12 +592,17 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
memcpy(value.value, p, value.len);
+ bool subtype_is_write_prepare = (p_clcb->op_subtype == GATT_WRITE_PREPARE);
+
if (!gatt_check_write_long_terminate(tcb, p_clcb, &value)) {
gatt_send_prepare_write(tcb, p_clcb);
return;
}
- if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
+ // We now know that we have not terminated, or else we would have returned
+ // early. We free the buffer only if the subtype is not equal to
+ // GATT_WRITE_PREPARE, so checking here is adequate to prevent UAF.
+ if (subtype_is_write_prepare) {
/* application should verify handle offset
and value are matched or not */
gatt_end_operation(p_clcb, p_clcb->status, &value);

View File

@ -1,50 +0,0 @@
From 039f815895f62c9f8af23df66622b66246f3f61e Mon Sep 17 00:00:00 2001
From: Michael Groover <mpgroover@google.com>
Date: Tue, 20 Jun 2023 11:51:03 -0500
Subject: [PATCH] Add errors from signature verify result to returned result
During APK signature verification, the apksig library will maintain
an internal Result instance for the current signature version being
verified; any errors / warnings from the specific version signer(s)
verification will then be copied to a Result instance that is
returned to the caller containing details for each of the signature
versions that the library attempted to verify. The internal Result
instance can also contain more general errors / warnings abut the
verification; these are currently not merged with the Result to be
returned to the caller, so some APKs may fail to verify without a
valid error returned. This commit resolves this by merging all
general errors / warnings with the Result to be returned to the
caller.
Bug: 266580022
Test: gradlew test
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0b086bdc130e1e6216fcbc5436fe8e3cdc9ec011)
Merged-In: Id0f4ee47a964a3bb5d30916808a3108858e6a0cf
Change-Id: Id0f4ee47a964a3bb5d30916808a3108858e6a0cf
---
src/main/java/com/android/apksig/ApkVerifier.java | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/main/java/com/android/apksig/ApkVerifier.java b/src/main/java/com/android/apksig/ApkVerifier.java
index 8ae5f78..0b04ef9 100644
--- a/src/main/java/com/android/apksig/ApkVerifier.java
+++ b/src/main/java/com/android/apksig/ApkVerifier.java
@@ -1276,6 +1276,15 @@ public class ApkVerifier {
}
private void mergeFrom(ApkSigningBlockUtils.Result source) {
+ if (source == null) {
+ return;
+ }
+ if (source.containsErrors()) {
+ mErrors.addAll(source.getErrors());
+ }
+ if (source.containsWarnings()) {
+ mWarnings.addAll(source.getWarnings());
+ }
switch (source.signatureSchemeVersion) {
case ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V2:
mVerifiedUsingV2Scheme = source.verified;
--
GitLab

View File

@ -1,60 +0,0 @@
From 89489ff5dd9b7717f0421ca4e90bc060af1ba8b7 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:b8c2d03b720f0cc200ac59f6cfb411fddc3b119c)
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 27db41cb9f4e..d3c3c370a641 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -814,10 +814,10 @@ public static Uri getActualDefaultRingtoneUri(Context context, int type) {
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
@@ -833,6 +833,21 @@ public static void setActualDefaultRingtoneUri(Context context, int type, Uri ri
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());

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +0,0 @@
From cbb1a0ecd6b67735bdb735d76606bc03f6b955bf Mon Sep 17 00:00:00 2001
From: Ioana Alexandru <aioana@google.com>
Date: Mon, 8 May 2023 18:39:35 +0000
Subject: [PATCH] Verify URI permissions for EXTRA_REMOTE_INPUT_HISTORY_ITEMS.
Also added a step to serialize & deserialize the notification in the
test, to prevent exceptions about not being able to cast e.g.
Parcelable[] to RemoteInputHistoryItem[].
Test: atest NotificationManagerServiceTest & tested with POC from bug
Bug: 276729064
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4e19431a60300c6ea6c7f7dd64299916e4eb09bc)
Merged-In: I7053ca59f9c7f1df5226418594109cfb8b609b1e
Change-Id: I7053ca59f9c7f1df5226418594109cfb8b609b1e
---
core/java/android/app/Notification.java | 5 +++--
.../notification/NotificationManagerServiceTest.java | 7 +++++++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8a730fb0deaa..01528ae06cf5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2858,8 +2858,9 @@ public void visitUris(@NonNull Consumer<Uri> visitor) {
visitor.accept(person.getIconUri());
}
- final RemoteInputHistoryItem[] history = (RemoteInputHistoryItem[])
- extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
+ final RemoteInputHistoryItem[] history = extras.getParcelableArray(
+ Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS,
+ RemoteInputHistoryItem.class);
if (history != null) {
for (int i = 0; i < history.length; i++) {
RemoteInputHistoryItem item = history[i];
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 dcaca51c176b..cf33eb5b3647 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5439,6 +5439,13 @@ public void testVisitUris() throws Exception {
.addExtras(extras)
.build();
+ // Serialize and deserialize the notification to make sure nothing breaks in the process,
+ // since that's what will usually happen before we get to call visitUris.
+ Parcel parcel = Parcel.obtain();
+ n.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ n = new Notification(parcel);
+
Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
n.visitUris(visitor);
verify(visitor, times(1)).accept(eq(audioContents));

View File

@ -1,47 +0,0 @@
From 4725772c0b3f0db2940e70851e145ec4ec71768b Mon Sep 17 00:00:00 2001
From: Josep del Rio <joseprio@google.com>
Date: Mon, 26 Jun 2023 09:30:06 +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.
Bug: 274058082
Test: Patch tested by Oppo
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3d993de0d1ada8065d1fe561f690c8f82b6a7d4b)
Merged-In: I745008a0a8ea30830660c45dcebee917b3913d13
Change-Id: I745008a0a8ea30830660c45dcebee917b3913d13
---
core/jni/android_view_InputDevice.cpp | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 9cc72437a023..f7c770e0bffb 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -42,6 +42,13 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
return NULL;
}
+ // b/274058082: Pass a copy of the key character map to avoid concurrent
+ // access
+ std::shared_ptr<KeyCharacterMap> map = deviceInfo.getKeyCharacterMap();
+ if (map != nullptr) {
+ map = std::make_shared<KeyCharacterMap>(*map);
+ }
+
ScopedLocalRef<jstring> descriptorObj(env,
env->NewStringUTF(deviceInfo.getIdentifier().descriptor.c_str()));
if (!descriptorObj.get()) {
@@ -49,8 +56,8 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
}
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

@ -1,197 +0,0 @@
From 19747f69235d208e3d61099c76fa47aa792fe3a7 Mon Sep 17 00:00:00 2001
From: Tim Yu <yunicorn@google.com>
Date: Tue, 20 Jun 2023 21:24:36 +0000
Subject: [PATCH] [DO NOT MERGE] Verify URI Permissions in Autofill RemoteViews
Check permissions of URI inside of FillResponse's RemoteViews. If the
current user does not have the required permissions to view the URI, the
RemoteView is dropped from displaying.
This fixes a security spill in which a user can view content of another
user through a malicious Autofill provider.
Bug: 283137865
Fixes: b/283264674 b/281666022 b/281665050 b/281848557 b/281533566
b/281534749 b/283101289
Test: Verified by POC app attached in bugs
Test: atest CtsAutoFillServiceTestCases (added new tests)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:93810ba1c0a4d31f49adbf9454731e2b7defdfc0)
Merged-In: I6f4d2a35e89bbed7bd9e07bf5cd3e2d68b20af9a
Change-Id: I6f4d2a35e89bbed7bd9e07bf5cd3e2d68b20af9a
---
.../com/android/server/autofill/Helper.java | 43 +++++++++++++++++++
.../server/autofill/ui/DialogFillUi.java | 12 ++++--
.../android/server/autofill/ui/FillUi.java | 11 +++--
.../android/server/autofill/ui/SaveUi.java | 3 +-
4 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index bc5d6457c945..48113a81cca5 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
@@ -34,6 +36,7 @@
import android.view.WindowManager;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
+import android.widget.RemoteViews;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
@@ -42,6 +45,8 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
+
public final class Helper {
@@ -75,6 +80,44 @@ private Helper() {
throw new UnsupportedOperationException("contains static members only");
}
+ private static boolean checkRemoteViewUriPermissions(
+ @UserIdInt int userId, @NonNull RemoteViews rView) {
+ final AtomicBoolean permissionsOk = new AtomicBoolean(true);
+
+ rView.visitUris(uri -> {
+ int uriOwnerId = android.content.ContentProvider.getUserIdFromUri(uri);
+ boolean allowed = uriOwnerId == userId;
+ permissionsOk.set(allowed && permissionsOk.get());
+ });
+
+ return permissionsOk.get();
+ }
+
+ /**
+ * Checks the URI permissions of the remote view,
+ * to see if the current userId is able to access it.
+ *
+ * Returns the RemoteView that is passed if user is able, null otherwise.
+ *
+ * TODO: instead of returning a null remoteview when
+ * the current userId cannot access an URI,
+ * return a new RemoteView with the URI removed.
+ */
+ public static @Nullable RemoteViews sanitizeRemoteView(RemoteViews rView) {
+ if (rView == null) return null;
+
+ int userId = ActivityManager.getCurrentUser();
+
+ boolean ok = checkRemoteViewUriPermissions(userId, rView);
+ if (!ok) {
+ Slog.w(TAG,
+ "sanitizeRemoteView() user: " + userId
+ + " tried accessing resource that does not belong to them");
+ }
+ return (ok ? rView : null);
+ }
+
+
@Nullable
static AutofillId[] toArray(@Nullable ArraySet<AutofillId> set) {
if (set == null) return null;
diff --git a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
index c2c630e01bee..59184e9ed288 100644
--- a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
@@ -52,6 +52,7 @@
import com.android.internal.R;
import com.android.server.autofill.AutofillManagerService;
+import com.android.server.autofill.Helper;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -197,7 +198,8 @@ private void setServiceIcon(View decor, Drawable serviceIcon) {
}
private void setHeader(View decor, FillResponse response) {
- final RemoteViews presentation = response.getDialogHeader();
+ final RemoteViews presentation =
+ Helper.sanitizeRemoteView(response.getDialogHeader());
if (presentation == null) {
return;
}
@@ -232,9 +234,10 @@ private void setContinueButton(View decor, View.OnClickListener listener) {
}
private void initialAuthenticationLayout(View decor, FillResponse response) {
- RemoteViews presentation = response.getDialogPresentation();
+ RemoteViews presentation = Helper.sanitizeRemoteView(
+ response.getDialogPresentation());
if (presentation == null) {
- presentation = response.getPresentation();
+ presentation = Helper.sanitizeRemoteView(response.getPresentation());
}
if (presentation == null) {
throw new RuntimeException("No presentation for fill dialog authentication");
@@ -278,7 +281,8 @@ private ArrayList<ViewItem> createDatasetItems(FillResponse response,
final Dataset dataset = response.getDatasets().get(i);
final int index = dataset.getFieldIds().indexOf(focusedViewId);
if (index >= 0) {
- RemoteViews presentation = dataset.getFieldDialogPresentation(index);
+ RemoteViews presentation = Helper.sanitizeRemoteView(
+ dataset.getFieldDialogPresentation(index));
if (presentation == null) {
if (sDebug) {
Slog.w(TAG, "not displaying UI on field " + focusedViewId + " because "
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 8fbdd81cc4cc..76fa258734cc 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -144,8 +144,9 @@ public static boolean isFullScreen(Context context) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
- final RemoteViews headerPresentation = response.getHeader();
- final RemoteViews footerPresentation = response.getFooter();
+ final RemoteViews headerPresentation = Helper.sanitizeRemoteView(response.getHeader());
+ final RemoteViews footerPresentation = Helper.sanitizeRemoteView(response.getFooter());
+
final ViewGroup decor;
if (mFullScreen) {
decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_fullscreen, null);
@@ -223,6 +224,9 @@ public static boolean isFullScreen(Context context) {
ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
final View content;
try {
+ if (Helper.sanitizeRemoteView(response.getPresentation()) == null) {
+ throw new RuntimeException("Permission error accessing RemoteView");
+ }
content = response.getPresentation().applyWithTheme(
mContext, decor, interceptionHandler, mThemeId);
container.addView(content);
@@ -302,7 +306,8 @@ public static boolean isFullScreen(Context context) {
final Dataset dataset = response.getDatasets().get(i);
final int index = dataset.getFieldIds().indexOf(focusedViewId);
if (index >= 0) {
- final RemoteViews presentation = dataset.getFieldPresentation(index);
+ final RemoteViews presentation = Helper.sanitizeRemoteView(
+ dataset.getFieldPresentation(index));
if (presentation == null) {
Slog.w(TAG, "not displaying UI on field " + focusedViewId + " because "
+ "service didn't provide a presentation for it on " + dataset);
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 677871f6c85f..533a7b69a650 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -368,8 +368,7 @@ private boolean applyCustomDescription(@NonNull Context context, @NonNull View s
return false;
}
writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION);
-
- final RemoteViews template = customDescription.getPresentation();
+ final RemoteViews template = Helper.sanitizeRemoteView(customDescription.getPresentation());
if (template == null) {
Slog.w(TAG, "No remote view on custom description");
return false;

View File

@ -1,53 +0,0 @@
From e7a1aa9ed0bc69853bc83d098e15b8fa3b1881b4 Mon Sep 17 00:00:00 2001
From: Hongwei Wang <hwwang@google.com>
Date: Thu, 25 May 2023 12:18: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:1aee65603e262affd815fa53dcc5416c605e4037)
Merged-In: Ib3f5b8b6b9ce644fdf1173548d9078e4d969ae2e
Change-Id: Ib3f5b8b6b9ce644fdf1173548d9078e4d969ae2e
---
.../wm/shell/pip/phone/PipMenuView.java | 21 ++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index 167c0321d3ad..779c539a2097 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -45,6 +45,7 @@
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -513,13 +514,19 @@ private void updateActionViews(int menuState, Rect stackBounds) {
final boolean isCloseAction = mCloseAction != null && Objects.equals(
mCloseAction.getActionIntent(), action.getActionIntent());
- // TODO: Check if the action drawable has changed before we reload it
- action.getIcon().loadDrawableAsync(mContext, d -> {
- if (d != null) {
- d.setTint(Color.WHITE);
- actionView.setImageDrawable(d);
- }
- }, mMainHandler);
+ final int iconType = action.getIcon().getType();
+ if (iconType == Icon.TYPE_URI || iconType == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
+ // 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(mContext, d -> {
+ if (d != null) {
+ d.setTint(Color.WHITE);
+ actionView.setImageDrawable(d);
+ }
+ }, mMainHandler);
+ }
actionView.setCustomCloseBackgroundVisibility(
isCloseAction ? View.VISIBLE : View.GONE);
actionView.setContentDescription(action.getContentDescription());

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