Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3af8461c authored by Pranav Madapurmath's avatar Pranav Madapurmath Committed by Automerger Merge Worker
Browse files

Resolve account image icon profile boundary exploit. am: a604311f am:...

Resolve account image icon profile boundary exploit. am: a604311f am: 13980cb7 am: 46031022 am: 9bbf25ed am: a4bc335e am: 733a8f6b am: 4fd0e1e4

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telecomm/+/24876043



Change-Id: I0f2408702bd5f59522d67db1267e2db6332b423f
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 26d3417b 4fd0e1e4
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -43,6 +43,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;
@@ -599,6 +600,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);
@@ -2752,4 +2756,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.");
                }
            }
        }
    }
}
+21 −0
Original line number Diff line number Diff line
@@ -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;
@@ -617,6 +618,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 {