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

Commit 0ac7f422 authored by Ashish Kumar's avatar Ashish Kumar
Browse files

Added logging of cases where getType is called without readPermission using westworld atom

Test: Manual test using statsd_testdrive

Bug: b/260556486

AMC review doc: https://eldar.corp.google.com/assessments/7185522/drafts/683536140?jsmode=du

Change-Id: Iedd317d1226672d7b6086d6d3cff5c9efa9b8d8f
parent 3ba84a17
Loading
Loading
Loading
Loading
+53 −1
Original line number Diff line number Diff line
@@ -21,6 +21,11 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.os.Process.myUserHandle;
import static android.os.Trace.TRACE_TAG_DATABASE;

import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_ERROR;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_FRAMEWORK_PERMISSION;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -58,6 +63,7 @@ import android.util.Log;
import android.util.SparseBooleanArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;

import java.io.File;
import java.io.FileDescriptor;
@@ -300,7 +306,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
            uri = maybeGetUriWithoutUserId(uri);
            traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
            try {
                return mInterface.getType(uri);
                final String type = mInterface.getType(uri);
                if (type != null) {
                    logGetTypeData(Binder.getCallingUid(), uri, type);
                }
                return type;
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            } finally {
@@ -308,6 +318,48 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
            }
        }

        // Utility function to log the getTypeData calls
        private void logGetTypeData(int callingUid, Uri uri, String type) {
            final int enumFrameworkPermission =
                    GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_FRAMEWORK_PERMISSION;
            final int enumCheckUriPermission =
                    GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION;
            final int enumError = GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_ERROR;

            try {
                final AttributionSource attributionSource = new AttributionSource.Builder(
                        callingUid).build();
                try {
                    if (enforceReadPermission(attributionSource, uri)
                            != PermissionChecker.PERMISSION_GRANTED) {
                        FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
                                enumFrameworkPermission,
                                callingUid, uri.getAuthority(), type);
                    } else {
                        final ProviderInfo cpi = mContext.getPackageManager()
                                .resolveContentProvider(uri.getAuthority(),
                                PackageManager.ComponentInfoFlags.of(PackageManager.GET_META_DATA));
                        if (cpi.forceUriPermissions
                                && mInterface.checkUriPermission(uri,
                                callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
                                != PermissionChecker.PERMISSION_GRANTED) {
                            FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
                                    enumCheckUriPermission,
                                    callingUid, uri.getAuthority(), type);
                        }
                    }
                } catch (SecurityException e) {
                    FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
                            enumFrameworkPermission,
                            callingUid, uri.getAuthority(), type);
                }
            } catch (Exception e) {
                FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
                        enumError,
                        callingUid, uri.getAuthority(), type);
            }
        }

        @Override
        public void getTypeAsync(Uri uri, RemoteCallback callback) {
            final Bundle result = new Bundle();
+71 −1
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@ import static android.os.Process.PROC_PARENS;
import static android.os.Process.PROC_SPACE_TERM;
import static android.os.Process.SYSTEM_UID;

import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_CHECK_URI_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_ERROR;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_FRAMEWORK_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.PROVIDER_ACQUISITION_EVENT_REPORTED;
import static com.android.internal.util.FrameworkStatsLog.PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
import static com.android.internal.util.FrameworkStatsLog.PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
@@ -46,6 +50,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -1003,7 +1008,11 @@ public class ContentProviderHelper {
                };
                mService.mHandler.postDelayed(providerNotResponding, 1000);
                try {
                    return holder.provider.getType(uri);
                    final String type = holder.provider.getType(uri);
                    if (type != null) {
                        backgroundLogging(callingUid, callingPid, userId, uri, holder, type);
                    }
                    return type;
                } finally {
                    mService.mHandler.removeCallbacks(providerNotResponding);
                    // We need to clear the identity to call removeContentProviderExternalUnchecked
@@ -1060,6 +1069,10 @@ public class ContentProviderHelper {
                        Binder.restoreCallingIdentity(identity);
                    }
                    resultCallback.sendResult(result);
                    final String type = result.getPairValue();
                    if (type != null) {
                        backgroundLogging(callingUid, callingPid, userId, uri, holder, type);
                    }
                }));
            } else {
                resultCallback.sendResult(Bundle.EMPTY);
@@ -1070,6 +1083,63 @@ public class ContentProviderHelper {
        }
    }

    private void backgroundLogging(int callingUid, int callingPid, int userId, Uri uri,
            ContentProviderHolder holder, String type) {
        // Push the logging code in a different handlerThread.
        try {
            mService.mHandler.post(new Runnable() {
                @Override
                public void run() {
                    logGetTypeData(callingUid, callingPid, userId,
                            uri, holder, type);
                }
            });
        } catch (Exception e) {
            // To ensure logging does not break the getType calls.
        }
    }

    // Utility function to log the getTypeData calls
    private void logGetTypeData(int callingUid, int callingPid, int userId, Uri uri,
            ContentProviderHolder holder, String type) {
        try {
            boolean checkUser = true;
            final String authority = uri.getAuthority();
            if (isAuthorityRedirectedForCloneProfile(authority)) {
                UserManagerInternal umInternal =
                        LocalServices.getService(UserManagerInternal.class);
                UserInfo userInfo = umInternal.getUserInfo(userId);

                if (userInfo != null && userInfo.isCloneProfile()) {
                    userId = umInternal.getProfileParentId(userId);
                    checkUser = false;
                }
            }
            final ProviderInfo cpi = holder.info;
            final AttributionSource attributionSource =
                    new AttributionSource.Builder(callingUid).build();
            final String permissionCheck =
                    checkContentProviderPermission(cpi, callingPid, callingUid,
                            userId, checkUser, null);
            if (permissionCheck != null) {
                FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
                        GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_FRAMEWORK_PERMISSION,
                        callingUid, authority, type);
            } else if (cpi.forceUriPermissions
                    && holder.provider.checkUriPermission(attributionSource,
                            uri, callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
                            != PermissionChecker.PERMISSION_GRANTED) {
                FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
                        GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_CHECK_URI_PERMISSION,
                        callingUid, authority, type);
            }
        } catch (Exception e) {
            FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
                    GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_ERROR, callingUid,
                    uri.getAuthority(), type);
        }
    }

    private boolean canClearIdentity(int callingPid, int callingUid, int userId) {
        if (UserHandle.getUserId(callingUid) == userId) {
            return true;