Resolve cross account user ringtone validation.
Resolves a vulnerability found with the lack of cross account user ringtone
validation in RingtoneFactory. The reporter found that a ringtone file owned by a different user can be accessed and played by the user who does not own that file.
Bug: 356604577
Flag: EXEMPT Critical CVE bugfix
Test: RingtoneFactoryTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1c7fbd70da65f7b2dd561af8ec9f94b81acf5baa)
Merged-In: Ie28e8d0890086caada561ed27dd660836e6aa6bb
Change-Id: Ie28e8d0890086caada561ed27dd660836e6aa6bb
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index cf52ce9..0399a80 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -3119,7 +3119,8 @@
return Contacts.getLookupUri(mCallerInfo.getContactId(), mCallerInfo.lookupKey);
}
- Uri getRingtone() {
+ @VisibleForTesting
+ public Uri getRingtone() {
return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri;
}
diff --git a/src/com/android/server/telecom/RingtoneFactory.java b/src/com/android/server/telecom/RingtoneFactory.java
index 6bcfb4c..1caa005 100644
--- a/src/com/android/server/telecom/RingtoneFactory.java
+++ b/src/com/android/server/telecom/RingtoneFactory.java
@@ -80,12 +80,18 @@
Ringtone ringtone = null;
if (ringtoneUri != null && userContext != null) {
- // Ringtone URI is explicitly specified. First, try to create a Ringtone with that.
- try {
- ringtone = RingtoneManager.getRingtone(
- userContext, ringtoneUri, volumeShaperConfig, audioAttrs);
- } catch (Exception e) {
- Log.e(this, e, "getRingtone: exception while getting ringtone.");
+ if (currentUserOwnsRingtone(ringtoneUri, incomingCall)) {
+ // Ringtone URI is explicitly specified and owned by the current user - try to
+ // create a Ringtone with that.
+ try {
+ ringtone = RingtoneManager.getRingtone(
+ userContext, ringtoneUri, volumeShaperConfig, audioAttrs);
+ } catch (Exception e) {
+ Log.e(this, e, "getRingtone: exception while getting ringtone.");
+ }
+ } else {
+ Log.w(this, "getRingtone: Failed to verify that the custom ringtone URI"
+ + " is owned by the current user. Falling back to the default ringtone.");
}
}
if (ringtone == null) {
@@ -120,6 +126,21 @@
return ringtone;
}
+ private static boolean currentUserOwnsRingtone(Uri ringtoneUri, Call incomingCall) {
+ if (TextUtils.isEmpty(ringtoneUri.getUserInfo()) ||
+ incomingCall.getAssociatedUser() == null) {
+ return false;
+ }
+
+ UserHandle associatedUser = incomingCall.getAssociatedUser();
+ if (associatedUser == null) {
+ return false;
+ }
+
+ String currentUserId = String.valueOf(associatedUser.getIdentifier());
+ return currentUserId.equals(ringtoneUri.getUserInfo());
+ }
+
private AudioAttributes getDefaultRingtoneAudioAttributes(boolean hapticChannelsMuted) {
return new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)