summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranav Madapurmath <pmadapurmath@google.com>2023-04-05 21:36:12 +0000
committerPranav Madapurmath <pmadapurmath@google.com>2023-09-27 17:18:09 +0000
commita604311f86ea8136ca2ac9f9ff0af7fa57ee3f42 (patch)
tree550997e9fe5babc6ae42362472ac67d584d21ab5
parent29b52e3cd027da2d8644450a4dee3a7d95dc0043 (diff)
downloadTelecomm-a604311f86ea8136ca2ac9f9ff0af7fa57ee3f42.tar.gz
Resolve account image icon profile boundary exploit.
Because Telecom grants the INTERACT_ACROSS_USERS permission, an exploit is possible where the user can upload an image icon (belonging to another user) via registering a phone account. This CL provides a lightweight solution for parsing the image URI to detect profile exploitation. Fixes: 273502295 Fixes: 296915211 Test: Unit test to enforce successful/failure path Change-Id: I2b6418f019a373ee9f02ba8683e5b694e7ab80a5 (cherry picked from commit d0d1d38e37de54e58a7532a0020582fbd7d476b7) Merged-In: I2b6418f019a373ee9f02ba8683e5b694e7ab80a5 (cherry picked from commit e7d0ca3fe5be6e393f643f565792ea5e7ed05f48)
-rw-r--r--src/com/android/server/telecom/TelecomServiceImpl.java22
-rw-r--r--tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java21
2 files changed, 43 insertions, 0 deletions
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 6d8a2f356..9b609af49 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -38,6 +38,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -539,6 +540,9 @@ public class TelecomServiceImpl {
.build();
}
+ // Validate the profile boundary of the given image URI.
+ validateAccountIconUserBoundary(account.getIcon());
+
final long token = Binder.clearCallingIdentity();
try {
mPhoneAccountRegistrar.registerPhoneAccount(account);
@@ -2361,4 +2365,22 @@ public class TelecomServiceImpl {
mContext.sendBroadcast(intent);
}
}
+
+ private void validateAccountIconUserBoundary(Icon icon) {
+ // Refer to Icon#getUriString for context. The URI string is invalid for icons of
+ // incompatible types.
+ if (icon != null && (icon.getType() == Icon.TYPE_URI
+ || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) {
+ String encodedUser = icon.getUri().getEncodedUserInfo();
+ // If there is no encoded user, the URI is calling into the calling user space
+ if (encodedUser != null) {
+ int userId = Integer.parseInt(encodedUser);
+ if (userId != UserHandle.getUserId(Binder.getCallingUid())) {
+ // If we are transcending the profile boundary, throw an error.
+ throw new IllegalArgumentException("Attempting to register a phone account with"
+ + " an image icon belonging to another user.");
+ }
+ }
+ }
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index c2d97e6ed..664b31efe 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -31,6 +31,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -593,6 +594,26 @@ public class TelecomServiceImplTest extends TelecomTestCase {
@SmallTest
@Test
+ public void testRegisterPhoneAccountImageIconCrossUser() throws RemoteException {
+ String packageNameToUse = "com.android.officialpackage";
+ PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName(
+ packageNameToUse, "cs"), "test", Binder.getCallingUserHandle());
+ Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/");
+ PhoneAccount phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build();
+ doReturn(PackageManager.PERMISSION_GRANTED)
+ .when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
+
+ // This should fail; security exception will be thrown.
+ registerPhoneAccountTestHelper(phoneAccount, false);
+
+ icon = Icon.createWithContentUri("content://0@media/external/images/media/");
+ phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build();
+ // This should succeed.
+ registerPhoneAccountTestHelper(phoneAccount, true);
+ }
+
+ @SmallTest
+ @Test
public void testUnregisterPhoneAccount() throws RemoteException {
String packageNameToUse = "com.android.officialpackage";
PhoneAccountHandle phHandle = new PhoneAccountHandle(new ComponentName(