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

Commit 4a0ca941 authored by Michael Groover's avatar Michael Groover
Browse files

Use StatsLog to log packages denied access to device identifiers

Bug: 123646983
Test: statsd_testdrive 146
Change-Id: I33836a4bad338316e092ebe4a4fce2a49f839696
parent 51a197d0
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ message Atom {
        ProcessStartTime process_start_time = 169;
        PermissionGrantRequestResultReported permission_grant_request_result_reported = 170;
        BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171;
        DeviceIdentifierAccessDenied device_identifier_access_denied = 172;
    }

    // Pulled events will start at field 10000.
@@ -5447,3 +5448,22 @@ message DangerousPermissionState {
    optional bool is_granted = 4;
}

/**
 * Logs when a package is denied access to a device identifier based on the new access requirements.
 *
 * Logged from:
 *     frameworks/base/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
 */
message DeviceIdentifierAccessDenied {
    // The name of the package denied access to the requested device identifier.
    optional string package_name = 1;

    // The name of the device identifier method the package attempted to invoke.
    optional string method_name = 2;

    // True if the package is preinstalled.
    optional bool is_preinstalled = 3;

    // True if the package is privileged.
    optional bool is_priv_app = 4;
}
+47 −18
Original line number Diff line number Diff line
@@ -35,9 +35,14 @@ import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.StatsLog;

import com.android.internal.annotations.VisibleForTesting;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

/** Utility class for Telephony permission enforcement. */
@@ -49,6 +54,14 @@ public final class TelephonyPermissions {
    private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
            ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));

    // Contains a mapping of packages that did not meet the new requirements to access device
    // identifiers and the methods they were attempting to invoke; used to prevent duplicate
    // reporting of packages / methods.
    private static final Map<String, Set<String>> sReportedDeviceIDPackages;
    static {
        sReportedDeviceIDPackages = new HashMap<>();
    }

    private TelephonyPermissions() {}

    /**
@@ -285,47 +298,63 @@ public final class TelephonyPermissions {
     */
    private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid,
            int uid, String callingPackage, String message) {
        // Check if the application is a 3P app; if so then a separate setting is required to relax
        // the check to begin flagging problems with 3P apps early.
        // Check if the application is not preinstalled; if not then a separate setting is required
        // to relax the check to begin flagging problems with non-preinstalled apps early.
        boolean relax3PDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
                Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED, 0) == 1;
        boolean is3PApp = true;
        boolean isPreinstalled = false;
        // Also check if the application is a preloaded non-privileged app; if so there is a
        // separate setting to relax the check for these apps to ensure users can relax the check
        // for 3P or non-priv apps as needed while continuing to test the other.
        // for non-preinstalled or non-priv apps as needed while continuing to test the other.
        boolean relaxNonPrivDeviceIdentifierCheck = Settings.Global.getInt(
                context.getContentResolver(),
                Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_NON_PRIV_CHECK_RELAXED, 0) == 1;
        boolean isNonPrivApp = false;
        boolean isPrivApp = false;
        // Similar to above support relaxing the check for privileged apps while still enforcing it
        // for non-privileged and 3P apps.
        // for non-privileged and non-preinstalled apps.
        boolean relaxPrivDeviceIdentifierCheck = Settings.Global.getInt(
                context.getContentResolver(),
                Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_PRIV_CHECK_RELAXED, 0) == 1;
        ApplicationInfo callingPackageInfo = null;
        try {
            callingPackageInfo = context.getPackageManager().getApplicationInfo(callingPackage, 0);
            if (callingPackageInfo.isSystemApp()) {
                isPreinstalled = true;
                if (callingPackageInfo.isPrivilegedApp()) {
                is3PApp = false;
            } else if (callingPackageInfo.isSystemApp()) {
                is3PApp = false;
                isNonPrivApp = true;
                    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 3P app to detect any issues with the check
            // calling app is a non-preinstalled app to detect any issues with the check
            Log.e(LOG_TAG, "Exception caught obtaining package info for package " + callingPackage,
                    e);
        }
        // The new Q restrictions for device identifier access will be enforced for all apps with
        // settings to individually disable the new restrictions for privileged, preloaded
        // non-privileged, and 3P apps.
        // non-privileged, and non-preinstalled apps.
        if (!isIdentifierCheckDisabled() && (
                (!is3PApp && !isNonPrivApp && !relaxPrivDeviceIdentifierCheck)
                        || (is3PApp && !relax3PDeviceIdentifierCheck)
                        || (isNonPrivApp && !relaxNonPrivDeviceIdentifierCheck))) {
            Log.wtf(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message
                    + ":is3PApp=" + is3PApp + ":isNonPrivApp=" + isNonPrivApp);
                (isPrivApp && !relaxPrivDeviceIdentifierCheck)
                        || (!isPreinstalled && !relax3PDeviceIdentifierCheck)
                        || (isPreinstalled && !isPrivApp && !relaxNonPrivDeviceIdentifierCheck))) {
            // The current package should only be reported in StatsLog if it has not previously been
            // reported for the currently invoked device identifier method.
            boolean packageReported = sReportedDeviceIDPackages.containsKey(callingPackage);
            if (!packageReported || !sReportedDeviceIDPackages.get(callingPackage).contains(
                    message)) {
                Set invokedMethods;
                if (!packageReported) {
                    invokedMethods = new HashSet<String>();
                    sReportedDeviceIDPackages.put(callingPackage, invokedMethods);
                } else {
                    invokedMethods = sReportedDeviceIDPackages.get(callingPackage);
                }
                invokedMethods.add(message);
                StatsLog.write(StatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED, callingPackage, message,
                        isPreinstalled, isPrivApp);
            }
            Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message
                    + ":isPreinstalled=" + isPreinstalled + ":isPrivApp=" + isPrivApp);
            // if the target SDK is pre-Q then check if the calling package would have previously
            // had access to device identifiers.
            if (callingPackageInfo != null && (