Loading core/java/android/app/ActivityManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,11 @@ package android.app; * @hide Only for use within the system server. */ public abstract class ActivityManagerInternal { /** * Verify that calling app has access to the given provider. */ public abstract String checkContentProviderAccess(String authority, int userId); // Called by the power manager. public abstract void goingToSleep(); public abstract void wakingUp(); Loading services/core/java/com/android/server/am/ActivityManagerService.java +42 −0 Original line number Diff line number Diff line Loading @@ -9050,6 +9050,43 @@ public final class ActivityManagerService extends ActivityManagerNative return providers; } /** * Check if the calling UID has a possible chance at accessing the provider * at the given authority and user. */ public String checkContentProviderAccess(String authority, int userId) { if (userId == UserHandle.USER_ALL) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); userId = UserHandle.getCallingUserId(); } ProviderInfo cpi = null; try { cpi = AppGlobals.getPackageManager().resolveContentProvider(authority, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId); } catch (RemoteException ignored) { } if (cpi == null) { // TODO: make this an outright failure in a future platform release; // until then anonymous content notifications are unprotected //return "Failed to find provider " + authority + " for user " + userId; return null; } ProcessRecord r = null; synchronized (mPidsSelfLocked) { r = mPidsSelfLocked.get(Binder.getCallingPid()); } if (r == null) { return "Failed to find PID " + Binder.getCallingPid(); } synchronized (this) { return checkContentProviderPermissionLocked(cpi, r, userId, true); } } /** * Check if {@link ProcessRecord} has a possible chance at accessing the * given {@link ProviderInfo}. Final permission checking is always done Loading Loading @@ -19097,6 +19134,11 @@ public final class ActivityManagerService extends ActivityManagerNative } private final class LocalService extends ActivityManagerInternal { @Override public String checkContentProviderAccess(String authority, int userId) { return ActivityManagerService.this.checkContentProviderAccess(authority, userId); } @Override public void goingToSleep() { ActivityManagerService.this.goingToSleep(); services/core/java/com/android/server/content/ContentService.java +43 −23 Original line number Diff line number Diff line Loading @@ -19,11 +19,14 @@ package com.android.server.content; import android.Manifest; import android.accounts.Account; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.IContentService; import android.content.ISyncStatusObserver; import android.content.Intent; import android.content.PeriodicSync; import android.content.pm.PackageManager; import android.content.SyncAdapterType; Loading @@ -46,6 +49,8 @@ import android.util.Log; import android.util.Slog; import android.util.SparseIntArray; import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; import java.security.InvalidParameterException; Loading Loading @@ -172,16 +177,17 @@ public final class ContentService extends IContentService.Stub { throw new IllegalArgumentException("You must pass a valid uri and observer"); } enforceCrossUserPermission(userHandle, "no permission to observe other users' provider view"); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { userHandle = ActivityManager.getCurrentUser(); } else if (userHandle != UserHandle.USER_ALL) { throw new InvalidParameterException("Bad user handle for registerContentObserver: " + userHandle); } userHandle = handleIncomingUser(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle); final String msg = LocalServices.getService(ActivityManagerInternal.class) .checkContentProviderAccess(uri.getAuthority(), userHandle); if (msg != null) { Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg); return; } synchronized (mRootNode) { Loading Loading @@ -224,24 +230,20 @@ public final class ContentService extends IContentService.Stub { + " from observer " + observer + ", syncToNetwork " + syncToNetwork); } // Notify for any user other than the caller's own requires permission. final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); if (userHandle != callingUserHandle) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS, "no permission to notify other users"); } // We passed the permission check; resolve pseudouser targets as appropriate if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { userHandle = ActivityManager.getCurrentUser(); } else if (userHandle != UserHandle.USER_ALL) { throw new InvalidParameterException("Bad user handle for notifyChange: " + userHandle); } userHandle = handleIncomingUser(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle); final String msg = LocalServices.getService(ActivityManagerInternal.class) .checkContentProviderAccess(uri.getAuthority(), userHandle); if (msg != null) { Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg); return; } final int uid = Binder.getCallingUid(); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. long identityToken = clearCallingIdentity(); Loading Loading @@ -881,6 +883,24 @@ public final class ContentService extends IContentService.Stub { return service; } private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, int userId) { if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } if (userId == UserHandle.USER_ALL) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); } else if (userId < 0) { throw new IllegalArgumentException("Invalid user: " + userId); } else if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); } return userId; } /** * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL * permission, if the userHandle is not for the caller. Loading Loading
core/java/android/app/ActivityManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,11 @@ package android.app; * @hide Only for use within the system server. */ public abstract class ActivityManagerInternal { /** * Verify that calling app has access to the given provider. */ public abstract String checkContentProviderAccess(String authority, int userId); // Called by the power manager. public abstract void goingToSleep(); public abstract void wakingUp(); Loading
services/core/java/com/android/server/am/ActivityManagerService.java +42 −0 Original line number Diff line number Diff line Loading @@ -9050,6 +9050,43 @@ public final class ActivityManagerService extends ActivityManagerNative return providers; } /** * Check if the calling UID has a possible chance at accessing the provider * at the given authority and user. */ public String checkContentProviderAccess(String authority, int userId) { if (userId == UserHandle.USER_ALL) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); userId = UserHandle.getCallingUserId(); } ProviderInfo cpi = null; try { cpi = AppGlobals.getPackageManager().resolveContentProvider(authority, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId); } catch (RemoteException ignored) { } if (cpi == null) { // TODO: make this an outright failure in a future platform release; // until then anonymous content notifications are unprotected //return "Failed to find provider " + authority + " for user " + userId; return null; } ProcessRecord r = null; synchronized (mPidsSelfLocked) { r = mPidsSelfLocked.get(Binder.getCallingPid()); } if (r == null) { return "Failed to find PID " + Binder.getCallingPid(); } synchronized (this) { return checkContentProviderPermissionLocked(cpi, r, userId, true); } } /** * Check if {@link ProcessRecord} has a possible chance at accessing the * given {@link ProviderInfo}. Final permission checking is always done Loading Loading @@ -19097,6 +19134,11 @@ public final class ActivityManagerService extends ActivityManagerNative } private final class LocalService extends ActivityManagerInternal { @Override public String checkContentProviderAccess(String authority, int userId) { return ActivityManagerService.this.checkContentProviderAccess(authority, userId); } @Override public void goingToSleep() { ActivityManagerService.this.goingToSleep();
services/core/java/com/android/server/content/ContentService.java +43 −23 Original line number Diff line number Diff line Loading @@ -19,11 +19,14 @@ package com.android.server.content; import android.Manifest; import android.accounts.Account; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.IContentService; import android.content.ISyncStatusObserver; import android.content.Intent; import android.content.PeriodicSync; import android.content.pm.PackageManager; import android.content.SyncAdapterType; Loading @@ -46,6 +49,8 @@ import android.util.Log; import android.util.Slog; import android.util.SparseIntArray; import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; import java.security.InvalidParameterException; Loading Loading @@ -172,16 +177,17 @@ public final class ContentService extends IContentService.Stub { throw new IllegalArgumentException("You must pass a valid uri and observer"); } enforceCrossUserPermission(userHandle, "no permission to observe other users' provider view"); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { userHandle = ActivityManager.getCurrentUser(); } else if (userHandle != UserHandle.USER_ALL) { throw new InvalidParameterException("Bad user handle for registerContentObserver: " + userHandle); } userHandle = handleIncomingUser(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle); final String msg = LocalServices.getService(ActivityManagerInternal.class) .checkContentProviderAccess(uri.getAuthority(), userHandle); if (msg != null) { Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg); return; } synchronized (mRootNode) { Loading Loading @@ -224,24 +230,20 @@ public final class ContentService extends IContentService.Stub { + " from observer " + observer + ", syncToNetwork " + syncToNetwork); } // Notify for any user other than the caller's own requires permission. final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); if (userHandle != callingUserHandle) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS, "no permission to notify other users"); } // We passed the permission check; resolve pseudouser targets as appropriate if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { userHandle = ActivityManager.getCurrentUser(); } else if (userHandle != UserHandle.USER_ALL) { throw new InvalidParameterException("Bad user handle for notifyChange: " + userHandle); } userHandle = handleIncomingUser(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle); final String msg = LocalServices.getService(ActivityManagerInternal.class) .checkContentProviderAccess(uri.getAuthority(), userHandle); if (msg != null) { Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg); return; } final int uid = Binder.getCallingUid(); // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. long identityToken = clearCallingIdentity(); Loading Loading @@ -881,6 +883,24 @@ public final class ContentService extends IContentService.Stub { return service; } private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, int userId) { if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } if (userId == UserHandle.USER_ALL) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); } else if (userId < 0) { throw new IllegalArgumentException("Invalid user: " + userId); } else if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); } return userId; } /** * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL * permission, if the userHandle is not for the caller. Loading