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:
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user