Tad 2023-11-13 15:54:48 -05:00
parent 798c665f74
commit c45a1db5e2
No known key found for this signature in database
GPG Key ID: B286E9F57A07424B
14 changed files with 1921 additions and 6 deletions

View File

@ -0,0 +1,214 @@
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;
}

View File

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

View File

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

View File

@ -10,10 +10,10 @@ requiring the READ_PHONE_STATE permission.
1 file changed, 1 insertion(+), 6 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..c9d3d44beb02 100644
index 3e99e594a702..409c546ca624 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5010,12 +5010,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@@ -5026,12 +5026,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}

View File

@ -13,7 +13,7 @@ Change-Id: Iecfc1fb962de611cbe3c51a44ba4fded53925a7d
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..08658694c5b8 100644
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;

View File

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

View File

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

View File

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

View File

@ -0,0 +1,102 @@
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);

View File

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

View File

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

View File

@ -0,0 +1,818 @@
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);

View File

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

View File

@ -98,7 +98,7 @@ 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-10-05/' core/version_defaults.mk; #Bump Security String #Q_asb_2023-10 #XXX
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
@ -126,10 +126,19 @@ applyPatch "$DOS_PATCHES/android_external_hardened_malloc/0001-Broken_Cameras.pa
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
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;
@ -145,6 +154,11 @@ 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
@ -154,6 +168,11 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/368062-backport.patch"; #R_asb_
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)
@ -380,9 +399,18 @@ 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/TelephonyProvider"; then
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.
#cp $DOS_PATCHES_COMMON/android_packages_providers_TelephonyProvider/carrier_list.* assets/;
#fi;
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.