diff options
| author | 2022-11-30 15:22:18 +0000 | |
|---|---|---|
| committer | 2022-12-09 16:41:09 +0000 | |
| commit | 0ac7f4220134d05121ee02669882d6e33251f92e (patch) | |
| tree | bcd311fdea477f06457c71ec840102855563ed9e | |
| parent | 3ba84a1710105ff0677e3bbf9c24a865d1cfd38f (diff) | |
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
| -rw-r--r-- | core/java/android/content/ContentProvider.java | 54 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ContentProviderHelper.java | 72 |
2 files changed, 124 insertions, 2 deletions
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index da486eebf9d1..5a153ce71a42 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -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(); diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java index 16055b9c44cd..d2fb7b55952d 100644 --- a/services/core/java/com/android/server/am/ContentProviderHelper.java +++ b/services/core/java/com/android/server/am/ContentProviderHelper.java @@ -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; |