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

Commit 13980cb7 authored by Pranav Madapurmath's avatar Pranav Madapurmath Committed by Automerger Merge Worker
Browse files

Resolve account image icon profile boundary exploit. am: a604311f

parents 1637f8e3 a604311f
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -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.");
                }
            }
        }
    }
}
+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;
@@ -591,6 +592,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 {