mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
Reconcile picks
This gains one us patch: 376607 Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
parent
85aa8d153d
commit
ba1e29a1b1
@ -1,214 +0,0 @@
|
||||
From c5803c1b6a680ad1c30f9655508784e07c08be36 Mon Sep 17 00:00:00 2001
|
||||
From: James Zern <jzern@google.com>
|
||||
Date: Sat, 9 Sep 2023 14:02:18 -0700
|
||||
Subject: [PATCH] update to v1.1.0-8-g50f60add
|
||||
|
||||
https://chromium.googlesource.com/webm/libwebp/+log/v1.1.0..v1.1.0-8-g50f60add
|
||||
|
||||
50f60add Fix OOB write in BuildHuffmanTable.
|
||||
5df85e9c EncodeAlphaInternal: clear result->bw on error
|
||||
89e226a3 GetBackwardReferences: fail on alloc error
|
||||
4d0964cd BackwardReferencesHashChainDistanceOnly: fix segfault on OOM
|
||||
5d805f72 VP8LEncodeStream: fix segfault on OOM
|
||||
b14eba64 alpha_processing_neon.c: fix 0x01... typo
|
||||
9183ff2e alpha_processing_neon.c: fix Dispatch/ExtractAlpha_NEON
|
||||
68d52453 Fix lossless encoding for MIPS.
|
||||
|
||||
Bug: 299477569
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c3f928a1d30e48a400ed434130da3609cbfd54ad)
|
||||
Merged-In: Ia4290d2a5f16a61ae0729b7d55ba144251c2b988
|
||||
Change-Id: Ia4290d2a5f16a61ae0729b7d55ba144251c2b988
|
||||
---
|
||||
README.android | 2 +-
|
||||
README.version | 4 ++--
|
||||
src/dsp/alpha_processing_neon.c | 6 ++++--
|
||||
src/dsp/lossless_enc_mips32.c | 8 ++++----
|
||||
src/enc/alpha_enc.c | 4 +++-
|
||||
src/enc/backward_references_cost_enc.c | 2 +-
|
||||
src/enc/backward_references_enc.c | 13 +++++++------
|
||||
src/enc/vp8l_enc.c | 11 ++++++++---
|
||||
8 files changed, 30 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/README.android b/README.android
|
||||
index 94fd4d4a..93c20140 100644
|
||||
--- a/README.android
|
||||
+++ b/README.android
|
||||
@@ -1,5 +1,5 @@
|
||||
URL: https://chromium.googlesource.com/webm/libwebp
|
||||
-Version: v1.1.0
|
||||
+Version: v1.1.0-8-g50f60add
|
||||
License: Google BSD like
|
||||
|
||||
Local modifications:
|
||||
diff --git a/README.version b/README.version
|
||||
index f94ac059..621b44fa 100644
|
||||
--- a/README.version
|
||||
+++ b/README.version
|
||||
@@ -1,3 +1,3 @@
|
||||
-URL: https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.1.0.tar.gz
|
||||
-Version: 1.1.0
|
||||
+URL: https://chromium.googlesource.com/webm/libwebp/+archive/v1.1.0-8-g50f60add.tar.gz
|
||||
+Version: v1.1.0-8-g50f60add
|
||||
BugComponent: 20174
|
||||
diff --git a/src/dsp/alpha_processing_neon.c b/src/dsp/alpha_processing_neon.c
|
||||
index 9d554217..27d71750 100644
|
||||
--- a/src/dsp/alpha_processing_neon.c
|
||||
+++ b/src/dsp/alpha_processing_neon.c
|
||||
@@ -83,7 +83,7 @@ static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first,
|
||||
static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
|
||||
int width, int height,
|
||||
uint8_t* dst, int dst_stride) {
|
||||
- uint32_t alpha_mask = 0xffffffffu;
|
||||
+ uint32_t alpha_mask = 0xffu;
|
||||
uint8x8_t mask8 = vdup_n_u8(0xff);
|
||||
uint32_t tmp[2];
|
||||
int i, j;
|
||||
@@ -107,6 +107,7 @@ static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
|
||||
dst += dst_stride;
|
||||
}
|
||||
vst1_u8((uint8_t*)tmp, mask8);
|
||||
+ alpha_mask *= 0x01010101;
|
||||
alpha_mask &= tmp[0];
|
||||
alpha_mask &= tmp[1];
|
||||
return (alpha_mask != 0xffffffffu);
|
||||
@@ -134,7 +135,7 @@ static void DispatchAlphaToGreen_NEON(const uint8_t* alpha, int alpha_stride,
|
||||
static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
|
||||
int width, int height,
|
||||
uint8_t* alpha, int alpha_stride) {
|
||||
- uint32_t alpha_mask = 0xffffffffu;
|
||||
+ uint32_t alpha_mask = 0xffu;
|
||||
uint8x8_t mask8 = vdup_n_u8(0xff);
|
||||
uint32_t tmp[2];
|
||||
int i, j;
|
||||
@@ -156,6 +157,7 @@ static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
|
||||
alpha += alpha_stride;
|
||||
}
|
||||
vst1_u8((uint8_t*)tmp, mask8);
|
||||
+ alpha_mask *= 0x01010101;
|
||||
alpha_mask &= tmp[0];
|
||||
alpha_mask &= tmp[1];
|
||||
return (alpha_mask == 0xffffffffu);
|
||||
diff --git a/src/dsp/lossless_enc_mips32.c b/src/dsp/lossless_enc_mips32.c
|
||||
index 0412a093..99630517 100644
|
||||
--- a/src/dsp/lossless_enc_mips32.c
|
||||
+++ b/src/dsp/lossless_enc_mips32.c
|
||||
@@ -347,24 +347,24 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[],
|
||||
static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb,
|
||||
uint32_t* pout, int size) {
|
||||
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
||||
- const uint32_t end = ((size) / 4) * 4;
|
||||
+ const int end = ((size) / 4) * 4;
|
||||
const uint32_t* const LoopEnd = pa + end;
|
||||
int i;
|
||||
ASM_START
|
||||
ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)
|
||||
ASM_END_0
|
||||
- for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i];
|
||||
+ for (i = 0; i < size - end; ++i) pout[i] = pa[i] + pb[i];
|
||||
}
|
||||
|
||||
static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) {
|
||||
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
||||
- const uint32_t end = ((size) / 4) * 4;
|
||||
+ const int end = ((size) / 4) * 4;
|
||||
const uint32_t* const LoopEnd = pa + end;
|
||||
int i;
|
||||
ASM_START
|
||||
ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)
|
||||
ASM_END_1
|
||||
- for (i = end; i < size; ++i) pout[i] += pa[i];
|
||||
+ for (i = 0; i < size - end; ++i) pout[i] += pa[i];
|
||||
}
|
||||
|
||||
#undef ASM_END_1
|
||||
diff --git a/src/enc/alpha_enc.c b/src/enc/alpha_enc.c
|
||||
index dce9ca95..c786ae59 100644
|
||||
--- a/src/enc/alpha_enc.c
|
||||
+++ b/src/enc/alpha_enc.c
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
|
||||
#include "src/enc/vp8i_enc.h"
|
||||
#include "src/dsp/dsp.h"
|
||||
@@ -148,6 +149,7 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
||||
}
|
||||
} else {
|
||||
VP8LBitWriterWipeOut(&tmp_bw);
|
||||
+ memset(&result->bw, 0, sizeof(result->bw));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -162,7 +164,7 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
||||
header = method | (filter << 2);
|
||||
if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
|
||||
|
||||
- VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size);
|
||||
+ if (!VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size)) ok = 0;
|
||||
ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN);
|
||||
ok = ok && VP8BitWriterAppend(&result->bw, output, output_size);
|
||||
|
||||
diff --git a/src/enc/backward_references_cost_enc.c b/src/enc/backward_references_cost_enc.c
|
||||
index 516abd73..5eb24d44 100644
|
||||
--- a/src/enc/backward_references_cost_enc.c
|
||||
+++ b/src/enc/backward_references_cost_enc.c
|
||||
@@ -577,7 +577,7 @@ static int BackwardReferencesHashChainDistanceOnly(
|
||||
(CostModel*)WebPSafeCalloc(1ULL, cost_model_size);
|
||||
VP8LColorCache hashers;
|
||||
CostManager* cost_manager =
|
||||
- (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager));
|
||||
+ (CostManager*)WebPSafeCalloc(1ULL, sizeof(*cost_manager));
|
||||
int offset_prev = -1, len_prev = -1;
|
||||
double offset_cost = -1;
|
||||
int first_offset_is_constant = -1; // initialized with 'impossible' value
|
||||
diff --git a/src/enc/backward_references_enc.c b/src/enc/backward_references_enc.c
|
||||
index d445b40f..59809b16 100644
|
||||
--- a/src/enc/backward_references_enc.c
|
||||
+++ b/src/enc/backward_references_enc.c
|
||||
@@ -912,13 +912,14 @@ static VP8LBackwardRefs* GetBackwardReferences(
|
||||
quality >= 25) {
|
||||
const VP8LHashChain* const hash_chain_tmp =
|
||||
(lz77_type_best == kLZ77Standard) ? hash_chain : &hash_chain_box;
|
||||
- if (VP8LBackwardReferencesTraceBackwards(width, height, argb, *cache_bits,
|
||||
- hash_chain_tmp, best, worst)) {
|
||||
- double bit_cost_trace;
|
||||
- VP8LHistogramCreate(histo, worst, *cache_bits);
|
||||
- bit_cost_trace = VP8LHistogramEstimateBits(histo);
|
||||
- if (bit_cost_trace < bit_cost_best) best = worst;
|
||||
+ double bit_cost_trace;
|
||||
+ if (!VP8LBackwardReferencesTraceBackwards(width, height, argb, *cache_bits,
|
||||
+ hash_chain_tmp, best, worst)) {
|
||||
+ goto Error;
|
||||
}
|
||||
+ VP8LHistogramCreate(histo, worst, *cache_bits);
|
||||
+ bit_cost_trace = VP8LHistogramEstimateBits(histo);
|
||||
+ if (bit_cost_trace < bit_cost_best) best = worst;
|
||||
}
|
||||
|
||||
BackwardReferences2DLocality(width, best);
|
||||
diff --git a/src/enc/vp8l_enc.c b/src/enc/vp8l_enc.c
|
||||
index 2efd403f..c9dea0bd 100644
|
||||
--- a/src/enc/vp8l_enc.c
|
||||
+++ b/src/enc/vp8l_enc.c
|
||||
@@ -1693,11 +1693,16 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
|
||||
const WebPWorkerInterface* const worker_interface = WebPGetWorkerInterface();
|
||||
int ok_main;
|
||||
|
||||
+ if (enc_main == NULL || !VP8LBitWriterInit(&bw_side, 0)) {
|
||||
+ WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
||||
+ VP8LEncoderDelete(enc_main);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
// Analyze image (entropy, num_palettes etc)
|
||||
- if (enc_main == NULL ||
|
||||
- !EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main,
|
||||
+ if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main,
|
||||
&red_and_blue_always_zero) ||
|
||||
- !EncoderInit(enc_main) || !VP8LBitWriterInit(&bw_side, 0)) {
|
||||
+ !EncoderInit(enc_main)) {
|
||||
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
||||
goto Error;
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shruti Bihani <shrutibihani@google.com>
|
||||
Date: Mon, 10 Jul 2023 08:53:42 +0000
|
||||
Subject: [PATCH] Fix for heap buffer overflow issue flagged by fuzzer test.
|
||||
|
||||
OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue.
|
||||
|
||||
Similar checks have been added wherever applicable on other such methods of the class.
|
||||
|
||||
Bug: 243463593
|
||||
Test: Build mtp_packet_fuzzer and run on the target device
|
||||
(cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1401a723899766632363129265b30d433ac69c44)
|
||||
Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b
|
||||
Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b
|
||||
---
|
||||
media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 31 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
|
||||
index 3b298a9bf3..e4467bbfdc 100644
|
||||
--- a/media/mtp/MtpPacket.cpp
|
||||
+++ b/media/mtp/MtpPacket.cpp
|
||||
@@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) {
|
||||
}
|
||||
|
||||
uint16_t MtpPacket::getUInt16(int offset) const {
|
||||
- return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
|
||||
+ if ((unsigned long)(offset+2) <= mBufferSize) {
|
||||
+ return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
|
||||
+ }
|
||||
+ else {
|
||||
+ ALOGE("offset for buffer read is greater than buffer size!");
|
||||
+ abort();
|
||||
+ }
|
||||
}
|
||||
|
||||
uint32_t MtpPacket::getUInt32(int offset) const {
|
||||
- return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
|
||||
- ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
|
||||
+ if ((unsigned long)(offset+4) <= mBufferSize) {
|
||||
+ return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
|
||||
+ ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
|
||||
+ }
|
||||
+ else {
|
||||
+ ALOGE("offset for buffer read is greater than buffer size!");
|
||||
+ abort();
|
||||
+ }
|
||||
}
|
||||
|
||||
void MtpPacket::putUInt16(int offset, uint16_t value) {
|
||||
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||
+ if ((unsigned long)(offset+2) <= mBufferSize) {
|
||||
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||
+ }
|
||||
+ else {
|
||||
+ ALOGE("offset for buffer write is greater than buffer size!");
|
||||
+ }
|
||||
}
|
||||
|
||||
void MtpPacket::putUInt32(int offset, uint32_t value) {
|
||||
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||
- mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
|
||||
- mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
|
||||
+ if ((unsigned long)(offset+4) <= mBufferSize) {
|
||||
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
|
||||
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
|
||||
+ mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
|
||||
+ mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
|
||||
+ }
|
||||
+ else {
|
||||
+ ALOGE("offset for buffer write is greater than buffer size!");
|
||||
+ }
|
||||
}
|
||||
|
||||
uint16_t MtpPacket::getContainerCode() const {
|
@ -1,72 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shruti Bihani <shrutibihani@google.com>
|
||||
Date: Thu, 13 Jul 2023 09:19:08 +0000
|
||||
Subject: [PATCH] Fix heap-use-after-free issue flagged by fuzzer test.
|
||||
|
||||
A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way.
|
||||
|
||||
Bug: 243381410
|
||||
Test: Build mtp_handle_fuzzer and run on the target device
|
||||
(cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:73d89318a658ece5f337c5f9c1ec1149c52eb722)
|
||||
Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411
|
||||
Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411
|
||||
---
|
||||
media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++
|
||||
media/mtp/MtpFfsHandle.h | 4 ++++
|
||||
2 files changed, 18 insertions(+)
|
||||
|
||||
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
|
||||
index bd6a6c679a..09eb96a00d 100644
|
||||
--- a/media/mtp/MtpFfsHandle.cpp
|
||||
+++ b/media/mtp/MtpFfsHandle.cpp
|
||||
@@ -296,6 +296,10 @@ int MtpFfsHandle::start(bool ptp) {
|
||||
}
|
||||
|
||||
void MtpFfsHandle::close() {
|
||||
+ auto timeout = std::chrono::seconds(2);
|
||||
+ std::unique_lock lk(m);
|
||||
+ cv.wait_for(lk, timeout ,[this]{return child_threads==0;});
|
||||
+
|
||||
io_destroy(mCtx);
|
||||
closeEndpoints();
|
||||
closeConfig();
|
||||
@@ -662,6 +666,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) {
|
||||
char *temp = new char[me.length];
|
||||
memcpy(temp, me.data, me.length);
|
||||
me.data = temp;
|
||||
+
|
||||
+ std::unique_lock lk(m);
|
||||
+ child_threads++;
|
||||
+ lk.unlock();
|
||||
+
|
||||
std::thread t([this, me]() { return this->doSendEvent(me); });
|
||||
t.detach();
|
||||
return 0;
|
||||
@@ -673,6 +682,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) {
|
||||
if (static_cast<unsigned>(ret) != length)
|
||||
PLOG(ERROR) << "Mtp error sending event thread!";
|
||||
delete[] reinterpret_cast<char*>(me.data);
|
||||
+
|
||||
+ std::unique_lock lk(m);
|
||||
+ child_threads--;
|
||||
+ lk.unlock();
|
||||
+ cv.notify_one();
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
|
||||
index fe343f74f6..ae78db2877 100644
|
||||
--- a/media/mtp/MtpFfsHandle.h
|
||||
+++ b/media/mtp/MtpFfsHandle.h
|
||||
@@ -58,6 +58,10 @@ protected:
|
||||
|
||||
bool mCanceled;
|
||||
|
||||
+ std::mutex m;
|
||||
+ std::condition_variable cv;
|
||||
+ std::atomic<int> child_threads{0};
|
||||
+
|
||||
android::base::unique_fd mControl;
|
||||
// "in" from the host's perspective => sink for mtp server
|
||||
android::base::unique_fd mBulkIn;
|
@ -1,60 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jean-Michel Trivi <jmtrivi@google.com>
|
||||
Date: Wed, 7 Dec 2022 04:36:46 +0000
|
||||
Subject: [PATCH] RingtoneManager: verify default ringtone is audio
|
||||
|
||||
When a ringtone picker tries to set a ringtone through
|
||||
RingtoneManager.setActualDefaultRingtoneUri (also
|
||||
called by com.android.settings.DefaultRingtonePreference),
|
||||
verify the mimeType can be obtained (not found when caller
|
||||
doesn't have access to it) and it is an audio resource.
|
||||
|
||||
Bug: 205837340
|
||||
Test: atest android.media.audio.cts.RingtoneManagerTest
|
||||
(cherry picked from commit 38618f9fb16d3b5617e2289354d47abe5af17dad)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:377144b64325dadad102f5233ecb50a4446b205b)
|
||||
Merged-In: I3f2c487ded405c0c1a83ef0a2fe99cff7cc9328e
|
||||
Change-Id: I3f2c487ded405c0c1a83ef0a2fe99cff7cc9328e
|
||||
---
|
||||
media/java/android/media/RingtoneManager.java | 19 +++++++++++++++++--
|
||||
1 file changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
|
||||
index 05b96ad016a8..ad4751165d30 100644
|
||||
--- a/media/java/android/media/RingtoneManager.java
|
||||
+++ b/media/java/android/media/RingtoneManager.java
|
||||
@@ -792,10 +792,10 @@ public class RingtoneManager {
|
||||
|
||||
return ringtoneUri;
|
||||
}
|
||||
-
|
||||
+
|
||||
/**
|
||||
* Sets the {@link Uri} of the default sound for a given sound type.
|
||||
- *
|
||||
+ *
|
||||
* @param context A context used for querying.
|
||||
* @param type The type whose default sound should be set. One of
|
||||
* {@link #TYPE_RINGTONE}, {@link #TYPE_NOTIFICATION}, or
|
||||
@@ -816,6 +816,21 @@ public class RingtoneManager {
|
||||
if(!isInternalRingtoneUri(ringtoneUri)) {
|
||||
ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
|
||||
}
|
||||
+
|
||||
+ if (ringtoneUri != null) {
|
||||
+ final String mimeType = resolver.getType(ringtoneUri);
|
||||
+ if (mimeType == null) {
|
||||
+ Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
|
||||
+ + " ignored: failure to find mimeType (no access from this context?)");
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
|
||||
+ Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
|
||||
+ + " ignored: associated mimeType:" + mimeType + " is not an audio type");
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
Settings.System.putStringForUser(resolver, setting,
|
||||
ringtoneUri != null ? ringtoneUri.toString() : null, context.getUserId());
|
||||
|
@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Josep del Rio <joseprio@google.com>
|
||||
Date: Mon, 26 Jun 2023 11:16:37 +0000
|
||||
Subject: [PATCH] Do not share key mappings with JNI object
|
||||
|
||||
The key mapping information between the native key mappings and
|
||||
the KeyCharacterMap object available in Java is currently shared,
|
||||
which means that a read can be attempted while it's being modified.
|
||||
|
||||
Because the code changed between R and S, this CL fixes it just
|
||||
for R; the patch for versions S+ is ag/23785419
|
||||
|
||||
Bug: 274058082
|
||||
Test: Presubmit
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4b3c4620166071561ec44961fb08a56676b4fd6c)
|
||||
Merged-In: I3be94534dcda365da473f82347ae2e3f57bb1b42
|
||||
Change-Id: I3be94534dcda365da473f82347ae2e3f57bb1b42
|
||||
---
|
||||
core/jni/android_view_InputDevice.cpp | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
|
||||
index 9f4e3e516ada..81ada6ad535c 100644
|
||||
--- a/core/jni/android_view_InputDevice.cpp
|
||||
+++ b/core/jni/android_view_InputDevice.cpp
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
+#include <binder/Parcel.h>
|
||||
#include <input/Input.h>
|
||||
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
@@ -48,9 +49,16 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ sp<KeyCharacterMap> map = deviceInfo.getKeyCharacterMap();
|
||||
+ if (map != nullptr) {
|
||||
+ Parcel parcel;
|
||||
+ map->writeToParcel(&parcel);
|
||||
+ map = map->readFromParcel(&parcel);
|
||||
+ }
|
||||
+
|
||||
ScopedLocalRef<jobject> kcmObj(env,
|
||||
- android_view_KeyCharacterMap_create(env, deviceInfo.getId(),
|
||||
- deviceInfo.getKeyCharacterMap()));
|
||||
+ android_view_KeyCharacterMap_create(env, deviceInfo.getId(),
|
||||
+ map));
|
||||
if (!kcmObj.get()) {
|
||||
return NULL;
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tim Yu <yunicorn@google.com>
|
||||
Date: Tue, 20 Jun 2023 21:24:36 +0000
|
||||
Subject: [PATCH] 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:26beceb9a252a50374d056b162fa7e8ea55051b3)
|
||||
Merged-In: I6f4d2a35e89bbed7bd9e07bf5cd3e2d68b20af9a
|
||||
Change-Id: I6f4d2a35e89bbed7bd9e07bf5cd3e2d68b20af9a
|
||||
---
|
||||
.../com/android/server/autofill/Helper.java | 45 +++++++++++++++++++
|
||||
.../android/server/autofill/ui/FillUi.java | 11 +++--
|
||||
.../android/server/autofill/ui/SaveUi.java | 2 +-
|
||||
3 files changed, 54 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
|
||||
index 80b0375a229d..8954a0c39091 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 @@ package com.android.server.autofill;
|
||||
|
||||
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;
|
||||
@@ -31,13 +33,18 @@ import android.view.View;
|
||||
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;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
+
|
||||
+import java.util.Arrays;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
+import java.util.concurrent.atomic.AtomicBoolean;
|
||||
+
|
||||
|
||||
public final class Helper {
|
||||
|
||||
@@ -71,6 +78,44 @@ public final class 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/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
|
||||
index dbd4d8c168ba..e728a6b91e11 100644
|
||||
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
|
||||
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
|
||||
@@ -140,8 +140,9 @@ final class FillUi {
|
||||
|
||||
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);
|
||||
@@ -219,6 +220,9 @@ final class FillUi {
|
||||
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);
|
||||
@@ -295,7 +299,8 @@ final class FillUi {
|
||||
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 73f5cb8326ea..6ae9a8b55c1e 100644
|
||||
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
|
||||
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
|
||||
@@ -288,7 +288,7 @@ final class SaveUi {
|
||||
final int type = info.getType();
|
||||
writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION, type);
|
||||
|
||||
- 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,29 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Josep del Rio <joseprio@google.com>
|
||||
Date: Wed, 12 Jul 2023 16:32:05 +0000
|
||||
Subject: [PATCH] Fix KCM key mapping cloning
|
||||
|
||||
ag/23792288 tried to fix a security issue by cloning the key
|
||||
mappings, but unfortunately the parcel was not being rewinded.
|
||||
|
||||
Bug: 274058082
|
||||
Test: Confirmed change works in newer Android versions
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:aaaba6cf190d976efdc5db6c78997dbdc9214c15)
|
||||
Merged-In: I6f75b9202e20d82ebf81a35a2916e653ee1b8372
|
||||
Change-Id: I6f75b9202e20d82ebf81a35a2916e653ee1b8372
|
||||
---
|
||||
core/jni/android_view_InputDevice.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
|
||||
index 81ada6ad535c..87102d3359a7 100644
|
||||
--- a/core/jni/android_view_InputDevice.cpp
|
||||
+++ b/core/jni/android_view_InputDevice.cpp
|
||||
@@ -53,6 +53,7 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
|
||||
if (map != nullptr) {
|
||||
Parcel parcel;
|
||||
map->writeToParcel(&parcel);
|
||||
+ parcel.setDataPosition(0);
|
||||
map = map->readFromParcel(&parcel);
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hongwei Wang <hwwang@google.com>
|
||||
Date: Wed, 24 May 2023 19:35:44 -0700
|
||||
Subject: [PATCH] Disallow loading icon from content URI to PipMenu
|
||||
|
||||
Bug: 278246904
|
||||
Test: manually, with the PoC app attached to the bug
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5f5a87d8a0dc9190327ba0e6113d5b80ee96abae)
|
||||
Merged-In: Iecfc1fb962de611cbe3c51a44ba4fded53925a7d
|
||||
Change-Id: Iecfc1fb962de611cbe3c51a44ba4fded53925a7d
|
||||
---
|
||||
.../systemui/pip/phone/PipMenuActivity.java | 17 ++++++++++++-----
|
||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
|
||||
index ec6d7ffaedb0..818d6576ac02 100644
|
||||
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
|
||||
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
|
||||
@@ -51,6 +51,7 @@ import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
+import android.graphics.drawable.Icon;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -457,11 +458,17 @@ public class PipMenuActivity extends Activity {
|
||||
final RemoteAction action = mActions.get(i);
|
||||
final ImageView actionView = (ImageView) mActionsGroup.getChildAt(i);
|
||||
|
||||
- // TODO: Check if the action drawable has changed before we reload it
|
||||
- action.getIcon().loadDrawableAsync(this, d -> {
|
||||
- d.setTint(Color.WHITE);
|
||||
- actionView.setImageDrawable(d);
|
||||
- }, mHandler);
|
||||
+ final int iconType = action.getIcon().getType();
|
||||
+ if (iconType == Icon.TYPE_URI /* || 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(this, d -> {
|
||||
+ d.setTint(Color.WHITE);
|
||||
+ actionView.setImageDrawable(d);
|
||||
+ }, mHandler);
|
||||
+ }
|
||||
actionView.setContentDescription(action.getContentDescription());
|
||||
if (action.isEnabled()) {
|
||||
actionView.setOnClickListener(v -> {
|
@ -1,59 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kunal Malhotra <malhk@google.com>
|
||||
Date: Fri, 2 Jun 2023 23:32:02 +0000
|
||||
Subject: [PATCH] Fixing DatabaseUtils to detect malformed UTF-16 strings
|
||||
|
||||
Test: tested with POC in bug, also using atest
|
||||
Bug: 224771621
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:fb4a72e3943d166088407e61aa4439ac349f3f12)
|
||||
Merged-In: Ide65205b83063801971c5778af3154bcf3f0e530
|
||||
Change-Id: Ide65205b83063801971c5778af3154bcf3f0e530
|
||||
---
|
||||
core/java/android/database/DatabaseUtils.java | 32 +++++++++++++------
|
||||
1 file changed, 23 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
|
||||
index 171fc8270d37..648b50877b61 100644
|
||||
--- a/core/java/android/database/DatabaseUtils.java
|
||||
+++ b/core/java/android/database/DatabaseUtils.java
|
||||
@@ -463,17 +463,31 @@ public class DatabaseUtils {
|
||||
*/
|
||||
public static void appendEscapedSQLString(StringBuilder sb, String sqlString) {
|
||||
sb.append('\'');
|
||||
- if (sqlString.indexOf('\'') != -1) {
|
||||
- int length = sqlString.length();
|
||||
- for (int i = 0; i < length; i++) {
|
||||
- char c = sqlString.charAt(i);
|
||||
- if (c == '\'') {
|
||||
- sb.append('\'');
|
||||
+ int length = sqlString.length();
|
||||
+ for (int i = 0; i < length; i++) {
|
||||
+ char c = sqlString.charAt(i);
|
||||
+ if (Character.isHighSurrogate(c)) {
|
||||
+ if (i == length - 1) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (Character.isLowSurrogate(sqlString.charAt(i + 1))) {
|
||||
+ // add them both
|
||||
+ sb.append(c);
|
||||
+ sb.append(sqlString.charAt(i + 1));
|
||||
+ continue;
|
||||
+ } else {
|
||||
+ // this is a lone surrogate, skip it
|
||||
+ continue;
|
||||
}
|
||||
- sb.append(c);
|
||||
}
|
||||
- } else
|
||||
- sb.append(sqlString);
|
||||
+ if (Character.isLowSurrogate(c)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (c == '\'') {
|
||||
+ sb.append('\'');
|
||||
+ }
|
||||
+ sb.append(c);
|
||||
+ }
|
||||
sb.append('\'');
|
||||
}
|
||||
|
@ -1,136 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Biggers <ebiggers@google.com>
|
||||
Date: Fri, 28 Jul 2023 22:03:03 +0000
|
||||
Subject: [PATCH] RESTRICT AUTOMERGE: SettingsProvider: exclude secure_frp_mode
|
||||
from resets
|
||||
|
||||
When RescueParty detects that a system process is crashing frequently,
|
||||
it tries to recover in various ways, such as by resetting all settings.
|
||||
Unfortunately, this included resetting the secure_frp_mode setting,
|
||||
which is the means by which the system keeps track of whether the
|
||||
Factory Reset Protection (FRP) challenge has been passed yet. With this
|
||||
setting reset, some FRP restrictions went away and it became possible to
|
||||
bypass FRP by setting a new lockscreen credential.
|
||||
|
||||
Fix this by excluding secure_frp_mode from resets.
|
||||
|
||||
Note: currently this bug isn't reproducible on 'main' due to ag/23727749
|
||||
disabling much of RescueParty, but that is a temporary change.
|
||||
|
||||
Bug: 253043065
|
||||
Test: With ag/23727749 reverted and with my fix to prevent
|
||||
com.android.settings from crashing *not* applied, tried repeatedly
|
||||
setting lockscreen credential while in FRP mode, using the
|
||||
smartlock setup activity launched by intent via adb. Verified
|
||||
that although RescueParty is still triggered after 5 attempts,
|
||||
secure_frp_mode is no longer reset (its value remains "1").
|
||||
Test: Verified that secure_frp_mode still gets changed from 1 to 0 when
|
||||
FRP is passed legitimately.
|
||||
Test: atest com.android.providers.settings.SettingsProviderTest
|
||||
Test: atest android.provider.SettingsProviderTest
|
||||
(cherry picked from commit 9890dd7f15c091f7d1a09e4fddb9f85d32015955)
|
||||
(changed Global.SECURE_FRP_MODE to Secure.SECURE_FRP_MODE,
|
||||
needed because this setting was moved in U)
|
||||
(removed static keyword from shouldExcludeSettingFromReset(),
|
||||
needed for compatibility with Java 15 and earlier)
|
||||
(resolved conflict in resetSettingsLocked())
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f0f020c21fd29d8076733e07847e6314172a312e)
|
||||
Merged-In: Id95ed43b9cc2208090064392bcd5dc012710af93
|
||||
Change-Id: Id95ed43b9cc2208090064392bcd5dc012710af93
|
||||
---
|
||||
.../providers/settings/SettingsProvider.java | 17 ++++++++++---
|
||||
.../settings/SettingsProviderTest.java | 25 +++++++++++++++++++
|
||||
2 files changed, 38 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||
index 760b0604a604..1569129c3797 100644
|
||||
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||
@@ -2737,6 +2737,15 @@ public class SettingsProvider extends ContentProvider {
|
||||
return settingsState.getSettingLocked(name);
|
||||
}
|
||||
|
||||
+ private boolean shouldExcludeSettingFromReset(Setting setting, String prefix) {
|
||||
+ // If a prefix was specified, exclude settings whose names don't start with it.
|
||||
+ if (prefix != null && !setting.getName().startsWith(prefix)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Never reset SECURE_FRP_MODE, as it could be abused to bypass FRP via RescueParty.
|
||||
+ return Secure.SECURE_FRP_MODE.equals(setting.getName());
|
||||
+ }
|
||||
+
|
||||
public void resetSettingsLocked(int type, int userId, String packageName, int mode,
|
||||
String tag) {
|
||||
resetSettingsLocked(type, userId, packageName, mode, tag, null);
|
||||
@@ -2757,7 +2766,7 @@ public class SettingsProvider extends ContentProvider {
|
||||
Setting setting = settingsState.getSettingLocked(name);
|
||||
if (packageName.equals(setting.getPackageName())) {
|
||||
if ((tag != null && !tag.equals(setting.getTag()))
|
||||
- || (prefix != null && !setting.getName().startsWith(prefix))) {
|
||||
+ || shouldExcludeSettingFromReset(setting, prefix)) {
|
||||
continue;
|
||||
}
|
||||
if (settingsState.resetSettingLocked(name)) {
|
||||
@@ -2777,7 +2786,7 @@ public class SettingsProvider extends ContentProvider {
|
||||
Setting setting = settingsState.getSettingLocked(name);
|
||||
if (!SettingsState.isSystemPackage(getContext(),
|
||||
setting.getPackageName(), INVALID_UID, userId)) {
|
||||
- if (prefix != null && !setting.getName().startsWith(prefix)) {
|
||||
+ if (shouldExcludeSettingFromReset(setting, prefix)) {
|
||||
continue;
|
||||
}
|
||||
if (settingsState.resetSettingLocked(name)) {
|
||||
@@ -2797,7 +2806,7 @@ public class SettingsProvider extends ContentProvider {
|
||||
Setting setting = settingsState.getSettingLocked(name);
|
||||
if (!SettingsState.isSystemPackage(getContext(),
|
||||
setting.getPackageName(), INVALID_UID, userId)) {
|
||||
- if (prefix != null && !setting.getName().startsWith(prefix)) {
|
||||
+ if (shouldExcludeSettingFromReset(setting, prefix)) {
|
||||
continue;
|
||||
}
|
||||
if (setting.isDefaultFromSystem()) {
|
||||
@@ -2820,7 +2829,7 @@ public class SettingsProvider extends ContentProvider {
|
||||
for (String name : settingsState.getSettingNamesLocked()) {
|
||||
Setting setting = settingsState.getSettingLocked(name);
|
||||
boolean someSettingChanged = false;
|
||||
- if (prefix != null && !setting.getName().startsWith(prefix)) {
|
||||
+ if (shouldExcludeSettingFromReset(setting, prefix)) {
|
||||
continue;
|
||||
}
|
||||
if (setting.isDefaultFromSystem()) {
|
||||
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
|
||||
index 183f5997a6b5..47c15d257ded 100644
|
||||
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
|
||||
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
|
||||
@@ -463,6 +463,31 @@ public class SettingsProviderTest extends BaseSettingsProviderTest {
|
||||
}
|
||||
}
|
||||
|
||||
+ // To prevent FRP bypasses, the SECURE_FRP_MODE setting should not be reset when all other
|
||||
+ // settings are reset. But it should still be possible to explicitly set its value.
|
||||
+ @Test
|
||||
+ public void testSecureFrpModeSettingCannotBeReset() throws Exception {
|
||||
+ final String name = Settings.Secure.SECURE_FRP_MODE;
|
||||
+ final String origValue = getSetting(SETTING_TYPE_GLOBAL, name);
|
||||
+ setSettingViaShell(SETTING_TYPE_GLOBAL, name, "1", false);
|
||||
+ try {
|
||||
+ assertEquals("1", getSetting(SETTING_TYPE_GLOBAL, name));
|
||||
+ for (int type : new int[] { SETTING_TYPE_GLOBAL, SETTING_TYPE_SECURE }) {
|
||||
+ resetSettingsViaShell(type, Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
|
||||
+ resetSettingsViaShell(type, Settings.RESET_MODE_UNTRUSTED_CHANGES);
|
||||
+ resetSettingsViaShell(type, Settings.RESET_MODE_TRUSTED_DEFAULTS);
|
||||
+ }
|
||||
+ // The value should still be "1". It should not have been reset to null.
|
||||
+ assertEquals("1", getSetting(SETTING_TYPE_GLOBAL, name));
|
||||
+ // It should still be possible to explicitly set the value to "0".
|
||||
+ setSettingViaShell(SETTING_TYPE_GLOBAL, name, "0", false);
|
||||
+ assertEquals("0", getSetting(SETTING_TYPE_GLOBAL, name));
|
||||
+ } finally {
|
||||
+ setSettingViaShell(SETTING_TYPE_GLOBAL, name, origValue, false);
|
||||
+ assertEquals(origValue, getSetting(SETTING_TYPE_GLOBAL, name));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private void doTestQueryStringInBracketsViaProviderApiForType(int type) {
|
||||
// Make sure we have a clean slate.
|
||||
deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
|
@ -1,31 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aaron Liu <aaronjli@google.com>
|
||||
Date: Thu, 10 Aug 2023 15:37:24 +0000
|
||||
Subject: [PATCH] Revert "DO NOT MERGE Dismiss keyguard when simpin auth'd
|
||||
and..."
|
||||
|
||||
This reverts commit 09f004722284ef6b9790ddf9338a1708b3f0833c.
|
||||
|
||||
Reason for revert: causing a partner bug
|
||||
Fixes: 295205456
|
||||
Bug: 222446076
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8df038265475bb062ead9eec1749ee92a0f5eb4e)
|
||||
Merged-In: Ida11d98117727f63547b096617a4778bea429e22
|
||||
Change-Id: Ida11d98117727f63547b096617a4778bea429e22
|
||||
---
|
||||
.../src/com/android/keyguard/KeyguardSecurityContainer.java | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
|
||||
index bd555e7360d8..89514a52d0bd 100644
|
||||
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
|
||||
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
|
||||
@@ -529,7 +529,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
|
||||
case SimPuk:
|
||||
// Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
|
||||
SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
|
||||
- if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled(
|
||||
+ if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled(
|
||||
KeyguardUpdateMonitor.getCurrentUser())) {
|
||||
finish = true;
|
||||
eventSubtype = BOUNCER_DISMISS_SIM;
|
@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nan Wu <wnan@google.com>
|
||||
Date: Fri, 16 Jun 2023 14:42:24 +0000
|
||||
Subject: [PATCH] DO NOT MERGE Fix BAL via notification.publicVersion
|
||||
|
||||
We stripped the token that allows app to retrieve their own notification
|
||||
and fire their own PI to launch activities from background. But we
|
||||
forgot to strip the token from notification.publicVersion
|
||||
|
||||
Bug: 278558814
|
||||
Test: NotificationManagerTest#testActivityStartFromRetrievedNotification_isBlocked
|
||||
(cherry picked from commit cf851d81a954f0a6dd0c2fd7defa93932539e7f9)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1896c2e7068c9ec1ab8355d863d7e8107d5d5706)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:75fcbb37617246c43c2af34b12c9ae4b4043f9ac)
|
||||
Merged-In: I8f25d7a5e47890a0496af023149717e1df482f98
|
||||
Change-Id: I8f25d7a5e47890a0496af023149717e1df482f98
|
||||
---
|
||||
core/java/android/app/Notification.java | 7 +++++--
|
||||
.../server/notification/NotificationManagerService.java | 2 +-
|
||||
2 files changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
|
||||
index 7921a89ca96f..d8eefc3d3be4 100644
|
||||
--- a/core/java/android/app/Notification.java
|
||||
+++ b/core/java/android/app/Notification.java
|
||||
@@ -2987,8 +2987,11 @@ public class Notification implements Parcelable
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
- public void setAllowlistToken(@Nullable IBinder token) {
|
||||
- mWhitelistToken = token;
|
||||
+ public void clearAllowlistToken() {
|
||||
+ mWhitelistToken = null;
|
||||
+ if (publicVersion != null) {
|
||||
+ publicVersion.clearAllowlistToken();
|
||||
+ }
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
index d056eac37039..e09491867f91 100755
|
||||
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
||||
@@ -3249,7 +3249,7 @@ public class NotificationManagerService extends SystemService {
|
||||
// Remove background token before returning notification to untrusted app, this
|
||||
// ensures the app isn't able to perform background operations that are
|
||||
// associated with notification interactions.
|
||||
- notification.setAllowlistToken(null);
|
||||
+ notification.clearAllowlistToken();
|
||||
return new StatusBarNotification(
|
||||
sbn.getPackageName(),
|
||||
sbn.getOpPkg(),
|
@ -1,62 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Piyush Mehrotra <piee@google.com>
|
||||
Date: Thu, 27 Jul 2023 19:35:14 +0000
|
||||
Subject: [PATCH] Check caller's uid in backupAgentCreated callback
|
||||
|
||||
AM.backupAgentCreated() should enforce that caller belongs the package called in the API.
|
||||
|
||||
Bug: 289549315
|
||||
Test: atest android.security.cts.ActivityManagerTest#testActivityManager_backupAgentCreated_rejectIfCallerUidNotEqualsPackageUid
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:52b91363583c4e2b68f1a818b067cefe04809285)
|
||||
Merged-In: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d
|
||||
Change-Id: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d
|
||||
---
|
||||
.../server/am/ActivityManagerService.java | 23 +++++++++++++++++--
|
||||
1 file changed, 21 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
|
||||
index ec8841debb7a..3e99e594a702 100644
|
||||
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
|
||||
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
|
||||
@@ -3136,6 +3136,22 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Enforces that the uid of the caller matches the uid of the package.
|
||||
+ *
|
||||
+ * @param packageName the name of the package to match uid against.
|
||||
+ * @param callingUid the uid of the caller.
|
||||
+ * @throws SecurityException if the calling uid doesn't match uid of the package.
|
||||
+ */
|
||||
+ private void enforceCallingPackage(String packageName, int callingUid) {
|
||||
+ final int userId = UserHandle.getUserId(callingUid);
|
||||
+ final int packageUid = getPackageManagerInternalLocked().getPackageUid(packageName,
|
||||
+ /*flags=*/ 0, userId);
|
||||
+ if (packageUid != callingUid) {
|
||||
+ throw new SecurityException(packageName + " does not belong to uid " + callingUid);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public void setPackageScreenCompatMode(String packageName, int mode) {
|
||||
mActivityTaskManager.setPackageScreenCompatMode(packageName, mode);
|
||||
@@ -14345,13 +14361,16 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
// A backup agent has just come up
|
||||
@Override
|
||||
public void backupAgentCreated(String agentPackageName, IBinder agent, int userId) {
|
||||
+ final int callingUid = Binder.getCallingUid();
|
||||
+ enforceCallingPackage(agentPackageName, callingUid);
|
||||
+
|
||||
// Resolve the target user id and enforce permissions.
|
||||
- userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
|
||||
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid,
|
||||
userId, /* allowAll */ false, ALLOW_FULL_ONLY, "backupAgentCreated", null);
|
||||
if (DEBUG_BACKUP) {
|
||||
Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent
|
||||
+ " callingUserId = " + UserHandle.getCallingUserId() + " userId = " + userId
|
||||
- + " callingUid = " + Binder.getCallingUid() + " uid = " + Process.myUid());
|
||||
+ + " callingUid = " + callingUid + " uid = " + Process.myUid());
|
||||
}
|
||||
|
||||
synchronized(this) {
|
@ -1,31 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kumarashishg <kumarashishg@google.com>
|
||||
Date: Thu, 3 Aug 2023 12:01:29 +0000
|
||||
Subject: [PATCH] Use type safe API of readParcelableArray
|
||||
|
||||
Bug: 291299076
|
||||
Test: Build and flash the device and check if it throws exception for
|
||||
non UsbInterface object
|
||||
Test: atest CtsUsbManagerTestCases
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:85d7e6712a9eeeed3bdd68ea3c3862c7e88bfe70)
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:60bfbde79f2ffb012abced55d358fdf6380c0bae)
|
||||
Merged-In: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503
|
||||
Change-Id: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503
|
||||
---
|
||||
core/java/android/hardware/usb/UsbConfiguration.java | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
|
||||
index 66269cb772f8..b25f47b11532 100644
|
||||
--- a/core/java/android/hardware/usb/UsbConfiguration.java
|
||||
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
|
||||
@@ -172,7 +172,8 @@ public class UsbConfiguration implements Parcelable {
|
||||
String name = in.readString();
|
||||
int attributes = in.readInt();
|
||||
int maxPower = in.readInt();
|
||||
- Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
|
||||
+ Parcelable[] interfaces = in.readParcelableArray(
|
||||
+ UsbInterface.class.getClassLoader(), UsbInterface.class);
|
||||
UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower);
|
||||
configuration.setInterfaces(interfaces);
|
||||
return configuration;
|
@ -1,102 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vova Sharaienko <sharaienko@google.com>
|
||||
Date: Mon, 24 Jul 2023 23:19:34 +0000
|
||||
Subject: [PATCH] RESTRICT AUTOMERGE Make log reader thread a class member
|
||||
|
||||
pushedEventThread references class members after detaching. Making
|
||||
pushedEventThread as class member and joining in statsService
|
||||
destructor. Adding a method to stop readLogs thread.
|
||||
|
||||
Ignore-AOSP-First: Bug is in still security triage and fuzzer is
|
||||
crashing on startup.
|
||||
Test: atest statsd_test
|
||||
Test: m statsd_service_fuzzer && adb sync data && adb shell
|
||||
/data/fuzz/arm64/statsd_service_fuzzer/statsd_service_fuzzer -runs=10000
|
||||
Bug: 285645039
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:03de4e4f1a0546fdd3b002651851bee9ffe0e11b)
|
||||
Merged-In: I1e886f9ccb7203714216da061c35e793b2a63d8a
|
||||
Change-Id: I1e886f9ccb7203714216da061c35e793b2a63d8a
|
||||
---
|
||||
cmds/statsd/src/StatsService.cpp | 23 +++++++++++++++++++++--
|
||||
cmds/statsd/src/StatsService.h | 9 +++++++++
|
||||
2 files changed, 30 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
|
||||
index 64b7aae01619..f158723f16a0 100644
|
||||
--- a/cmds/statsd/src/StatsService.cpp
|
||||
+++ b/cmds/statsd/src/StatsService.cpp
|
||||
@@ -205,12 +205,15 @@ StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQ
|
||||
init_system_properties();
|
||||
|
||||
if (mEventQueue != nullptr) {
|
||||
- std::thread pushedEventThread([this] { readLogs(); });
|
||||
- pushedEventThread.detach();
|
||||
+ mLogsReaderThread = std::make_unique<std::thread>([this] { readLogs(); });
|
||||
}
|
||||
}
|
||||
|
||||
StatsService::~StatsService() {
|
||||
+ if (mEventQueue != nullptr) {
|
||||
+ stopReadingLogs();
|
||||
+ mLogsReaderThread->join();
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Runs on a dedicated thread to process pushed events. */
|
||||
@@ -219,6 +222,13 @@ void StatsService::readLogs() {
|
||||
while (1) {
|
||||
// Block until an event is available.
|
||||
auto event = mEventQueue->waitPop();
|
||||
+
|
||||
+ // Below flag will be set when statsd is exiting and log event will be pushed to break
|
||||
+ // out of waitPop.
|
||||
+ if (mIsStopRequested) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
// Pass it to StatsLogProcess to all configs/metrics
|
||||
// At this point, the LogEventQueue is not blocked, so that the socketListener
|
||||
// can read events from the socket and write to buffer to avoid data drop.
|
||||
@@ -1605,6 +1615,15 @@ void StatsService::binderDied(const wp <IBinder>& who) {
|
||||
mPullerManager->SetStatsCompanionService(nullptr);
|
||||
}
|
||||
|
||||
+void StatsService::stopReadingLogs() {
|
||||
+ mIsStopRequested = true;
|
||||
+ // Push this event so that readLogs will process and break out of the loop
|
||||
+ // after the stop is requested.
|
||||
+ int64_t timeStamp;
|
||||
+ std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
|
||||
+ mEventQueue->push(std::move(logEvent), &timeStamp);
|
||||
+}
|
||||
+
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
|
||||
index 5f1335efc2e0..412f1c30ea4d 100644
|
||||
--- a/cmds/statsd/src/StatsService.h
|
||||
+++ b/cmds/statsd/src/StatsService.h
|
||||
@@ -397,6 +397,14 @@ private:
|
||||
*/
|
||||
void set_config(int uid, const string& name, const StatsdConfig& config);
|
||||
|
||||
+ /*
|
||||
+ * This method is used to stop log reader thread.
|
||||
+ */
|
||||
+ void stopReadingLogs();
|
||||
+
|
||||
+ std::atomic<bool> mIsStopRequested = false;
|
||||
+
|
||||
+
|
||||
/**
|
||||
* Tracks the uid <--> package name mapping.
|
||||
*/
|
||||
@@ -439,6 +447,7 @@ private:
|
||||
*/
|
||||
mutable mutex mShellSubscriberMutex;
|
||||
std::shared_ptr<LogEventQueue> mEventQueue;
|
||||
+ std::unique_ptr<std::thread> mLogsReaderThread;
|
||||
|
||||
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
|
||||
FRIEND_TEST(StatsServiceTest, TestAddConfig_simple);
|
@ -1,68 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Songchun Fan <schfan@google.com>
|
||||
Date: Mon, 14 Aug 2023 15:24:11 -0700
|
||||
Subject: [PATCH] verify ringtone URI before setting
|
||||
|
||||
Similar to ag/24422287, but the same URI verification should be done in
|
||||
SettingsProvider as well, which can be called by apps via
|
||||
Settings.System API or ContentProvider APIs without using
|
||||
RingtoneManager.
|
||||
|
||||
BUG: 227201030
|
||||
Test: manual with a test app. Will add a CTS test.
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b234678ec122994ccbfc52ac48aafdad7fdb1ed)
|
||||
Merged-In: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b
|
||||
Change-Id: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b
|
||||
---
|
||||
.../providers/settings/SettingsProvider.java | 31 +++++++++++++++++++
|
||||
1 file changed, 31 insertions(+)
|
||||
|
||||
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||
index 760b0604a604..7cb41275984e 100644
|
||||
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
|
||||
@@ -1734,6 +1734,9 @@ public class SettingsProvider extends ContentProvider {
|
||||
cacheName = Settings.System.ALARM_ALERT_CACHE;
|
||||
}
|
||||
if (cacheName != null) {
|
||||
+ if (!isValidAudioUri(name, value)) {
|
||||
+ return false;
|
||||
+ }
|
||||
final File cacheFile = new File(
|
||||
getRingtoneCacheDir(owningUserId), cacheName);
|
||||
cacheFile.delete();
|
||||
@@ -1766,6 +1769,34 @@ public class SettingsProvider extends ContentProvider {
|
||||
}
|
||||
}
|
||||
|
||||
+ private boolean isValidAudioUri(String name, String uri) {
|
||||
+ if (uri != null) {
|
||||
+ Uri audioUri = Uri.parse(uri);
|
||||
+ if (Settings.AUTHORITY.equals(
|
||||
+ ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) {
|
||||
+ // Don't accept setting the default uri to self-referential URIs like
|
||||
+ // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this
|
||||
+ // setting.
|
||||
+ return false;
|
||||
+ }
|
||||
+ final String mimeType = getContext().getContentResolver().getType(audioUri);
|
||||
+ if (mimeType == null) {
|
||||
+ Slog.e(LOG_TAG,
|
||||
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
|
||||
+ + " ignored: failure to find mimeType (no access from this context?)");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
|
||||
+ || mimeType.equals("application/x-flac"))) {
|
||||
+ Slog.e(LOG_TAG,
|
||||
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
|
||||
+ + " ignored: associated mimeType: " + mimeType + " is not an audio type");
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
private boolean hasWriteSecureSettingsPermission() {
|
||||
// Write secure settings is a more protected permission. If caller has it we are good.
|
||||
if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
|
@ -1,129 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Weng Su <wengsu@google.com>
|
||||
Date: Fri, 7 Jul 2023 19:52:04 +0800
|
||||
Subject: [PATCH] Restrict ApnEditor settings
|
||||
|
||||
- Finish ApnEditor settings if user is not an admin
|
||||
|
||||
- Finish ApnEditor settings if user has DISALLOW_CONFIG_MOBILE_NETWORKS restriction
|
||||
|
||||
Bug: 279902472
|
||||
Test: manual test
|
||||
make RunSettingsRoboTests ROBOTEST_FILTER=ApnEditorTest
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5c2d727b8f9198bf758a4896eda7c9e5385435ff)
|
||||
Merged-In: Iecdbbff7e21dfb11e3ba385858747a220cfd3e04
|
||||
Change-Id: Iecdbbff7e21dfb11e3ba385858747a220cfd3e04
|
||||
---
|
||||
.../android/settings/network/ApnEditor.java | 23 +++++++++++++++
|
||||
.../settings/network/ApnEditorTest.java | 29 +++++++++++++++++++
|
||||
2 files changed, 52 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
|
||||
index 92e689ddd16..cb1c5cce242 100644
|
||||
--- a/src/com/android/settings/network/ApnEditor.java
|
||||
+++ b/src/com/android/settings/network/ApnEditor.java
|
||||
@@ -27,6 +27,7 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
+import android.os.UserManager;
|
||||
import android.provider.Telephony;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.ServiceState;
|
||||
@@ -209,6 +210,11 @@ public class ApnEditor extends SettingsPreferenceFragment
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
+ if (isUserRestricted()) {
|
||||
+ Log.e(TAG, "This setting isn't available due to user restriction.");
|
||||
+ finish();
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
addPreferencesFromResource(R.xml.apn_editor);
|
||||
|
||||
@@ -1203,6 +1209,23 @@ public class ApnEditor extends SettingsPreferenceFragment
|
||||
return userEnteredApnType;
|
||||
}
|
||||
|
||||
+ @VisibleForTesting
|
||||
+ boolean isUserRestricted() {
|
||||
+ UserManager userManager = getContext().getSystemService(UserManager.class);
|
||||
+ if (userManager == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!userManager.isAdminUser()) {
|
||||
+ Log.e(TAG, "User is not an admin");
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
|
||||
+ Log.e(TAG, "User is not allowed to configure mobile network");
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
public static class ErrorDialog extends InstrumentedDialogFragment {
|
||||
|
||||
public static void showError(ApnEditor editor) {
|
||||
diff --git a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
|
||||
index dc14418b596..6251484aad9 100644
|
||||
--- a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
|
||||
+++ b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
|
||||
@@ -33,6 +33,7 @@ import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
+import android.os.UserManager;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -101,6 +102,8 @@ public class ApnEditorTest {
|
||||
|
||||
private ApnEditor mApnEditorUT;
|
||||
private FragmentActivity mActivity;
|
||||
+ @Mock
|
||||
+ private UserManager mUserManager;
|
||||
private Resources mResources;
|
||||
|
||||
@Before
|
||||
@@ -116,6 +119,11 @@ public class ApnEditorTest {
|
||||
doNothing().when(mApnEditorUT).showError();
|
||||
when(mApnEditorUT.getContext()).thenReturn(RuntimeEnvironment.application);
|
||||
|
||||
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
||||
+ doReturn(true).when(mUserManager).isAdminUser();
|
||||
+ doReturn(false).when(mUserManager)
|
||||
+ .hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
|
||||
+
|
||||
setMockPreference(mActivity);
|
||||
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
|
||||
mApnEditorUT.sNotSet = "Not Set";
|
||||
@@ -454,6 +462,27 @@ public class ApnEditorTest {
|
||||
assertThat(ApnEditor.formatInteger("not an int")).isEqualTo("not an int");
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ @Config(shadows = ShadowFragment.class)
|
||||
+ public void onCreate_notAdminUser_shouldFinish() {
|
||||
+ doReturn(false).when(mUserManager).isAdminUser();
|
||||
+
|
||||
+ mApnEditorUT.onCreate(null);
|
||||
+
|
||||
+ verify(mApnEditorUT).finish();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ @Config(shadows = ShadowFragment.class)
|
||||
+ public void onCreate_hasUserRestriction_shouldFinish() {
|
||||
+ doReturn(true).when(mUserManager)
|
||||
+ .hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
|
||||
+
|
||||
+ mApnEditorUT.onCreate(null);
|
||||
+
|
||||
+ verify(mApnEditorUT).finish();
|
||||
+ }
|
||||
+
|
||||
@Test
|
||||
public void onCreate_noAction_shouldFinishAndNoCrash() {
|
||||
doNothing().when(mApnEditorUT).addPreferencesFromResource(anyInt());
|
@ -1,267 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Nikolaienkov <sergeynv@google.com>
|
||||
Date: Tue, 28 Mar 2023 12:22:31 +0200
|
||||
Subject: [PATCH] Fix path traversal vulnerabilities in MediaProvider
|
||||
|
||||
Canonicalize filepath provided by the caller when hanling SCAN_FILE_CALL
|
||||
method call in MediaProvider.
|
||||
Additionally, make sure to check access permission in SCAN_FILE_CALL
|
||||
(using enforceCallingPermissionInternal()).
|
||||
|
||||
Preemptively canonicalize Files provided as an arguments to the public
|
||||
API methods in ModernMediaScanner (scanFile(), scanDirectory() and
|
||||
onDirectoryDirty()) to prevent path traversal attacks.
|
||||
|
||||
Bug: 262244882
|
||||
Test: atest MediaProviderTests
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5d2808f30c9dbe35ddbefeda4845328557569a93)
|
||||
Merged-In: I61e77d69ae857984b819fa0ea27bec5c26a34842
|
||||
Change-Id: I61e77d69ae857984b819fa0ea27bec5c26a34842
|
||||
|
||||
Change-Id: Idf0babc3ab4cae14e69ab7448b914510861a47d7
|
||||
---
|
||||
.../providers/media/MediaProvider.java | 88 +++++++++++++------
|
||||
.../media/scan/LegacyMediaScanner.java | 25 +++++-
|
||||
.../media/scan/ModernMediaScanner.java | 23 ++++-
|
||||
3 files changed, 108 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
|
||||
index 822d69537..0887bd6ae 100644
|
||||
--- a/src/com/android/providers/media/MediaProvider.java
|
||||
+++ b/src/com/android/providers/media/MediaProvider.java
|
||||
@@ -2317,18 +2317,25 @@ public class MediaProvider extends ContentProvider {
|
||||
}
|
||||
|
||||
private static @Nullable String extractRelativePath(@Nullable String data) {
|
||||
- data = getCanonicalPath(data);
|
||||
if (data == null) return null;
|
||||
|
||||
- final Matcher matcher = PATTERN_RELATIVE_PATH.matcher(data);
|
||||
+ final String path;
|
||||
+ try {
|
||||
+ path = getCanonicalPath(data);
|
||||
+ } catch (IOException e) {
|
||||
+ Log.d(TAG, "Unable to get canonical path from invalid data path: " + data, e);
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ final Matcher matcher = PATTERN_RELATIVE_PATH.matcher(path);
|
||||
if (matcher.find()) {
|
||||
- final int lastSlash = data.lastIndexOf('/');
|
||||
+ final int lastSlash = path.lastIndexOf('/');
|
||||
if (lastSlash == -1 || lastSlash < matcher.end()) {
|
||||
// This is a file in the top-level directory, so relative path is "/"
|
||||
// which is different than null, which means unknown path
|
||||
return "/";
|
||||
} else {
|
||||
- return data.substring(matcher.end(), lastSlash + 1);
|
||||
+ return path.substring(matcher.end(), lastSlash + 1);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
@@ -4193,30 +4200,45 @@ public class MediaProvider extends ContentProvider {
|
||||
@Override
|
||||
public Bundle call(String method, String arg, Bundle extras) {
|
||||
switch (method) {
|
||||
- case MediaStore.SCAN_FILE_CALL:
|
||||
+ case MediaStore.SCAN_FILE_CALL: {
|
||||
+ final LocalCallingIdentity token = clearLocalCallingIdentity();
|
||||
+ final CallingIdentity providerToken = clearCallingIdentity();
|
||||
+
|
||||
+ final Uri uri;
|
||||
+ try {
|
||||
+ final Uri fileUri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
+ File file;
|
||||
+ try {
|
||||
+ file = getCanonicalFile(fileUri.getPath());
|
||||
+ } catch (IOException e) {
|
||||
+ file = null;
|
||||
+ }
|
||||
+
|
||||
+ uri = file != null ? MediaScanner.instance(getContext()).scanFile(file) : null;
|
||||
+ } finally {
|
||||
+ restoreCallingIdentity(providerToken);
|
||||
+ restoreLocalCallingIdentity(token);
|
||||
+ }
|
||||
+
|
||||
+ final Bundle res = new Bundle();
|
||||
+ res.putParcelable(Intent.EXTRA_STREAM, uri);
|
||||
+ return res;
|
||||
+ }
|
||||
case MediaStore.SCAN_VOLUME_CALL: {
|
||||
final LocalCallingIdentity token = clearLocalCallingIdentity();
|
||||
final CallingIdentity providerToken = clearCallingIdentity();
|
||||
+
|
||||
try {
|
||||
final Uri uri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
final File file = new File(uri.getPath());
|
||||
- final Bundle res = new Bundle();
|
||||
- switch (method) {
|
||||
- case MediaStore.SCAN_FILE_CALL:
|
||||
- res.putParcelable(Intent.EXTRA_STREAM,
|
||||
- MediaScanner.instance(getContext()).scanFile(file));
|
||||
- break;
|
||||
- case MediaStore.SCAN_VOLUME_CALL:
|
||||
- MediaService.onScanVolume(getContext(), Uri.fromFile(file));
|
||||
- break;
|
||||
- }
|
||||
- return res;
|
||||
+ MediaService.onScanVolume(getContext(), Uri.fromFile(file));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
restoreCallingIdentity(providerToken);
|
||||
restoreLocalCallingIdentity(token);
|
||||
}
|
||||
+ return Bundle.EMPTY;
|
||||
}
|
||||
case MediaStore.UNHIDE_CALL: {
|
||||
throw new UnsupportedOperationException();
|
||||
@@ -6705,14 +6727,30 @@ public class MediaProvider extends ContentProvider {
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
- @Nullable
|
||||
- private static String getCanonicalPath(@Nullable String path) {
|
||||
- if (path == null) return null;
|
||||
- try {
|
||||
- return new File(path).getCanonicalPath();
|
||||
- } catch (IOException e) {
|
||||
- Log.d(TAG, "Unable to get canonical path from invalid data path: " + path, e);
|
||||
- return null;
|
||||
- }
|
||||
+ /**
|
||||
+ * Returns the canonical {@link File} for the provided abstract pathname.
|
||||
+ *
|
||||
+ * @return The canonical pathname string denoting the same file or directory as this abstract
|
||||
+ * pathname
|
||||
+ * @see File#getCanonicalFile()
|
||||
+ */
|
||||
+ @NonNull
|
||||
+ public static File getCanonicalFile(@NonNull String path) throws IOException {
|
||||
+ Objects.requireNonNull(path);
|
||||
+ return new File(path).getCanonicalFile();
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the canonical pathname string of the provided abstract pathname.
|
||||
+ *
|
||||
+ * @return The canonical pathname string denoting the same file or directory as this abstract
|
||||
+ * pathname.
|
||||
+ * @see File#getCanonicalPath()
|
||||
+ */
|
||||
+ @NonNull
|
||||
+ public static String getCanonicalPath(@NonNull String path) throws IOException {
|
||||
+ Objects.requireNonNull(path);
|
||||
+ return new File(path).getCanonicalPath();
|
||||
+ }
|
||||
+
|
||||
}
|
||||
diff --git a/src/com/android/providers/media/scan/LegacyMediaScanner.java b/src/com/android/providers/media/scan/LegacyMediaScanner.java
|
||||
index 5041265cb..eb28b5b59 100644
|
||||
--- a/src/com/android/providers/media/scan/LegacyMediaScanner.java
|
||||
+++ b/src/com/android/providers/media/scan/LegacyMediaScanner.java
|
||||
@@ -16,16 +16,23 @@
|
||||
|
||||
package com.android.providers.media.scan;
|
||||
|
||||
+import static java.util.Objects.requireNonNull;
|
||||
+
|
||||
+import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Trace;
|
||||
import android.provider.MediaStore;
|
||||
+import android.util.Log;
|
||||
|
||||
import libcore.net.MimeUtils;
|
||||
|
||||
import java.io.File;
|
||||
+import java.io.IOException;
|
||||
|
||||
public class LegacyMediaScanner implements MediaScanner {
|
||||
+ private static final String TAG = "LegacyMediaScanner";
|
||||
+
|
||||
private final Context mContext;
|
||||
|
||||
public LegacyMediaScanner(Context context) {
|
||||
@@ -39,6 +46,14 @@ public class LegacyMediaScanner implements MediaScanner {
|
||||
|
||||
@Override
|
||||
public void scanDirectory(File file) {
|
||||
+ requireNonNull(file);
|
||||
+ try {
|
||||
+ file = file.getCanonicalFile();
|
||||
+ } catch (IOException e) {
|
||||
+ Log.e(TAG, "Couldn't canonicalize directory to scan" + file, e);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
final String path = file.getAbsolutePath();
|
||||
final String volumeName = MediaStore.getVolumeName(file);
|
||||
|
||||
@@ -52,7 +67,15 @@ public class LegacyMediaScanner implements MediaScanner {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Uri scanFile(File file) {
|
||||
+ public Uri scanFile(@NonNull File file) {
|
||||
+ requireNonNull(file);
|
||||
+ try {
|
||||
+ file = file.getCanonicalFile();
|
||||
+ } catch (IOException e) {
|
||||
+ Log.e(TAG, "Couldn't canonicalize file to scan" + file, e);
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
final String path = file.getAbsolutePath();
|
||||
final String volumeName = MediaStore.getVolumeName(file);
|
||||
|
||||
diff --git a/src/com/android/providers/media/scan/ModernMediaScanner.java b/src/com/android/providers/media/scan/ModernMediaScanner.java
|
||||
index fe0e5cf78..f8f29fb4e 100644
|
||||
--- a/src/com/android/providers/media/scan/ModernMediaScanner.java
|
||||
+++ b/src/com/android/providers/media/scan/ModernMediaScanner.java
|
||||
@@ -39,6 +39,8 @@ import static android.provider.MediaStore.UNKNOWN_STRING;
|
||||
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||
|
||||
+import static java.util.Objects.requireNonNull;
|
||||
+
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.CurrentTimeSecondsLong;
|
||||
import android.annotation.NonNull;
|
||||
@@ -161,7 +163,15 @@ public class ModernMediaScanner implements MediaScanner {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void scanDirectory(File file) {
|
||||
+ public void scanDirectory(@NonNull File file) {
|
||||
+ requireNonNull(file);
|
||||
+ try {
|
||||
+ file = file.getCanonicalFile();
|
||||
+ } catch (IOException e) {
|
||||
+ Log.e(TAG, "Couldn't canonicalize directory to scan" + file, e);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
try (Scan scan = new Scan(file)) {
|
||||
scan.run();
|
||||
} catch (OperationCanceledException ignored) {
|
||||
@@ -169,7 +179,16 @@ public class ModernMediaScanner implements MediaScanner {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Uri scanFile(File file) {
|
||||
+ @Nullable
|
||||
+ public Uri scanFile(@NonNull File file) {
|
||||
+ requireNonNull(file);
|
||||
+ try {
|
||||
+ file = file.getCanonicalFile();
|
||||
+ } catch (IOException e) {
|
||||
+ Log.e(TAG, "Couldn't canonicalize file to scan" + file, e);
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
try (Scan scan = new Scan(file)) {
|
||||
scan.run();
|
||||
return scan.mFirstResult;
|
@ -1,818 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aishwarya Mallampati <amallampati@google.com>
|
||||
Date: Wed, 23 Aug 2023 18:30:46 +0000
|
||||
Subject: [PATCH] DO NOT MERGE Block access to sms/mms db from work profile.
|
||||
|
||||
Bug: 289242655
|
||||
Test: Manually verified work profile cannot access personal sms by
|
||||
following steps mentioned in b/289242655#comment26
|
||||
- atest SmsProviderTest
|
||||
- atest MmsProviderTest
|
||||
- atest SmsBackupRestoreTest
|
||||
- QA performed regression testing and confirmed fix is working as intended here: b/294459052#comment30
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:950a7e5a4bf1b38e846fe00642105479efded57d)
|
||||
Merged-In: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277
|
||||
Change-Id: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277
|
||||
---
|
||||
.../providers/telephony/MmsProvider.java | 41 ++++-
|
||||
.../telephony/MmsSmsDatabaseHelper.java | 156 +++++++++-------
|
||||
.../providers/telephony/MmsSmsProvider.java | 36 ++++
|
||||
.../providers/telephony/SmsProvider.java | 35 ++++
|
||||
.../providers/telephony/MmsProviderTest.java | 173 ++++++++++++++++++
|
||||
.../telephony/MmsProviderTestable.java | 77 ++++++++
|
||||
.../providers/telephony/SmsProviderTest.java | 55 ++++++
|
||||
7 files changed, 503 insertions(+), 70 deletions(-)
|
||||
create mode 100644 tests/src/com/android/providers/telephony/MmsProviderTest.java
|
||||
create mode 100644 tests/src/com/android/providers/telephony/MmsProviderTestable.java
|
||||
|
||||
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
|
||||
index 7546c246..9f58fc33 100644
|
||||
--- a/src/com/android/providers/telephony/MmsProvider.java
|
||||
+++ b/src/com/android/providers/telephony/MmsProvider.java
|
||||
@@ -25,6 +25,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
+import android.database.MatrixCursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
@@ -34,6 +35,7 @@ import android.os.Binder;
|
||||
import android.os.FileUtils;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.UserHandle;
|
||||
+import android.os.UserManager;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.Telephony;
|
||||
import android.provider.Telephony.CanonicalAddressesColumns;
|
||||
@@ -50,6 +52,8 @@ import android.text.TextUtils;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
|
||||
+import com.android.internal.annotations.VisibleForTesting;
|
||||
+
|
||||
import com.google.android.mms.pdu.PduHeaders;
|
||||
import com.google.android.mms.util.DownloadDrmHelper;
|
||||
|
||||
@@ -94,6 +98,16 @@ public class MmsProvider extends ContentProvider {
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection,
|
||||
String selection, String[] selectionArgs, String sortOrder) {
|
||||
+ Cursor emptyCursor = new MatrixCursor((projection == null) ?
|
||||
+ (new String[] {}) : projection);
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to query mms, return empty cursor.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to query MMS.");
|
||||
+ return emptyCursor;
|
||||
+ }
|
||||
+
|
||||
// First check if a restricted view of the "pdu" table should be used based on the
|
||||
// caller's identity. Only system, phone or the default sms app can have full access
|
||||
// of mms data. For other apps, we present a restricted view which only contains sent
|
||||
@@ -307,6 +321,14 @@ public class MmsProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to insert mms, return null.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to insert MMS.");
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
final int callerUid = Binder.getCallingUid();
|
||||
final String callerPkg = getCallingPackage();
|
||||
int msgBox = Mms.MESSAGE_BOX_ALL;
|
||||
@@ -622,6 +644,14 @@ public class MmsProvider extends ContentProvider {
|
||||
@Override
|
||||
public int delete(Uri uri, String selection,
|
||||
String[] selectionArgs) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to delete mms, return 0.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to delete MMS.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
int match = sURLMatcher.match(uri);
|
||||
if (LOCAL_LOGV) {
|
||||
Log.v(TAG, "Delete uri=" + uri + ", match=" + match);
|
||||
@@ -774,6 +804,14 @@ public class MmsProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to update mms, return 0.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to update MMS.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
// The _data column is filled internally in MmsProvider, so this check is just to avoid
|
||||
// it from being inadvertently set. This is not supposed to be a protection against
|
||||
// malicious attack, since sql injection could still be attempted to bypass the check. On
|
||||
@@ -1062,7 +1100,8 @@ public class MmsProvider extends ContentProvider {
|
||||
sURLMatcher.addURI("mms", "resetFilePerm/*", MMS_PART_RESET_FILE_PERMISSION);
|
||||
}
|
||||
|
||||
- private SQLiteOpenHelper mOpenHelper;
|
||||
+ @VisibleForTesting
|
||||
+ public SQLiteOpenHelper mOpenHelper;
|
||||
|
||||
private static String concatSelections(String selection1, String selection2) {
|
||||
if (TextUtils.isEmpty(selection1)) {
|
||||
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
|
||||
index afde117a..13abc8fc 100644
|
||||
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
|
||||
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
|
||||
@@ -721,79 +721,97 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
+ @VisibleForTesting
|
||||
+ public static String CREATE_ADDR_TABLE_STR =
|
||||
+ "CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" +
|
||||
+ Addr._ID + " INTEGER PRIMARY KEY," +
|
||||
+ Addr.MSG_ID + " INTEGER," +
|
||||
+ Addr.CONTACT_ID + " INTEGER," +
|
||||
+ Addr.ADDRESS + " TEXT," +
|
||||
+ Addr.TYPE + " INTEGER," +
|
||||
+ Addr.CHARSET + " INTEGER);";
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ public static String CREATE_PART_TABLE_STR =
|
||||
+ "CREATE TABLE " + MmsProvider.TABLE_PART + " (" +
|
||||
+ Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
+ Part.MSG_ID + " INTEGER," +
|
||||
+ Part.SEQ + " INTEGER DEFAULT 0," +
|
||||
+ Part.CONTENT_TYPE + " TEXT," +
|
||||
+ Part.NAME + " TEXT," +
|
||||
+ Part.CHARSET + " INTEGER," +
|
||||
+ Part.CONTENT_DISPOSITION + " TEXT," +
|
||||
+ Part.FILENAME + " TEXT," +
|
||||
+ Part.CONTENT_ID + " TEXT," +
|
||||
+ Part.CONTENT_LOCATION + " TEXT," +
|
||||
+ Part.CT_START + " INTEGER," +
|
||||
+ Part.CT_TYPE + " TEXT," +
|
||||
+ Part._DATA + " TEXT," +
|
||||
+ Part.TEXT + " TEXT);";
|
||||
+
|
||||
+ public static String CREATE_PDU_TABLE_STR =
|
||||
+ "CREATE TABLE " + MmsProvider.TABLE_PDU + " (" +
|
||||
+ Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
+ Mms.THREAD_ID + " INTEGER," +
|
||||
+ Mms.DATE + " INTEGER," +
|
||||
+ Mms.DATE_SENT + " INTEGER DEFAULT 0," +
|
||||
+ Mms.MESSAGE_BOX + " INTEGER," +
|
||||
+ Mms.READ + " INTEGER DEFAULT 0," +
|
||||
+ Mms.MESSAGE_ID + " TEXT," +
|
||||
+ Mms.SUBJECT + " TEXT," +
|
||||
+ Mms.SUBJECT_CHARSET + " INTEGER," +
|
||||
+ Mms.CONTENT_TYPE + " TEXT," +
|
||||
+ Mms.CONTENT_LOCATION + " TEXT," +
|
||||
+ Mms.EXPIRY + " INTEGER," +
|
||||
+ Mms.MESSAGE_CLASS + " TEXT," +
|
||||
+ Mms.MESSAGE_TYPE + " INTEGER," +
|
||||
+ Mms.MMS_VERSION + " INTEGER," +
|
||||
+ Mms.MESSAGE_SIZE + " INTEGER," +
|
||||
+ Mms.PRIORITY + " INTEGER," +
|
||||
+ Mms.READ_REPORT + " INTEGER," +
|
||||
+ Mms.REPORT_ALLOWED + " INTEGER," +
|
||||
+ Mms.RESPONSE_STATUS + " INTEGER," +
|
||||
+ Mms.STATUS + " INTEGER," +
|
||||
+ Mms.TRANSACTION_ID + " TEXT," +
|
||||
+ Mms.RETRIEVE_STATUS + " INTEGER," +
|
||||
+ Mms.RETRIEVE_TEXT + " TEXT," +
|
||||
+ Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," +
|
||||
+ Mms.READ_STATUS + " INTEGER," +
|
||||
+ Mms.CONTENT_CLASS + " INTEGER," +
|
||||
+ Mms.RESPONSE_TEXT + " TEXT," +
|
||||
+ Mms.DELIVERY_TIME + " INTEGER," +
|
||||
+ Mms.DELIVERY_REPORT + " INTEGER," +
|
||||
+ Mms.LOCKED + " INTEGER DEFAULT 0," +
|
||||
+ Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT "
|
||||
+ + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
|
||||
+ Mms.SEEN + " INTEGER DEFAULT 0," +
|
||||
+ Mms.CREATOR + " TEXT," +
|
||||
+ Mms.TEXT_ONLY + " INTEGER DEFAULT 0);";
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ public static String CREATE_RATE_TABLE_STR =
|
||||
+ "CREATE TABLE " + MmsProvider.TABLE_RATE + " (" +
|
||||
+ Rate.SENT_TIME + " INTEGER);";
|
||||
+
|
||||
+ @VisibleForTesting
|
||||
+ public static String CREATE_DRM_TABLE_STR =
|
||||
+ "CREATE TABLE " + MmsProvider.TABLE_DRM + " (" +
|
||||
+ BaseColumns._ID + " INTEGER PRIMARY KEY," +
|
||||
+ "_data TEXT);";
|
||||
+
|
||||
@VisibleForTesting
|
||||
void createMmsTables(SQLiteDatabase db) {
|
||||
// N.B.: Whenever the columns here are changed, the columns in
|
||||
// {@ref MmsSmsProvider} must be changed to match.
|
||||
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PDU + " (" +
|
||||
- Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
- Mms.THREAD_ID + " INTEGER," +
|
||||
- Mms.DATE + " INTEGER," +
|
||||
- Mms.DATE_SENT + " INTEGER DEFAULT 0," +
|
||||
- Mms.MESSAGE_BOX + " INTEGER," +
|
||||
- Mms.READ + " INTEGER DEFAULT 0," +
|
||||
- Mms.MESSAGE_ID + " TEXT," +
|
||||
- Mms.SUBJECT + " TEXT," +
|
||||
- Mms.SUBJECT_CHARSET + " INTEGER," +
|
||||
- Mms.CONTENT_TYPE + " TEXT," +
|
||||
- Mms.CONTENT_LOCATION + " TEXT," +
|
||||
- Mms.EXPIRY + " INTEGER," +
|
||||
- Mms.MESSAGE_CLASS + " TEXT," +
|
||||
- Mms.MESSAGE_TYPE + " INTEGER," +
|
||||
- Mms.MMS_VERSION + " INTEGER," +
|
||||
- Mms.MESSAGE_SIZE + " INTEGER," +
|
||||
- Mms.PRIORITY + " INTEGER," +
|
||||
- Mms.READ_REPORT + " INTEGER," +
|
||||
- Mms.REPORT_ALLOWED + " INTEGER," +
|
||||
- Mms.RESPONSE_STATUS + " INTEGER," +
|
||||
- Mms.STATUS + " INTEGER," +
|
||||
- Mms.TRANSACTION_ID + " TEXT," +
|
||||
- Mms.RETRIEVE_STATUS + " INTEGER," +
|
||||
- Mms.RETRIEVE_TEXT + " TEXT," +
|
||||
- Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," +
|
||||
- Mms.READ_STATUS + " INTEGER," +
|
||||
- Mms.CONTENT_CLASS + " INTEGER," +
|
||||
- Mms.RESPONSE_TEXT + " TEXT," +
|
||||
- Mms.DELIVERY_TIME + " INTEGER," +
|
||||
- Mms.DELIVERY_REPORT + " INTEGER," +
|
||||
- Mms.LOCKED + " INTEGER DEFAULT 0," +
|
||||
- Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT "
|
||||
- + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
|
||||
- Mms.SEEN + " INTEGER DEFAULT 0," +
|
||||
- Mms.CREATOR + " TEXT," +
|
||||
- Mms.TEXT_ONLY + " INTEGER DEFAULT 0" +
|
||||
- ");");
|
||||
-
|
||||
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" +
|
||||
- Addr._ID + " INTEGER PRIMARY KEY," +
|
||||
- Addr.MSG_ID + " INTEGER," +
|
||||
- Addr.CONTACT_ID + " INTEGER," +
|
||||
- Addr.ADDRESS + " TEXT," +
|
||||
- Addr.TYPE + " INTEGER," +
|
||||
- Addr.CHARSET + " INTEGER);");
|
||||
-
|
||||
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PART + " (" +
|
||||
- Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
- Part.MSG_ID + " INTEGER," +
|
||||
- Part.SEQ + " INTEGER DEFAULT 0," +
|
||||
- Part.CONTENT_TYPE + " TEXT," +
|
||||
- Part.NAME + " TEXT," +
|
||||
- Part.CHARSET + " INTEGER," +
|
||||
- Part.CONTENT_DISPOSITION + " TEXT," +
|
||||
- Part.FILENAME + " TEXT," +
|
||||
- Part.CONTENT_ID + " TEXT," +
|
||||
- Part.CONTENT_LOCATION + " TEXT," +
|
||||
- Part.CT_START + " INTEGER," +
|
||||
- Part.CT_TYPE + " TEXT," +
|
||||
- Part._DATA + " TEXT," +
|
||||
- Part.TEXT + " TEXT);");
|
||||
-
|
||||
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_RATE + " (" +
|
||||
- Rate.SENT_TIME + " INTEGER);");
|
||||
-
|
||||
- db.execSQL("CREATE TABLE " + MmsProvider.TABLE_DRM + " (" +
|
||||
- BaseColumns._ID + " INTEGER PRIMARY KEY," +
|
||||
- "_data TEXT);");
|
||||
+ db.execSQL(CREATE_PDU_TABLE_STR);
|
||||
+
|
||||
+ db.execSQL(CREATE_ADDR_TABLE_STR);
|
||||
+
|
||||
+ db.execSQL(CREATE_PART_TABLE_STR);
|
||||
+
|
||||
+ db.execSQL(CREATE_RATE_TABLE_STR);
|
||||
+
|
||||
+ db.execSQL(CREATE_DRM_TABLE_STR);
|
||||
|
||||
// Restricted view of pdu table, only sent/received messages without wap pushes
|
||||
db.execSQL("CREATE VIEW " + MmsProvider.VIEW_PDU_RESTRICTED + " AS " +
|
||||
diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java
|
||||
index dbf85aed..9877a44a 100644
|
||||
--- a/src/com/android/providers/telephony/MmsSmsProvider.java
|
||||
+++ b/src/com/android/providers/telephony/MmsSmsProvider.java
|
||||
@@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
+import android.database.MatrixCursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
@@ -30,6 +31,7 @@ import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
+import android.os.UserManager;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.Telephony;
|
||||
import android.provider.Telephony.CanonicalAddressesColumns;
|
||||
@@ -323,6 +325,16 @@ public class MmsSmsProvider extends ContentProvider {
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection,
|
||||
String selection, String[] selectionArgs, String sortOrder) {
|
||||
+ Cursor emptyCursor = new MatrixCursor((projection == null) ?
|
||||
+ (new String[] {}) : projection);
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to query mms/sms, return empty cursor.
|
||||
+ Log.e(LOG_TAG, "Managed profile is not allowed to query MMS/SMS.");
|
||||
+ return emptyCursor;
|
||||
+ }
|
||||
+
|
||||
// First check if restricted views of the "sms" and "pdu" tables should be used based on the
|
||||
// caller's identity. Only system, phone or the default sms app can have full access
|
||||
// of sms/mms data. For other apps, we present a restricted view which only contains sent
|
||||
@@ -1226,6 +1238,14 @@ public class MmsSmsProvider extends ContentProvider {
|
||||
@Override
|
||||
public int delete(Uri uri, String selection,
|
||||
String[] selectionArgs) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to delete mms/sms, return 0.
|
||||
+ Log.e(LOG_TAG, "Managed profile is not allowed to delete MMS/SMS.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
Context context = getContext();
|
||||
int affectedRows = 0;
|
||||
@@ -1282,6 +1302,14 @@ public class MmsSmsProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to insert mms/sms, return null.
|
||||
+ Log.e(LOG_TAG, "Managed profile is not allowed to insert MMS/SMS.");
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
int matchIndex = URI_MATCHER.match(uri);
|
||||
|
||||
@@ -1298,6 +1326,14 @@ public class MmsSmsProvider extends ContentProvider {
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values,
|
||||
String selection, String[] selectionArgs) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to update mms/sms, return 0.
|
||||
+ Log.e(LOG_TAG, "Managed profile is not allowed to update MMS/SMS.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
final int callerUid = Binder.getCallingUid();
|
||||
final String callerPkg = getCallingPackage();
|
||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
|
||||
index 1213c379..85a224bd 100644
|
||||
--- a/src/com/android/providers/telephony/SmsProvider.java
|
||||
+++ b/src/com/android/providers/telephony/SmsProvider.java
|
||||
@@ -32,6 +32,7 @@ import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.UserHandle;
|
||||
+import android.os.UserManager;
|
||||
import android.provider.Contacts;
|
||||
import android.provider.Telephony;
|
||||
import android.provider.Telephony.MmsSms;
|
||||
@@ -113,6 +114,16 @@ public class SmsProvider extends ContentProvider {
|
||||
@Override
|
||||
public Cursor query(Uri url, String[] projectionIn, String selection,
|
||||
String[] selectionArgs, String sort) {
|
||||
+ Cursor emptyCursor = new MatrixCursor((projectionIn == null) ?
|
||||
+ (new String[] {}) : projectionIn);
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to query sms, return empty cursor.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to query SMS.");
|
||||
+ return emptyCursor;
|
||||
+ }
|
||||
+
|
||||
// First check if a restricted view of the "sms" table should be used based on the
|
||||
// caller's identity. Only system, phone or the default sms app can have full access
|
||||
// of sms data. For other apps, we present a restricted view which only contains sent
|
||||
@@ -468,6 +479,14 @@ public class SmsProvider extends ContentProvider {
|
||||
}
|
||||
|
||||
private Uri insertInner(Uri url, ContentValues initialValues, int callerUid, String callerPkg) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to insert sms, return null.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to insert SMS.");
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
ContentValues values;
|
||||
long rowID;
|
||||
int type = Sms.MESSAGE_TYPE_ALL;
|
||||
@@ -656,6 +675,14 @@ public class SmsProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public int delete(Uri url, String where, String[] whereArgs) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to delete sms, return 0.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to delete SMS.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
int count;
|
||||
int match = sURLMatcher.match(url);
|
||||
SQLiteDatabase db = getWritableDatabase(match);
|
||||
@@ -758,6 +785,14 @@ public class SmsProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
|
||||
+ UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||
+ if ((userManager != null) && (userManager.isManagedProfile(
|
||||
+ Binder.getCallingUserHandle().getIdentifier()))) {
|
||||
+ // If work profile is trying to update sms, return 0.
|
||||
+ Log.e(TAG, "Managed profile is not allowed to update SMS.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
final int callerUid = Binder.getCallingUid();
|
||||
final String callerPkg = getCallingPackage();
|
||||
int count = 0;
|
||||
diff --git a/tests/src/com/android/providers/telephony/MmsProviderTest.java b/tests/src/com/android/providers/telephony/MmsProviderTest.java
|
||||
new file mode 100644
|
||||
index 00000000..e1010e01
|
||||
--- /dev/null
|
||||
+++ b/tests/src/com/android/providers/telephony/MmsProviderTest.java
|
||||
@@ -0,0 +1,173 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2023 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.providers.telephony;
|
||||
+
|
||||
+import static org.mockito.ArgumentMatchers.anyInt;
|
||||
+import static org.mockito.ArgumentMatchers.anyString;
|
||||
+import static org.mockito.ArgumentMatchers.eq;
|
||||
+import static org.mockito.Mockito.mock;
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
+import android.app.AppOpsManager;
|
||||
+import android.content.ContentValues;
|
||||
+import android.content.Context;
|
||||
+import android.content.pm.PackageManager;
|
||||
+import android.content.pm.ProviderInfo;
|
||||
+import android.database.ContentObserver;
|
||||
+import android.database.Cursor;
|
||||
+import android.net.Uri;
|
||||
+import android.os.UserManager;
|
||||
+import android.provider.Telephony;
|
||||
+import android.telephony.TelephonyManager;
|
||||
+import android.test.mock.MockContentResolver;
|
||||
+import android.util.Log;
|
||||
+
|
||||
+import junit.framework.TestCase;
|
||||
+
|
||||
+import org.junit.Test;
|
||||
+import org.mockito.Mock;
|
||||
+import org.mockito.MockitoAnnotations;
|
||||
+
|
||||
+public class MmsProviderTest extends TestCase {
|
||||
+ private static final String TAG = "MmsProviderTest";
|
||||
+
|
||||
+ @Mock private Context mContext;
|
||||
+ private MockContentResolver mContentResolver;
|
||||
+ private MmsProviderTestable mMmsProviderTestable;
|
||||
+ @Mock private PackageManager mPackageManager;
|
||||
+
|
||||
+ private int notifyChangeCount;
|
||||
+ private UserManager mUserManager;
|
||||
+
|
||||
+ @Override
|
||||
+ protected void setUp() throws Exception {
|
||||
+ super.setUp();
|
||||
+ MockitoAnnotations.initMocks(this);
|
||||
+ mMmsProviderTestable = new MmsProviderTestable();
|
||||
+ mUserManager = mock(UserManager.class);
|
||||
+
|
||||
+ // setup mocks
|
||||
+ when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE)))
|
||||
+ .thenReturn(mock(AppOpsManager.class));
|
||||
+ when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE)))
|
||||
+ .thenReturn(mock(TelephonyManager.class));
|
||||
+ when(mContext.getSystemService(eq(Context.USER_SERVICE)))
|
||||
+ .thenReturn(mUserManager);
|
||||
+
|
||||
+ when(mContext.checkCallingOrSelfPermission(anyString()))
|
||||
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
|
||||
+ when(mContext.getUserId()).thenReturn(0);
|
||||
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
+
|
||||
+ /**
|
||||
+ * This is used to give the MmsProviderTest a mocked context which takes a
|
||||
+ * SmsProvider and attaches it to the ContentResolver with telephony authority.
|
||||
+ * The mocked context also gives WRITE_APN_SETTINGS permissions
|
||||
+ */
|
||||
+ mContentResolver = new MockContentResolver() {
|
||||
+ @Override
|
||||
+ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
|
||||
+ int userHandle) {
|
||||
+ notifyChangeCount++;
|
||||
+ }
|
||||
+ };
|
||||
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
|
||||
+
|
||||
+ // Add authority="mms" to given mmsProvider
|
||||
+ ProviderInfo providerInfo = new ProviderInfo();
|
||||
+ providerInfo.authority = "mms";
|
||||
+
|
||||
+ // Add context to given mmsProvider
|
||||
+ mMmsProviderTestable.attachInfoForTesting(mContext, providerInfo);
|
||||
+ Log.d(TAG, "MockContextWithProvider: mmsProvider.getContext(): "
|
||||
+ + mMmsProviderTestable.getContext());
|
||||
+
|
||||
+ // Add given MmsProvider to mResolver with authority="mms" so that
|
||||
+ // mResolver can send queries to mMmsProvider
|
||||
+ mContentResolver.addProvider("mms", mMmsProviderTestable);
|
||||
+ Log.d(TAG, "MockContextWithProvider: Add MmsProvider to mResolver");
|
||||
+ notifyChangeCount = 0;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected void tearDown() throws Exception {
|
||||
+ super.tearDown();
|
||||
+ mMmsProviderTestable.closeDatabase();
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testInsertMms() {
|
||||
+ final ContentValues values = new ContentValues();
|
||||
+ values.put(Telephony.Mms.READ, 1);
|
||||
+ values.put(Telephony.Mms.SEEN, 1);
|
||||
+ values.put(Telephony.Mms.SUBSCRIPTION_ID, 1);
|
||||
+ values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_ALL);
|
||||
+ values.put(Telephony.Mms.TEXT_ONLY, 1);
|
||||
+ values.put(Telephony.Mms.THREAD_ID, 1);
|
||||
+
|
||||
+ Uri expected = Uri.parse("content://mms/1");
|
||||
+ Uri actual = mContentResolver.insert(Telephony.Mms.CONTENT_URI, values);
|
||||
+
|
||||
+ assertEquals(expected, actual);
|
||||
+ assertEquals(1, notifyChangeCount);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testInsertUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try {
|
||||
+ assertNull(mContentResolver.insert(Telephony.Mms.CONTENT_URI, null));
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Error inserting mms: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testQueryUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try (Cursor cursor = mContentResolver.query(Telephony.Mms.CONTENT_URI,
|
||||
+ null, null, null, null)) {
|
||||
+ assertEquals(0, cursor.getCount());
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Exception in getting count: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testUpdateUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try {
|
||||
+ assertEquals(0, mContentResolver.update(Telephony.Mms.CONTENT_URI, null, null, null));
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Exception in updating mms: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testDeleteUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try {
|
||||
+ assertEquals(0, mContentResolver.delete(Telephony.Mms.CONTENT_URI, null, null));
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Exception in deleting mms: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/src/com/android/providers/telephony/MmsProviderTestable.java b/tests/src/com/android/providers/telephony/MmsProviderTestable.java
|
||||
new file mode 100644
|
||||
index 00000000..cea411be
|
||||
--- /dev/null
|
||||
+++ b/tests/src/com/android/providers/telephony/MmsProviderTestable.java
|
||||
@@ -0,0 +1,77 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2023 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+package com.android.providers.telephony;
|
||||
+
|
||||
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_ADDR_TABLE_STR;
|
||||
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_DRM_TABLE_STR;
|
||||
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_PART_TABLE_STR;
|
||||
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_PDU_TABLE_STR;
|
||||
+import static com.android.providers.telephony.MmsSmsDatabaseHelper.CREATE_RATE_TABLE_STR;
|
||||
+
|
||||
+import android.database.sqlite.SQLiteDatabase;
|
||||
+import android.database.sqlite.SQLiteOpenHelper;
|
||||
+import android.util.Log;
|
||||
+
|
||||
+/**
|
||||
+ * A subclass of MmsProvider used for testing on an in-memory database
|
||||
+ */
|
||||
+public class MmsProviderTestable extends MmsProvider {
|
||||
+ private static final String TAG = "MmsProviderTestable";
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean onCreate() {
|
||||
+ Log.d(TAG, "onCreate called: mDbHelper = new InMemoryMmsProviderDbHelper()");
|
||||
+ mOpenHelper = new InMemoryMmsProviderDbHelper();
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // close mDbHelper database object
|
||||
+ protected void closeDatabase() {
|
||||
+ mOpenHelper.close();
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * An in memory DB for MmsProviderTestable to use
|
||||
+ */
|
||||
+ public static class InMemoryMmsProviderDbHelper extends SQLiteOpenHelper {
|
||||
+
|
||||
+
|
||||
+ public InMemoryMmsProviderDbHelper() {
|
||||
+ super(null, // no context is needed for in-memory db
|
||||
+ null, // db file name is null for in-memory db
|
||||
+ null, // CursorFactory is null by default
|
||||
+ 1); // db version is no-op for tests
|
||||
+ Log.d(TAG, "InMemoryMmsProviderDbHelper creating in-memory database");
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onCreate(SQLiteDatabase db) {
|
||||
+ // Set up the mms tables
|
||||
+ Log.d(TAG, "InMemoryMmsProviderDbHelper onCreate creating the mms tables");
|
||||
+ db.execSQL(CREATE_PDU_TABLE_STR);
|
||||
+ db.execSQL(CREATE_ADDR_TABLE_STR);
|
||||
+ db.execSQL(CREATE_PART_TABLE_STR);
|
||||
+ db.execSQL(CREATE_RATE_TABLE_STR);
|
||||
+ db.execSQL(CREATE_DRM_TABLE_STR);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
+ Log.d(TAG, "InMemorySmsProviderDbHelper onUpgrade doing nothing");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/src/com/android/providers/telephony/SmsProviderTest.java b/tests/src/com/android/providers/telephony/SmsProviderTest.java
|
||||
index 2bc5f0f1..f86fcd34 100644
|
||||
--- a/tests/src/com/android/providers/telephony/SmsProviderTest.java
|
||||
+++ b/tests/src/com/android/providers/telephony/SmsProviderTest.java
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package com.android.providers.telephony;
|
||||
|
||||
+
|
||||
+import static org.mockito.ArgumentMatchers.anyInt;
|
||||
+import static org.mockito.Mockito.when;
|
||||
+
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
@@ -26,6 +30,7 @@ import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
+import android.os.UserManager;
|
||||
import android.provider.Telephony;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.test.mock.MockContentResolver;
|
||||
@@ -57,6 +62,7 @@ public class SmsProviderTest extends TestCase {
|
||||
private MockContextWithProvider mContext;
|
||||
private MockContentResolver mContentResolver;
|
||||
private SmsProviderTestable mSmsProviderTestable;
|
||||
+ private UserManager mUserManager;
|
||||
|
||||
private int notifyChangeCount;
|
||||
|
||||
@@ -115,6 +121,8 @@ public class SmsProviderTest extends TestCase {
|
||||
return Mockito.mock(AppOpsManager.class);
|
||||
case Context.TELEPHONY_SERVICE:
|
||||
return Mockito.mock(TelephonyManager.class);
|
||||
+ case Context.USER_SERVICE:
|
||||
+ return mUserManager;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -148,6 +156,8 @@ public class SmsProviderTest extends TestCase {
|
||||
mSmsProviderTestable = new SmsProviderTestable();
|
||||
mContext = new MockContextWithProvider(mSmsProviderTestable);
|
||||
mContentResolver = mContext.getContentResolver();
|
||||
+ mUserManager = Mockito.mock(UserManager.class);
|
||||
+
|
||||
notifyChangeCount = 0;
|
||||
}
|
||||
|
||||
@@ -254,6 +264,51 @@ public class SmsProviderTest extends TestCase {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testInsertUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try {
|
||||
+ assertNull(mContentResolver.insert(Telephony.Sms.CONTENT_URI, null));
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Error inserting sms: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testQueryUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try (Cursor cursor = mContentResolver.query(Telephony.Sms.CONTENT_URI,
|
||||
+ null, null, null, null)) {
|
||||
+ assertEquals(0, cursor.getCount());
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Exception in getting count: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testUpdateUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try {
|
||||
+ assertEquals(0, mContentResolver.update(Telephony.Sms.CONTENT_URI, null, null, null));
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Exception in updating sms: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void testDeleteUsingManagedProfile() {
|
||||
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
|
||||
+
|
||||
+ try {
|
||||
+ assertEquals(0, mContentResolver.delete(Telephony.Sms.CONTENT_URI, null, null));
|
||||
+ } catch (Exception e) {
|
||||
+ Log.d(TAG, "Exception in deleting sms: " + e);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private ContentValues getFakeRawValue() {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("pdu", mFakePdu);
|
@ -1,122 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Glade Diviney <mopriadevteam@gmail.com>
|
||||
Date: Sun, 22 Nov 2020 17:42:27 -0800
|
||||
Subject: [PATCH] Adjust APIs for CUPS 2.3.3
|
||||
|
||||
Bug: 168903843
|
||||
Test: Build the code, flash the device and run fuzzer
|
||||
Test: Perform a print job
|
||||
Signed-off-by: Glade Diviney <mopriadevteam@gmail.com>
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:78aedf410610768bdfd8f6c87a704e82a4fd1526)
|
||||
Merged-In: I0000b0950bf38e0b09e47a4bdf970b0e2b2684d1
|
||||
Change-Id: I0000b0950bf38e0b09e47a4bdf970b0e2b2684d1
|
||||
---
|
||||
jni/include/lib_wprint.h | 2 ++
|
||||
jni/ipphelper/ipp_print.c | 15 ++++++++-------
|
||||
jni/ipphelper/ipphelper.c | 14 ++++++++------
|
||||
3 files changed, 18 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/jni/include/lib_wprint.h b/jni/include/lib_wprint.h
|
||||
index 0d2fd12..57cf9f3 100644
|
||||
--- a/jni/include/lib_wprint.h
|
||||
+++ b/jni/include/lib_wprint.h
|
||||
@@ -53,6 +53,8 @@
|
||||
#define MAX_ID_STRING_LENGTH (64)
|
||||
#define MAX_NAME_LENGTH (255)
|
||||
|
||||
+#define HTTP_TIMEOUT_MILLIS 30000
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
diff --git a/jni/ipphelper/ipp_print.c b/jni/ipphelper/ipp_print.c
|
||||
index 36b7015..8ea4a20 100644
|
||||
--- a/jni/ipphelper/ipp_print.c
|
||||
+++ b/jni/ipphelper/ipp_print.c
|
||||
@@ -98,17 +98,20 @@ static status_t _init(const ifc_print_job_t *this_p, const char *printer_address
|
||||
ipp_scheme = (use_secure_uri) ? IPPS_PREFIX : IPP_PREFIX;
|
||||
|
||||
httpAssembleURIf(HTTP_URI_CODING_ALL, ipp_job->printer_uri, sizeof(ipp_job->printer_uri),
|
||||
- ipp_scheme, NULL, printer_address, ippPortNumber, printer_uri);
|
||||
+ ipp_scheme, NULL, printer_address, ippPortNumber, "%s", printer_uri);
|
||||
getResourceFromURI(ipp_job->printer_uri, ipp_job->http_resource, 1024);
|
||||
if (use_secure_uri) {
|
||||
- ipp_job->http = httpConnectEncrypt(printer_address, ippPortNumber, HTTP_ENCRYPTION_ALWAYS);
|
||||
+ ipp_job->http = httpConnect2(printer_address, ippPortNumber, NULL, AF_UNSPEC,
|
||||
+ HTTP_ENCRYPTION_ALWAYS, 1, HTTP_TIMEOUT_MILLIS, NULL);
|
||||
|
||||
// If ALWAYS doesn't work, fall back to REQUIRED
|
||||
if (ipp_job->http == NULL) {
|
||||
- ipp_job->http = httpConnectEncrypt(printer_address, ippPortNumber, HTTP_ENCRYPT_REQUIRED);
|
||||
+ ipp_job->http = httpConnect2(printer_address, ippPortNumber, NULL, AF_UNSPEC,
|
||||
+ HTTP_ENCRYPTION_REQUIRED, 1, HTTP_TIMEOUT_MILLIS, NULL);
|
||||
}
|
||||
} else {
|
||||
- ipp_job->http = httpConnectEncrypt(printer_address, ippPortNumber, HTTP_ENCRYPTION_IF_REQUESTED);
|
||||
+ ipp_job->http = httpConnect2(printer_address, ippPortNumber, NULL, AF_UNSPEC,
|
||||
+ HTTP_ENCRYPTION_IF_REQUESTED, 1, HTTP_TIMEOUT_MILLIS, NULL);
|
||||
}
|
||||
|
||||
httpSetTimeout(ipp_job->http, DEFAULT_IPP_TIMEOUT, NULL, 0);
|
||||
@@ -514,8 +517,6 @@ static status_t _start_job(const ifc_print_job_t *this_p, const wprint_job_param
|
||||
ippDelete(request);
|
||||
continue;
|
||||
}
|
||||
-
|
||||
- _cupsSetHTTPError(ipp_job->status);
|
||||
}
|
||||
ippDelete(request);
|
||||
LOGI("_start_job httpPrint fd %d status %d ipp_status %d", ipp_job->http->fd,
|
||||
@@ -615,4 +616,4 @@ static status_t _end_job(const ifc_print_job_t *this_p) {
|
||||
LOGD("_end_job: exit status %d job_id %d", ipp_job->status, job_id);
|
||||
|
||||
return result;
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
diff --git a/jni/ipphelper/ipphelper.c b/jni/ipphelper/ipphelper.c
|
||||
index 8b7f00d..27a4090 100644
|
||||
--- a/jni/ipphelper/ipphelper.c
|
||||
+++ b/jni/ipphelper/ipphelper.c
|
||||
@@ -1198,19 +1198,22 @@ http_t *ipp_cups_connect(const wprint_connect_info_t *connect_info, char *printe
|
||||
int ippPortNumber = ((connect_info->port_num == IPP_PORT) ? ippPort() : connect_info->port_num);
|
||||
|
||||
if (strstr(connect_info->uri_scheme,IPPS_PREFIX) != NULL) {
|
||||
- curl_http = httpConnectEncrypt(connect_info->printer_addr, ippPortNumber, HTTP_ENCRYPTION_ALWAYS);
|
||||
+ curl_http = httpConnect2(connect_info->printer_addr, ippPortNumber, NULL, AF_UNSPEC,
|
||||
+ HTTP_ENCRYPTION_ALWAYS, 1, HTTP_TIMEOUT_MILLIS, NULL);
|
||||
|
||||
// If ALWAYS doesn't work, fall back to REQUIRED
|
||||
if (curl_http == NULL) {
|
||||
- curl_http = httpConnectEncrypt(connect_info->printer_addr, ippPortNumber, HTTP_ENCRYPT_REQUIRED);
|
||||
+ curl_http = httpConnect2(connect_info->printer_addr, ippPortNumber, NULL, AF_UNSPEC,
|
||||
+ HTTP_ENCRYPTION_REQUIRED, 1, HTTP_TIMEOUT_MILLIS, NULL);
|
||||
}
|
||||
} else {
|
||||
- curl_http = httpConnectEncrypt(connect_info->printer_addr, ippPortNumber, HTTP_ENCRYPTION_IF_REQUESTED);
|
||||
+ curl_http = httpConnect2(connect_info->printer_addr, ippPortNumber, NULL, AF_UNSPEC,
|
||||
+ HTTP_ENCRYPTION_IF_REQUESTED, 1, HTTP_TIMEOUT_MILLIS, NULL);
|
||||
}
|
||||
|
||||
httpSetTimeout(curl_http, (double)connect_info->timeout / 1000, NULL, 0);
|
||||
httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, uriLength, connect_info->uri_scheme, NULL,
|
||||
- connect_info->printer_addr, ippPortNumber, uri_path);
|
||||
+ connect_info->printer_addr, ippPortNumber, "%s", uri_path);
|
||||
|
||||
if (curl_http == NULL) {
|
||||
LOGD("ipp_cups_connect failed addr=%s port=%d", connect_info->printer_addr, ippPortNumber);
|
||||
@@ -1242,7 +1245,6 @@ static ipp_t *ippSendRequest(http_t *http, ipp_t *request, char *resource) {
|
||||
LOGD("ippSendRequest: (Continue with NULL response) Retry");
|
||||
retry = true;
|
||||
} else if (result == HTTP_ERROR || result >= HTTP_BAD_REQUEST) {
|
||||
- _cupsSetHTTPError(result);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1345,4 +1347,4 @@ ipp_t *ipp_doCupsRequest(http_t *http, ipp_t *request, char *http_resource, char
|
||||
} while (1);
|
||||
|
||||
return response;
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
@ -1,48 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Grace Jia <xiaotonj@google.com>
|
||||
Date: Thu, 20 Jul 2023 13:42:50 -0700
|
||||
Subject: [PATCH] Fix vulnerability in CallRedirectionService.
|
||||
|
||||
Currently when the CallRedirectionService binding died, we didn't do
|
||||
anything, which cause malicious app start activities even not run in the
|
||||
background by implementing a CallRedirectionService and overriding the
|
||||
onPlaceCall method to schedule a activity start job in an independent
|
||||
process and then kill itself. In that way, the activity can still
|
||||
start after the CallRedirectionService died. Fix this by unbinding the
|
||||
service when the binding died.
|
||||
|
||||
Bug: b/289809991
|
||||
Test: Using testapp provided in bug to make sure the test activity can't
|
||||
be started
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:29b52e3cd027da2d8644450a4dee3a7d95dc0043)
|
||||
Merged-In: I065d361b83700474a1efab2a75928427ee0a14ba
|
||||
Change-Id: I065d361b83700474a1efab2a75928427ee0a14ba
|
||||
---
|
||||
.../callredirection/CallRedirectionProcessor.java | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
|
||||
index 5de576ccb..b7c719689 100644
|
||||
--- a/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
|
||||
+++ b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
|
||||
@@ -164,6 +164,20 @@ public class CallRedirectionProcessor implements CallRedirectionCallback {
|
||||
Log.endSession();
|
||||
}
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public void onBindingDied(ComponentName componentName) {
|
||||
+ // Make sure we unbind the service if binding died to avoid background stating
|
||||
+ // activity leaks
|
||||
+ Log.startSession("CRSC.oBD");
|
||||
+ try {
|
||||
+ synchronized (mTelecomLock) {
|
||||
+ finishCallRedirection();
|
||||
+ }
|
||||
+ } finally {
|
||||
+ Log.endSession();
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
private class CallRedirectionAdapter extends ICallRedirectionAdapter.Stub {
|
@ -1,30 +0,0 @@
|
||||
From 1428dc76adbbe06b8dc02af4f29422783388457e Mon Sep 17 00:00:00 2001
|
||||
From: kumarashishg <kumarashishg@google.com>
|
||||
Date: Wed, 28 Jun 2023 07:15:27 +0000
|
||||
Subject: [PATCH] Change open jpeg folder name
|
||||
|
||||
Replace libopenjpeg20 to libopenjpeg as folder name got updated in the
|
||||
pdfium library
|
||||
|
||||
Bug: 279055389
|
||||
Test: Build the code and flash the device and check Print functionality
|
||||
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4a4e992e9f3af9ea5dc71d725abb599dadbdd5e1)
|
||||
Merged-In: I5b3d5740128f6ecc23dd8f9446a4f40c8550fd88
|
||||
Change-Id: I5b3d5740128f6ecc23dd8f9446a4f40c8550fd88
|
||||
---
|
||||
|
||||
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
|
||||
index 382d629..aa676df 100644
|
||||
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
|
||||
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
|
||||
@@ -30,8 +30,9 @@
|
||||
],
|
||||
static_libs: [
|
||||
"libpdfium-libopenjpeg2",
|
||||
+ "libpdfium-fxcrt",
|
||||
],
|
||||
include_dirs: [
|
||||
- "external/pdfium/third_party/libopenjpeg20",
|
||||
+ "external/pdfium/third_party/libopenjpeg",
|
||||
],
|
||||
}
|
@ -139,7 +139,6 @@ git revert --no-edit 1419d63b4889a26d22443fd8df1f9073bf229d3d; #Add back Makefil
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/webp"; then
|
||||
applyPatch "$DOS_PATCHES_COMMON/android_external_webp/373948.patch"; #R_asb_2023-11 Update to v1.1.0-8-g50f60add
|
||||
sed -i '85i\ \ \ \ \ \ \ \ "src/utils/filters_utils.c",' Android.bp; #Fixup
|
||||
fi;
|
||||
|
||||
|
@ -149,10 +149,6 @@ if enterAndClear "external/libvpx"; then
|
||||
applyPatch "$DOS_PATCHES_COMMON/android_external_libvpx/CVE-2023-5217.patch"; #VP8: disallow thread count changes
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/webp"; then
|
||||
applyPatch "$DOS_PATCHES_COMMON/android_external_webp/373948.patch"; #R_asb_2023-11 Update to v1.1.0-8-g50f60add
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/libxml2"; then
|
||||
applyPatch "$DOS_PATCHES/android_external_libxml2/368053.patch"; #R_asb_2023-10 malloc-fail: Fix OOB read after xmlRegGetCounter
|
||||
fi;
|
||||
|
@ -86,6 +86,8 @@ patchWorkspaceReal() {
|
||||
repopick -fit Q_asb_2023-07 -e 362202;
|
||||
repopick -fit Q_asb_2023-08 -e 365443;
|
||||
repopick -fit Q_asb_2023-09;
|
||||
repopick -fit Q_asb_2023-10 -e 376554;
|
||||
repopick -fit Q_asb_2023-11 -e 376568;
|
||||
|
||||
sh "$DOS_SCRIPTS/Patch.sh";
|
||||
sh "$DOS_SCRIPTS_COMMON/Enable_Verity.sh";
|
||||
|
@ -98,7 +98,6 @@ sed -i '75i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aap
|
||||
awk -i inplace '!/updatable_apex.mk/' target/product/mainline_system.mk; #Disable APEX
|
||||
sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
|
||||
#sed -i 's/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := true/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := false/' core/product_config.mk; #broken by hardenDefconfig
|
||||
sed -i 's/2023-09-05/2023-11-05/' core/version_defaults.mk; #Bump Security String #Q_asb_2023-11 #XXX
|
||||
fi;
|
||||
|
||||
if enterAndClear "build/soong"; then
|
||||
@ -127,18 +126,14 @@ fi;
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/libcups"; then
|
||||
git fetch https://github.com/LineageOS/android_external_libcups refs/changes/46/373946/1 && git cherry-pick FETCH_HEAD; #R_asb_2023-11 Upgrade libcups to v2.3.1
|
||||
git fetch https://github.com/LineageOS/android_external_libcups refs/changes/47/373947/1 && git cherry-pick FETCH_HEAD; #R_asb_2023-11 Upgrade libcups to v2.3.3
|
||||
git fetch https://github.com/LineageOS/android_external_libcups refs/changes/95/376595/1 && git cherry-pick FETCH_HEAD; #Q_asb_2023-11 Upgrade libcups to v2.3.1
|
||||
git fetch https://github.com/LineageOS/android_external_libcups refs/changes/96/376596/1 && git cherry-pick FETCH_HEAD; #Q_asb_2023-11 Upgrade libcups to v2.3.3
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/libvpx"; then
|
||||
applyPatch "$DOS_PATCHES_COMMON/android_external_libvpx/CVE-2023-5217.patch"; #VP8: disallow thread count changes
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/webp"; then
|
||||
applyPatch "$DOS_PATCHES_COMMON/android_external_webp/373948.patch"; #R_asb_2023-11 Update to v1.1.0-8-g50f60add
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/libxml2"; then
|
||||
applyPatch "$DOS_PATCHES/android_external_libxml2/368053.patch"; #R_asb_2023-10 malloc-fail: Fix OOB read after xmlRegGetCounter
|
||||
fi;
|
||||
@ -154,25 +149,7 @@ if enterAndClear "external/zlib"; then
|
||||
git fetch https://github.com/LineageOS/android_external_zlib refs/changes/70/352570/1 && git cherry-pick FETCH_HEAD; #Q_asb_2023-03
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/av"; then
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_av/373949.patch"; #R_asb_2023-11 Fix for heap buffer overflow issue flagged by fuzzer test.
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_av/373950.patch"; #R_asb_2023-11 Fix heap-use-after-free issue flagged by fuzzer test.
|
||||
fi;
|
||||
|
||||
if enterAndClear "frameworks/base"; then
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368055.patch"; #R_asb_2023-10 RingtoneManager: verify default ringtone is audio
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368059.patch"; #R_asb_2023-10 Do not share key mappings with JNI object
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368060-backport.patch"; #R_asb_2023-10 Verify URI Permissions in Autofill RemoteViews
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368061.patch"; #R_asb_2023-10 Fix KCM key mapping cloning
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368062-backport.patch"; #R_asb_2023-10 Disallow loading icon from content URI to PipMenu
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368063.patch"; #R_asb_2023-10 Fixing DatabaseUtils to detect malformed UTF-16 strings
|
||||
#applyPatch "$DOS_PATCHES/android_frameworks_base/368065-backport.patch"; #R_asb_2023-10 SettingsProvider: exclude secure_frp_mode from resets
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/368067.patch"; #R_asb_2023-10 Revert "DO NOT MERGE Dismiss keyguard when simpin auth'd and..."
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/373951.patch"; #R_asb_2023-11 Fix BAL via notification.publicVersion
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/373952.patch"; #R_asb_2023-11 Check caller's uid in backupAgentCreated callback
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/373953.patch"; #R_asb_2023-11 Use type safe API of readParcelableArray
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/373954-backport.patch"; #R_asb_2023-11 Make log reader thread a class member
|
||||
applyPatch "$DOS_PATCHES/android_frameworks_base/373955.patch"; #R_asb_2023-11 [SettingsProvider] verify ringtone URI before setting
|
||||
#applyPatch "$DOS_PATCHES/android_frameworks_base/272645.patch"; #ten-bt-sbc-hd-dualchannel: Add CHANNEL_MODE_DUAL_CHANNEL constant (ValdikSS)
|
||||
#applyPatch "$DOS_PATCHES/android_frameworks_base/272646-forwardport.patch"; #ten-bt-sbc-hd-dualchannel: Add Dual Channel into Bluetooth Audio Channel Mode developer options menu (ValdikSS)
|
||||
#applyPatch "$DOS_PATCHES/android_frameworks_base/272647.patch"; #ten-bt-sbc-hd-dualchannel: Allow SBC as HD audio codec in Bluetooth device configuration (ValdikSS)
|
||||
@ -349,7 +326,6 @@ fi;
|
||||
|
||||
if enterAndClear "packages/apps/Settings"; then
|
||||
git revert --no-edit 486980cfecce2ca64267f41462f9371486308e9d; #Don't hide OEM unlock
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/368069-backport.patch"; #R_asb_2023-10 Restrict ApnEditor settings
|
||||
#applyPatch "$DOS_PATCHES/android_packages_apps_Settings/272651.patch"; #ten-bt-sbc-hd-dualchannel: Add Dual Channel into Bluetooth Audio Channel Mode developer options menu (ValdikSS)
|
||||
applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0001-Captive_Portal_Toggle.patch"; #Add option to disable captive portal checks (MSe1969)
|
||||
#applyPatch "$DOS_PATCHES/android_packages_apps_Settings/0001-Captive_Portal_Toggle-gos.patch"; #Add option to disable captive portal checks (GrapheneOS) #FIXME: needs work
|
||||
@ -399,22 +375,9 @@ if enterAndClear "packages/providers/DownloadProvider"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_DownloadProvider/0001-Network_Permission.patch"; #Expose the NETWORK permission (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/providers/MediaProvider"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_MediaProvider/368071.patch"; #R_asb_2023-10 Fix path traversal vulnerabilities in MediaProvider
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/providers/TelephonyProvider"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_providers_TelephonyProvider/373957.patch"; #R_asb_2023-11 Block access to sms/mms db from work profile.
|
||||
#if enterAndClear "packages/providers/TelephonyProvider"; then
|
||||
#cp $DOS_PATCHES_COMMON/android_packages_providers_TelephonyProvider/carrier_list.* assets/;
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/services/BuiltInPrintService"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_services_BuiltInPrintService/373958.patch"; #R_asb_2023-11 Adjust APIs for CUPS 2.3.3
|
||||
fi;
|
||||
|
||||
if enterAndClear "packages/services/Telecomm"; then
|
||||
applyPatch "$DOS_PATCHES/android_packages_services_Telecomm/368072.patch"; #R_asb_2023-10 Fix vulnerability in CallRedirectionService.
|
||||
fi;
|
||||
#fi;
|
||||
|
||||
if enterAndClear "prebuilts/abi-dumps/vndk"; then
|
||||
applyPatch "$DOS_PATCHES/android_prebuilts_abi-dumps_vndk/0001-protobuf-avi.patch"; #Work around ABI changes from compiler hardening (GrapheneOS)
|
||||
|
@ -69,7 +69,7 @@ patchWorkspaceReal() {
|
||||
source build/envsetup.sh;
|
||||
#repopick -ift twelve-bt-sbc-hd-dualchannel;
|
||||
#repopick -it twelve-colors;
|
||||
repopick -it S_asb_2023-12 -e 376774;
|
||||
repopick -it S_asb_2023-12;
|
||||
|
||||
sh "$DOS_SCRIPTS/Patch.sh";
|
||||
sh "$DOS_SCRIPTS_COMMON/Enable_Verity.sh";
|
||||
|
@ -98,7 +98,6 @@ sed -i '75i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aap
|
||||
awk -i inplace '!/updatable_apex.mk/' target/product/generic_system.mk; #Disable APEX
|
||||
sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
|
||||
#sed -i 's/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := true/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := false/' core/product_config.mk; #broken by hardenDefconfig
|
||||
sed -i 's/2023-11-05/2023-12-05/' core/version_defaults.mk; #Bump Security String #Q_asb_2023-11 #XXX #S_asb_2023-12
|
||||
fi;
|
||||
|
||||
if enterAndClear "build/soong"; then
|
||||
|
@ -161,7 +161,6 @@ patchWorkspaceReal() {
|
||||
|
||||
source build/envsetup.sh;
|
||||
repopick -i 361248; #Launcher3: Allow toggling monochrome icons for all apps
|
||||
repopick -it T_asb_2023-12 -e 376247;
|
||||
|
||||
sh "$DOS_SCRIPTS/Patch.sh";
|
||||
sh "$DOS_SCRIPTS_COMMON/Enable_Verity.sh";
|
||||
|
@ -97,7 +97,6 @@ applyPatch "$DOS_PATCHES/android_build/0004-Selective_APEX.patch"; #Only enable
|
||||
sed -i '75i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aapt2.mk; #Enable auto-add-overlay for packages, this allows the vendor overlay to easily work across all branches.
|
||||
sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_util.mk; #Set the minimum supported target SDK to Pie (GrapheneOS)
|
||||
#sed -i 's/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := true/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := false/' core/product_config.mk; #broken by hardenDefconfig
|
||||
sed -i 's/2023-11-05/2023-12-05/' core/version_defaults.mk; #Bump Security String #Q_asb_2023-11 #XXX #T_asb_2023-12
|
||||
fi;
|
||||
|
||||
if enterAndClear "build/soong"; then
|
||||
@ -105,10 +104,6 @@ applyPatch "$DOS_PATCHES/android_build_soong/0001-Enable_fwrapv.patch"; #Use -fw
|
||||
if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_build_soong/0002-hm_apex.patch"; fi; #(GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "cts"; then
|
||||
applyPatch "$DOS_PATCHES/android_cts/1428dc7.patch"; #T_asb_2023-12
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/chromium-webview"; then
|
||||
if [ "$(type -t DOS_WEBVIEW_CHERRYPICK)" = "alias" ] ; then DOS_WEBVIEW_CHERRYPICK; fi; #Update the WebView to latest if available
|
||||
if [ "$DOS_WEBVIEW_LFS" = true ]; then git lfs pull; fi; #Ensure the objects are available
|
||||
@ -127,10 +122,6 @@ sed -i 's/34359738368/2147483648/' Android.bp; #revert 48-bit address space requ
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if enterAndClear "external/pdfium"; then
|
||||
git fetch https://github.com/LineageOS/android_external_pdfium refs/changes/50/376250/1 && git cherry-pick FETCH_HEAD; #T_asb_2023-12
|
||||
fi;
|
||||
|
||||
|
||||
if enterAndClear "frameworks/av"; then
|
||||
git am $DOS_PATCHES/ASB-2023-10/av-*.patch;
|
||||
|
Loading…
Reference in New Issue
Block a user