summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ashish Kumar <akgaurav@google.com> 2022-11-30 15:22:18 +0000
committer Ashish Kumar <akgaurav@google.com> 2022-12-09 16:41:09 +0000
commit0ac7f4220134d05121ee02669882d6e33251f92e (patch)
treebcd311fdea477f06457c71ec840102855563ed9e
parent3ba84a1710105ff0677e3bbf9c24a865d1cfd38f (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.java54
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java72
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;