Check UID in getUiccCardsInfoSecurity To avoid the case where a caller calls PhoneInterfaceManager#getUiccCardsInfoSecurity using reflection and supplies a calling package with privilege which isn't their own package, we confirm that the calling package UID matches the supplied package. Bug: 146570216 Test: atest com.android.phone.PhoneInterfaceManagerTest Change-Id: Id08009f2feb281c20aaad55aa89faae66b709f88 Merged-In: Id08009f2feb281c20aaad55aa89faae66b709f88 (cherry picked from commit 102b27765aadb26935faa9b89bb0c784d019fd18)
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java index d0ed9bd..2061796 100755 --- a/src/com/android/phone/PhoneInterfaceManager.java +++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -113,6 +113,7 @@ import com.android.ims.ImsException; import com.android.ims.ImsManager; import com.android.ims.internal.IImsServiceFeatureCallback; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CallManager; import com.android.internal.telephony.CallStateException; import com.android.internal.telephony.CarrierInfoManager; @@ -1319,7 +1320,8 @@ } /** Private constructor; @see init() */ - private PhoneInterfaceManager(PhoneGlobals app) { + @VisibleForTesting + /* package */ PhoneInterfaceManager(PhoneGlobals app) { mApp = app; mCM = PhoneGlobals.getInstance().mCM; mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE); @@ -6325,6 +6327,15 @@ @Override public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) { + try { + PackageManager pm = mApp.getPackageManager(); + if (Binder.getCallingUid() != pm.getPackageUid(callingPackage, 0)) { + throw new SecurityException("Calling package " + callingPackage + " does not match " + + "calling UID"); + } + } catch (PackageManager.NameNotFoundException e) { + throw new SecurityException("Invalid calling package. e=" + e); + } boolean hasReadPermission = false; try { enforceReadPrivilegedPermission("getUiccCardsInfo");
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java new file mode 100644 index 0000000..9f8de9e --- /dev/null +++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -0,0 +1,83 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.phone; + +import static junit.framework.TestCase.fail; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import android.content.pm.PackageManager; +import android.os.Binder; +import android.util.Log; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.TelephonyTestBase; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class PhoneInterfaceManagerTest extends TelephonyTestBase { + + private static final String PRIVILEGED_PACKAGE_NAME = "test.package.name"; + + private static final String TAG = "PhoneInterfaceManagerTest"; + + private PhoneInterfaceManager mPhoneInterfaceManager; + private PhoneGlobals mMockPhoneGlobals; + + @Before + public void setUp() throws Exception { + super.setUp(); + mMockPhoneGlobals = mock(PhoneGlobals.class); + //PhoneGlobals phoneGlobals = new PhoneGlobals(mContext); + mPhoneInterfaceManager = new PhoneInterfaceManager(mMockPhoneGlobals); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testGetUiccCardsInfoSecurity() { + // Set up mocks so that the supplied package UID does not equal the calling UID + PackageManager mockPackageManager = mock(PackageManager.class); + try { + doReturn(Binder.getCallingUid() + 1).when(mockPackageManager) + .getPackageUid(eq(PRIVILEGED_PACKAGE_NAME), anyInt()); + } catch (Exception e) { + Log.d(TAG, "testGetUiccCardsInfoSecurity unable to setup mocks"); + fail(); + } + doReturn(mockPackageManager).when(mContext).getPackageManager(); + doReturn(mockPackageManager).when(mMockPhoneGlobals).getPackageManager(); + try { + mPhoneInterfaceManager.getUiccCardsInfo(PRIVILEGED_PACKAGE_NAME); + fail(); + } catch (SecurityException e) { + Log.d(TAG, "testGetUiccCardsInfoSecurity e = " + e); + } + } +}