Loading core/java/android/app/ActivityManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,11 @@ public abstract class ActivityManagerInternal { */ public static final int APP_TRANSITION_TIMEOUT = 3; /** * 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 onWakefulnessChanged(int wakefulness); Loading services/core/java/com/android/server/am/ActivityManagerService.java +45 −0 Original line number Diff line number Diff line Loading @@ -10362,6 +10362,46 @@ 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 | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 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 @@ -21551,6 +21591,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 onWakefulnessChanged(int wakefulness) { ActivityManagerService.this.onWakefulnessChanged(wakefulness); services/core/java/com/android/server/content/ContentService.java +38 −34 Original line number Diff line number Diff line Loading @@ -20,12 +20,12 @@ import android.Manifest; import android.accounts.Account; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.job.JobInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.IContentService; Loading Loading @@ -66,7 +66,6 @@ import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.PrintWriter; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; Loading Loading @@ -296,24 +295,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); // Registering an observer for any user other than the calling user requires uri grant or // cross user permission if (callingUserHandle != userHandle) { if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle) != PackageManager.PERMISSION_GRANTED) { enforceCrossUserPermission(userHandle, "no permission to observe other users' provider view"); } } 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 @@ -363,22 +353,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); // Notify for any user other than the caller requires uri grant or cross user permission if (callingUserHandle != userHandle) { if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle) != PackageManager.PERMISSION_GRANTED) { enforceCrossUserPermission(userHandle, "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; } // This makes it so that future permission checks will be in the context of this Loading Loading @@ -1145,6 +1128,27 @@ public final class ContentService extends IContentService.Stub { } } 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()) { if (checkUriPermission(uri, pid, uid, modeFlags, userId) != PackageManager.PERMISSION_GRANTED) { 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 @@ -57,6 +57,11 @@ public abstract class ActivityManagerInternal { */ public static final int APP_TRANSITION_TIMEOUT = 3; /** * 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 onWakefulnessChanged(int wakefulness); Loading
services/core/java/com/android/server/am/ActivityManagerService.java +45 −0 Original line number Diff line number Diff line Loading @@ -10362,6 +10362,46 @@ 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 | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 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 @@ -21551,6 +21591,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 onWakefulnessChanged(int wakefulness) { ActivityManagerService.this.onWakefulnessChanged(wakefulness);
services/core/java/com/android/server/content/ContentService.java +38 −34 Original line number Diff line number Diff line Loading @@ -20,12 +20,12 @@ import android.Manifest; import android.accounts.Account; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.job.JobInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.IContentService; Loading Loading @@ -66,7 +66,6 @@ import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.PrintWriter; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; Loading Loading @@ -296,24 +295,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); // Registering an observer for any user other than the calling user requires uri grant or // cross user permission if (callingUserHandle != userHandle) { if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle) != PackageManager.PERMISSION_GRANTED) { enforceCrossUserPermission(userHandle, "no permission to observe other users' provider view"); } } 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 @@ -363,22 +353,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); // Notify for any user other than the caller requires uri grant or cross user permission if (callingUserHandle != userHandle) { if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle) != PackageManager.PERMISSION_GRANTED) { enforceCrossUserPermission(userHandle, "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; } // This makes it so that future permission checks will be in the context of this Loading Loading @@ -1145,6 +1128,27 @@ public final class ContentService extends IContentService.Stub { } } 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()) { if (checkUriPermission(uri, pid, uid, modeFlags, userId) != PackageManager.PERMISSION_GRANTED) { 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