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

Commit 7aac1013 authored by Michael Groover's avatar Michael Groover Committed by Android (Google) Code Review
Browse files

Merge "Grant device ID access to app with carrier privlege on any sub ID" into qt-dev

parents 9ff409c7 dd2c1667
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();