Resolve cross account user icon validation.
Resolves a vulnerability found with the cross account user icon
validation in StatusHint and TelecomServiceImpl (when registering a
phone account). The reporter found that an uri formatted as `userId%`
isn't parsed properly with the existing reference to Uri.encodedUserInfo.
Bug: 376461551
Bug: 376259166
Flag: EXEMPT bugfix
Test: atest TelecomServiceImplTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:089dc975fc9dce402ec8c6c84e76fa100c9adcf5)
Merged-In: I7a5f64ae01eaf6a133ea04c51bd00dbe1653b74f
Change-Id: I7a5f64ae01eaf6a133ea04c51bd00dbe1653b74f
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 37e9d33..df174c2 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -55,6 +55,7 @@
import android.telecom.Log;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.StatusHints;
import android.telecom.TelecomAnalytics;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
@@ -2764,15 +2765,13 @@
// 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.");
- }
+ int callingUserId = UserHandle.getCallingUserId();
+ int requestingUserId = StatusHints.getUserIdFromAuthority(
+ icon.getUri().getAuthority(), callingUserId);
+ if(callingUserId != requestingUserId) {
+ // 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 572c975..f539bd0 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -632,6 +632,20 @@
// This should fail; security exception will be thrown.
registerPhoneAccountTestHelper(phoneAccount, false);
+ icon = Icon.createWithContentUri(
+ new Uri.Builder().scheme("content")
+ .encodedAuthority("10%40media")
+ .path("external/images/media/${mediaId.text}".trim())
+ .build());
+ phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build();
+ // This should fail; security exception will be thrown
+ registerPhoneAccountTestHelper(phoneAccount, false);
+
+ icon = Icon.createWithContentUri( Uri.parse("content://10%40play.ground"));
+ phoneAccount = makePhoneAccount(phHandle).setIcon(icon).build();
+ // 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.