diff options
Diffstat (limited to 'services/core/java/com/android/server/content/ContentService.java')
-rw-r--r-- | services/core/java/com/android/server/content/ContentService.java | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index f581a7f..1db31c9 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -19,6 +19,8 @@ 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; @@ -51,7 +53,6 @@ import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -190,23 +191,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 && - 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) { - 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) { @@ -253,21 +246,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 && - 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 - 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 @@ -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, boolean observerWantsSelfNotifications, boolean syncToNetwork) { notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, @@ -924,6 +920,27 @@ 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()) { + 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. |