mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-28 08:59:40 -05:00
Switch to upstream ASB patchsets
Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
parent
7b54b4459c
commit
bf565cd578
@ -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
|
@ -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 */
|
@ -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 );
|
@ -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 */
|
@ -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 );
|
@ -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 );
|
||||
|
||||
|
||||
/*************************************************************************/
|
@ -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;
|
@ -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<br>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<br>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);
|
@ -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();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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 {
|
@ -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)
|
@ -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()));
|
||||
+ }
|
||||
}
|
@ -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) {
|
@ -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));
|
||||
}
|
@ -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
|
@ -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);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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
|
@ -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
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -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");
|
@ -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);
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
@ -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
|
@ -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);
|
||||
}
|
@ -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();
|
||||
|
@ -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())) {
|
@ -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);
|
||||
}
|
@ -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);
|
@ -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;
|
@ -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);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
@ -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);
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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));
|
||||
|
@ -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);
|
@ -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
|
@ -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 );
|
@ -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 );
|
||||
|
||||
|
||||
/**************************************************************************
|
@ -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;
|
@ -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;
|
||||
|
||||
/**
|
@ -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<br>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<br>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);
|
@ -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
@ -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;
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
@ -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;
|
@ -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;
|
||||
|
@ -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)
|
@ -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()));
|
||||
+ }
|
||||
}
|
@ -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) {
|
@ -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) {
|
@ -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 + "'");
|
@ -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
|
@ -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;
|
@ -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);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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
|
@ -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
|
@ -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);
|
@ -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
|
@ -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);
|
@ -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);
|
@ -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");
|
@ -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());
|
@ -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);
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
@ -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
|
@ -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);
|
||||
}
|
@ -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();
|
||||
|
@ -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);
|
@ -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())) {
|
@ -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);
|
||||
}
|
@ -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);
|
@ -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;
|
@ -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);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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);
|
@ -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;
|
@ -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);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
@ -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
|
||||
|
@ -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
@ -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));
|
@ -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;
|
||||
}
|
@ -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;
|
@ -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
Loading…
Reference in New Issue
Block a user