Loading core/java/android/app/ActivityManagerInternal.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,11 @@ public abstract class ActivityManagerInternal { */ */ public static final int APP_TRANSITION_TIMEOUT = 3; 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. // Called by the power manager. public abstract void onWakefulnessChanged(int wakefulness); public abstract void onWakefulnessChanged(int wakefulness); Loading services/core/java/com/android/server/am/ActivityManagerService.java +45 −0 Original line number Original line Diff line number Diff line Loading @@ -10419,6 +10419,46 @@ public final class ActivityManagerService extends ActivityManagerNative return providers; 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 * Check if {@link ProcessRecord} has a possible chance at accessing the * given {@link ProviderInfo}. Final permission checking is always done * given {@link ProviderInfo}. Final permission checking is always done Loading Loading @@ -21882,6 +21922,11 @@ public final class ActivityManagerService extends ActivityManagerNative } } private final class LocalService extends ActivityManagerInternal { private final class LocalService extends ActivityManagerInternal { @Override public String checkContentProviderAccess(String authority, int userId) { return ActivityManagerService.this.checkContentProviderAccess(authority, userId); } @Override @Override public void onWakefulnessChanged(int wakefulness) { public void onWakefulnessChanged(int wakefulness) { ActivityManagerService.this.onWakefulnessChanged(wakefulness); ActivityManagerService.this.onWakefulnessChanged(wakefulness); services/core/java/com/android/server/content/ContentService.java +38 −34 Original line number Original line Diff line number Diff line Loading @@ -20,12 +20,12 @@ import android.Manifest; import android.accounts.Account; import android.accounts.Account; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.job.JobInfo; import android.app.job.JobInfo; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.IContentService; import android.content.IContentService; Loading Loading @@ -66,7 +66,6 @@ import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.ArrayList; import java.util.Collections; import java.util.Collections; import java.util.Comparator; import java.util.Comparator; Loading Loading @@ -296,24 +295,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); 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) { userHandle = handleIncomingUser(uri, pid, uid, if (userHandle == UserHandle.USER_CURRENT) { Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle); userHandle = ActivityManager.getCurrentUser(); } else if (userHandle != UserHandle.USER_ALL) { final String msg = LocalServices.getService(ActivityManagerInternal.class) throw new InvalidParameterException("Bad user handle for registerContentObserver: " .checkContentProviderAccess(uri.getAuthority(), userHandle); + userHandle); if (msg != null) { } Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg); return; } } synchronized (mRootNode) { synchronized (mRootNode) { Loading Loading @@ -363,22 +353,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); 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 userHandle = handleIncomingUser(uri, pid, uid, if (userHandle < 0) { Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle); if (userHandle == UserHandle.USER_CURRENT) { userHandle = ActivityManager.getCurrentUser(); final String msg = LocalServices.getService(ActivityManagerInternal.class) } else if (userHandle != UserHandle.USER_ALL) { .checkContentProviderAccess(uri.getAuthority(), userHandle); throw new InvalidParameterException("Bad user handle for notifyChange: " if (msg != null) { + userHandle); 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 // This makes it so that future permission checks will be in the context of this Loading Loading @@ -1143,6 +1126,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 * 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. * permission, if the userHandle is not for the caller. Loading Loading
core/java/android/app/ActivityManagerInternal.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,11 @@ public abstract class ActivityManagerInternal { */ */ public static final int APP_TRANSITION_TIMEOUT = 3; 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. // Called by the power manager. public abstract void onWakefulnessChanged(int wakefulness); public abstract void onWakefulnessChanged(int wakefulness); Loading
services/core/java/com/android/server/am/ActivityManagerService.java +45 −0 Original line number Original line Diff line number Diff line Loading @@ -10419,6 +10419,46 @@ public final class ActivityManagerService extends ActivityManagerNative return providers; 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 * Check if {@link ProcessRecord} has a possible chance at accessing the * given {@link ProviderInfo}. Final permission checking is always done * given {@link ProviderInfo}. Final permission checking is always done Loading Loading @@ -21882,6 +21922,11 @@ public final class ActivityManagerService extends ActivityManagerNative } } private final class LocalService extends ActivityManagerInternal { private final class LocalService extends ActivityManagerInternal { @Override public String checkContentProviderAccess(String authority, int userId) { return ActivityManagerService.this.checkContentProviderAccess(authority, userId); } @Override @Override public void onWakefulnessChanged(int wakefulness) { public void onWakefulnessChanged(int wakefulness) { ActivityManagerService.this.onWakefulnessChanged(wakefulness); ActivityManagerService.this.onWakefulnessChanged(wakefulness);
services/core/java/com/android/server/content/ContentService.java +38 −34 Original line number Original line Diff line number Diff line Loading @@ -20,12 +20,12 @@ import android.Manifest; import android.accounts.Account; import android.accounts.Account; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.job.JobInfo; import android.app.job.JobInfo; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.IContentService; import android.content.IContentService; Loading Loading @@ -66,7 +66,6 @@ import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.ArrayList; import java.util.Collections; import java.util.Collections; import java.util.Comparator; import java.util.Comparator; Loading Loading @@ -296,24 +295,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); 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) { userHandle = handleIncomingUser(uri, pid, uid, if (userHandle == UserHandle.USER_CURRENT) { Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle); userHandle = ActivityManager.getCurrentUser(); } else if (userHandle != UserHandle.USER_ALL) { final String msg = LocalServices.getService(ActivityManagerInternal.class) throw new InvalidParameterException("Bad user handle for registerContentObserver: " .checkContentProviderAccess(uri.getAuthority(), userHandle); + userHandle); if (msg != null) { } Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg); return; } } synchronized (mRootNode) { synchronized (mRootNode) { Loading Loading @@ -363,22 +353,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); 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 userHandle = handleIncomingUser(uri, pid, uid, if (userHandle < 0) { Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle); if (userHandle == UserHandle.USER_CURRENT) { userHandle = ActivityManager.getCurrentUser(); final String msg = LocalServices.getService(ActivityManagerInternal.class) } else if (userHandle != UserHandle.USER_ALL) { .checkContentProviderAccess(uri.getAuthority(), userHandle); throw new InvalidParameterException("Bad user handle for notifyChange: " if (msg != null) { + userHandle); 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 // This makes it so that future permission checks will be in the context of this Loading Loading @@ -1143,6 +1126,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 * 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. * permission, if the userHandle is not for the caller. Loading