Loading core/java/android/app/ActivityManagerInternal.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,11 @@ import android.content.ComponentName; * @hide Only for use within the system server. * @hide Only for use within the system server. */ */ public abstract class ActivityManagerInternal { 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. // 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 +42 −0 Original line number Original line Diff line number Diff line Loading @@ -9314,6 +9314,43 @@ 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, 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 @@ -20659,6 +20696,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 +48 −31 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.server.content; import android.Manifest; import android.Manifest; import android.accounts.Account; import android.accounts.Account; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentResolver; import android.content.Context; import android.content.Context; Loading Loading @@ -51,7 +53,6 @@ import com.android.server.LocalServices; 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 @@ -190,23 +191,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 && mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) != 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 @@ -253,21 +246,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 && mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 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 @@ -317,6 +304,15 @@ public final class ContentService extends IContentService.Stub { } } } } private int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, int userHandle) { try { return ActivityManagerNative.getDefault().checkUriPermission( uri, pid, uid, modeFlags, userHandle, null); } catch (RemoteException e) { return PackageManager.PERMISSION_DENIED; } } public void notifyChange(Uri uri, IContentObserver observer, public void notifyChange(Uri uri, IContentObserver observer, boolean observerWantsSelfNotifications, boolean syncToNetwork) { boolean observerWantsSelfNotifications, boolean syncToNetwork) { notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, Loading Loading @@ -924,6 +920,27 @@ public final class ContentService extends IContentService.Stub { return service; 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()) { 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 @@ -25,6 +25,11 @@ import android.content.ComponentName; * @hide Only for use within the system server. * @hide Only for use within the system server. */ */ public abstract class ActivityManagerInternal { 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. // 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 +42 −0 Original line number Original line Diff line number Diff line Loading @@ -9314,6 +9314,43 @@ 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, 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 @@ -20659,6 +20696,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 +48 −31 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.server.content; import android.Manifest; import android.Manifest; import android.accounts.Account; import android.accounts.Account; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentResolver; import android.content.Context; import android.content.Context; Loading Loading @@ -51,7 +53,6 @@ import com.android.server.LocalServices; 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 @@ -190,23 +191,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 && mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) != 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 @@ -253,21 +246,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 && mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 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 @@ -317,6 +304,15 @@ public final class ContentService extends IContentService.Stub { } } } } private int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, int userHandle) { try { return ActivityManagerNative.getDefault().checkUriPermission( uri, pid, uid, modeFlags, userHandle, null); } catch (RemoteException e) { return PackageManager.PERMISSION_DENIED; } } public void notifyChange(Uri uri, IContentObserver observer, public void notifyChange(Uri uri, IContentObserver observer, boolean observerWantsSelfNotifications, boolean syncToNetwork) { boolean observerWantsSelfNotifications, boolean syncToNetwork) { notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, Loading Loading @@ -924,6 +920,27 @@ public final class ContentService extends IContentService.Stub { return service; 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()) { 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