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

Commit dd2c1667 authored by Michael Groover's avatar Michael Groover
Browse files

Grant device ID access to app with carrier privlege on any sub ID

Fixes: 132173603
Test: atest TelephonyPermissionsTest
Test: cts-tradefed run cts-dev -m CtsTelephony3TestCases
Test: cts-tradefed run cts-dev -m CtsDevicePolicyManagerTestCases -t \
com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCanGetDeviceIdentifiers
Test: cts-tradefed run cts-dev -m CtsDevicePolicyManagerTestCases -t \
com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCanGetDeviceIdentifiers
Test: cts-tradefed run cts-dev -m CtsTelephonyTestCases -t android.telephony.cts.TelephonyManagerTest

Change-Id: I6a92790389db8ce08118e7f7f45d9309296d2551
parent a9ac86f6
Loading
Loading
Loading
Loading
+70 −76
Original line number Diff line number Diff line
@@ -209,18 +209,9 @@ public final class TelephonyPermissions {
                context.enforcePermission(
                        android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
            } catch (SecurityException phoneStateException) {
                SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
                        Context.TELEPHONY_SUBSCRIPTION_SERVICE);
                int[] activeSubIds = sm.getActiveSubscriptionIdList();
                for (int activeSubId : activeSubIds) {
                // If we don't have the runtime permission, but do have carrier privileges, that
                // suffices for reading phone state.
                    if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
                            == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
                        return true;
                    }
                }
                return false;
                return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid);
            }
        }

@@ -236,9 +227,9 @@ public final class TelephonyPermissions {
     *
     * <p>This method behaves in one of the following ways:
     * <ul>
     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the
     *       calling package passes a DevicePolicyManager Device Owner / Profile Owner device
     *       identifier access check,
     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
     *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
     *       access check, or the calling package has carrier privileges.
     *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
     *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
     *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
@@ -258,9 +249,9 @@ public final class TelephonyPermissions {
     *
     * <p>This method behaves in one of the following ways:
     * <ul>
     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the
     *       calling package passes a DevicePolicyManager Device Owner / Profile Owner device
     *       identifier access check,
     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
     *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
     *       access check, or the calling package has carrier privileges.
     *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
     *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
     *       or carrier privileges.
@@ -272,23 +263,8 @@ public final class TelephonyPermissions {
     */
    public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
            String callingPackage, String message) {
        int pid = Binder.getCallingPid();
        int uid = Binder.getCallingUid();
        // if the device identifier check completes successfully then grant access.
        if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
            return true;
        }
        // Calling packages with carrier privileges will also have access to device identifiers, but
        // this may be removed in a future release.
        if (checkCarrierPrivilegeForSubId(subId)) {
            return true;
        }
        // else the calling package is not authorized to access the device identifiers; call
        // a central method to report the failure based on the target SDK and if the calling package
        // has the READ_PHONE_STATE permission or carrier privileges that were previously required
        // to access the identifiers.
        return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
                message);
        return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
                Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
    }

    /**
@@ -298,7 +274,7 @@ public final class TelephonyPermissions {
     * <ul>
     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
     *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
     *       access check, or the calling package has carrier privleges.
     *       access check, or the calling package has carrier privileges.
     *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
     *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
     *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
@@ -309,19 +285,8 @@ public final class TelephonyPermissions {
     */
    public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
            String callingPackage, String message) {
        int pid = Binder.getCallingPid();
        int uid = Binder.getCallingUid();
        // if the device identifiers can be read then grant access to the subscriber identifiers
        if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
            return true;
        }
        // If the calling package has carrier privileges then allow access to the subscriber
        // identifiers.
        if (checkCarrierPrivilegeForSubId(subId)) {
            return true;
        }
        return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
                message);
        return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
                Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
    }

    /**
@@ -331,8 +296,10 @@ public final class TelephonyPermissions {
     * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier access
     * check.
     */
    private static boolean checkReadDeviceIdentifiers(Context context, int pid, int uid,
            String callingPackage) {
    @VisibleForTesting
    public static boolean checkReadDeviceIdentifiers(Context context,
            Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
            String callingPackage, String message) {
        // Allow system and root access to the device identifiers.
        final int appId = UserHandle.getAppId(uid);
        if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
@@ -343,11 +310,13 @@ public final class TelephonyPermissions {
                uid) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        // if the calling package is null then return now as there's no way to perform the
        // DevicePolicyManager device / profile owner and AppOp checks
        if (callingPackage == null) {
            return false;
        // If the calling package has carrier privileges for any subscription then allow access.
        if (checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid)) {
            return true;
        }
        // if the calling package is not null then perform the DevicePolicyManager device /
        // profile owner and Appop checks.
        if (callingPackage != null) {
            // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op.
            long token = Binder.clearCallingIdentity();
            AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(
@@ -361,13 +330,16 @@ public final class TelephonyPermissions {
                Binder.restoreCallingIdentity(token);
            }
            // Allow access to a device / profile owner app.
        DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(
            DevicePolicyManager devicePolicyManager =
                    (DevicePolicyManager) context.getSystemService(
                            Context.DEVICE_POLICY_SERVICE);
            if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess(
                    callingPackage, pid, uid)) {
                return true;
            }
        return false;
        }
        return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
            message);
    }

    /**
@@ -403,12 +375,14 @@ public final class TelephonyPermissions {
        try {
            callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser(
                    callingPackage, 0, UserHandle.getUserId(uid));
            if (callingPackageInfo != null) {
                if (callingPackageInfo.isSystemApp()) {
                    isPreinstalled = true;
                    if (callingPackageInfo.isPrivilegedApp()) {
                        isPrivApp = true;
                    }
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            // If the application info for the calling package could not be found then assume the
            // calling app is a non-preinstalled app to detect any issues with the check
@@ -651,6 +625,26 @@ public final class TelephonyPermissions {
        }
    }

    /**
     * Returns whether the provided uid has carrier privileges for any active subscription ID.
     */
    private static boolean checkCarrierPrivilegeForAnySubId(Context context,
            Supplier<ITelephony> telephonySupplier, int uid) {
        SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
        int[] activeSubIds = sm.getActiveSubscriptionIdList();
        if (activeSubIds != null) {
            for (int activeSubId : activeSubIds) {
                if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
                        == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
                    return true;
                }
            }
        }
        return false;
    }


    private static int getCarrierPrivilegeStatus(
            Supplier<ITelephony> telephonySupplier, int subId, int uid) {
        ITelephony telephony = telephonySupplier.get();