Merge "Check carrier privilege permissions with package name" am: f1a81b04b1 am: cc103b3c7a

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1649652

Change-Id: I6a7721ad113fb28a6ec18ebcc2f6bda31cbd0e7e
This commit is contained in:
Benedict Wong
2021-03-24 02:34:04 +00:00
committed by Automerger Merge Worker
4 changed files with 41 additions and 18 deletions

View File

@@ -29,7 +29,7 @@ import android.os.ParcelUuid;
*/ */
interface IVcnManagementService { interface IVcnManagementService {
void setVcnConfig(in ParcelUuid subscriptionGroup, in VcnConfig config, in String opPkgName); void setVcnConfig(in ParcelUuid subscriptionGroup, in VcnConfig config, in String opPkgName);
void clearVcnConfig(in ParcelUuid subscriptionGroup); void clearVcnConfig(in ParcelUuid subscriptionGroup, in String opPkgName);
void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener); void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener); void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);

View File

@@ -154,7 +154,7 @@ public class VcnManager {
requireNonNull(subscriptionGroup, "subscriptionGroup was null"); requireNonNull(subscriptionGroup, "subscriptionGroup was null");
try { try {
mService.clearVcnConfig(subscriptionGroup); mService.clearVcnConfig(subscriptionGroup, mContext.getOpPackageName());
} catch (ServiceSpecificException e) { } catch (ServiceSpecificException e) {
throw new IOException(e); throw new IOException(e);
} catch (RemoteException e) { } catch (RemoteException e) {

View File

@@ -349,7 +349,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
} }
} }
private void enforceCallingUserAndCarrierPrivilege(ParcelUuid subscriptionGroup) { private void enforceCallingUserAndCarrierPrivilege(
ParcelUuid subscriptionGroup, String pkgName) {
// Only apps running in the primary (system) user are allowed to configure the VCN. This is // Only apps running in the primary (system) user are allowed to configure the VCN. This is
// in line with Telephony's behavior with regards to binding to a Carrier App provided // in line with Telephony's behavior with regards to binding to a Carrier App provided
// CarrierConfigService. // CarrierConfigService.
@@ -363,12 +364,15 @@ public class VcnManagementService extends IVcnManagementService.Stub {
subscriptionInfos.addAll(subMgr.getSubscriptionsInGroup(subscriptionGroup)); subscriptionInfos.addAll(subMgr.getSubscriptionsInGroup(subscriptionGroup));
}); });
final TelephonyManager telMgr = mContext.getSystemService(TelephonyManager.class);
for (SubscriptionInfo info : subscriptionInfos) { for (SubscriptionInfo info : subscriptionInfos) {
final TelephonyManager telMgr = mContext.getSystemService(TelephonyManager.class)
.createForSubscriptionId(info.getSubscriptionId());
// Check subscription is active first; much cheaper/faster check, and an app (currently) // Check subscription is active first; much cheaper/faster check, and an app (currently)
// cannot be carrier privileged for inactive subscriptions. // cannot be carrier privileged for inactive subscriptions.
if (subMgr.isValidSlotIndex(info.getSimSlotIndex()) if (subMgr.isValidSlotIndex(info.getSimSlotIndex())
&& telMgr.hasCarrierPrivileges(info.getSubscriptionId())) { && telMgr.checkCarrierPrivilegesForPackage(pkgName)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
// TODO (b/173717728): Allow configuration for inactive, but manageable // TODO (b/173717728): Allow configuration for inactive, but manageable
// subscriptions. // subscriptions.
// TODO (b/173718661): Check for whole subscription groups at a time. // TODO (b/173718661): Check for whole subscription groups at a time.
@@ -536,7 +540,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
mContext.getSystemService(AppOpsManager.class) mContext.getSystemService(AppOpsManager.class)
.checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName()); .checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName());
enforceCallingUserAndCarrierPrivilege(subscriptionGroup); enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> { Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) { synchronized (mLock) {
@@ -554,11 +558,14 @@ public class VcnManagementService extends IVcnManagementService.Stub {
* <p>Implements the IVcnManagementService Binder interface. * <p>Implements the IVcnManagementService Binder interface.
*/ */
@Override @Override
public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) { public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull String opPkgName) {
requireNonNull(subscriptionGroup, "subscriptionGroup was null"); requireNonNull(subscriptionGroup, "subscriptionGroup was null");
requireNonNull(opPkgName, "opPkgName was null");
Slog.v(TAG, "VCN config cleared for subGrp: " + subscriptionGroup); Slog.v(TAG, "VCN config cleared for subGrp: " + subscriptionGroup);
enforceCallingUserAndCarrierPrivilege(subscriptionGroup); mContext.getSystemService(AppOpsManager.class)
.checkPackage(mDeps.getBinderCallingUid(), opPkgName);
enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> { Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) { synchronized (mLock) {

View File

@@ -19,6 +19,8 @@ package com.android.server;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback; import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
@@ -238,9 +240,14 @@ public class VcnManagementServiceTest {
doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO)) doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
.when(mSubMgr) .when(mSubMgr)
.getSubscriptionsInGroup(any()); .getSubscriptionsInGroup(any());
doReturn(isPrivileged) doReturn(mTelMgr)
.when(mTelMgr) .when(mTelMgr)
.hasCarrierPrivileges(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId())); .createForSubscriptionId(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId()));
doReturn(isPrivileged
? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
: CARRIER_PRIVILEGE_STATUS_NO_ACCESS)
.when(mTelMgr)
.checkCarrierPrivilegesForPackage(eq(TEST_PACKAGE_NAME));
} }
@Test @Test
@@ -391,7 +398,7 @@ public class VcnManagementServiceTest {
mTestLooper.moveTimeForward( mTestLooper.moveTimeForward(
VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2); VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2);
mTestLooper.dispatchAll(); mTestLooper.dispatchAll();
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2); final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2);
// Verify that new instance was different, and the old one was torn down // Verify that new instance was different, and the old one was torn down
@@ -492,7 +499,7 @@ public class VcnManagementServiceTest {
doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
try { try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
fail("Expected IllegalStateException exception for system server"); fail("Expected IllegalStateException exception for system server");
} catch (IllegalStateException expected) { } catch (IllegalStateException expected) {
} }
@@ -505,7 +512,7 @@ public class VcnManagementServiceTest {
.getBinderCallingUid(); .getBinderCallingUid();
try { try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
fail("Expected security exception for non system user"); fail("Expected security exception for non system user");
} catch (SecurityException expected) { } catch (SecurityException expected) {
} }
@@ -516,15 +523,24 @@ public class VcnManagementServiceTest {
setupMockedCarrierPrivilege(false); setupMockedCarrierPrivilege(false);
try { try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
fail("Expected security exception for missing carrier privileges"); fail("Expected security exception for missing carrier privileges");
} catch (SecurityException expected) { } catch (SecurityException expected) {
} }
} }
@Test
public void testClearVcnConfigMismatchedPackages() throws Exception {
try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, "IncorrectPackage");
fail("Expected security exception due to mismatched packages");
} catch (SecurityException expected) {
}
}
@Test @Test
public void testClearVcnConfig() throws Exception { public void testClearVcnConfig() throws Exception {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
} }
@@ -535,7 +551,7 @@ public class VcnManagementServiceTest {
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED);
} }
@@ -564,7 +580,7 @@ public class VcnManagementServiceTest {
verify(vcnInstance).updateConfig(TEST_VCN_CONFIG); verify(vcnInstance).updateConfig(TEST_VCN_CONFIG);
// Verify Vcn is stopped if it was already started // Verify Vcn is stopped if it was already started
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
verify(vcnInstance).teardownAsynchronously(); verify(vcnInstance).teardownAsynchronously();
} }
@@ -781,7 +797,7 @@ public class VcnManagementServiceTest {
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2); mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME);
verify(mMockPolicyListener).onPolicyChanged(); verify(mMockPolicyListener).onPolicyChanged();
} }