diff options
author | Pranav Madapurmath <pmadapurmath@google.com> | 2023-04-05 21:36:12 +0000 |
---|---|---|
committer | Pranav Madapurmath <pmadapurmath@google.com> | 2023-09-27 17:18:09 +0000 |
commit | a604311f86ea8136ca2ac9f9ff0af7fa57ee3f42 (patch) | |
tree | 550997e9fe5babc6ae42362472ac67d584d21ab5 | |
parent | 29b52e3cd027da2d8644450a4dee3a7d95dc0043 (diff) | |
download | Telecomm-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.java | 22 | ||||
-rw-r--r-- | tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java | 21 |
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( |