diff options
| -rw-r--r-- | core/api/current.txt | 3 | ||||
| -rw-r--r-- | core/java/android/app/ContextImpl.java | 32 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/content/Context.java | 75 | ||||
| -rw-r--r-- | core/java/android/content/ContextWrapper.java | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 18 |
6 files changed, 150 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index e264f1ddddb6..583bbcf370c0 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -10226,12 +10226,15 @@ package android.content { method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.INTERACT_ACROSS_PROFILES}) public boolean bindServiceAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull android.os.UserHandle); method @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)") public abstract int checkCallingOrSelfPermission(@NonNull String); method @CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)") public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int); + method @NonNull public int[] checkCallingOrSelfUriPermissions(@NonNull java.util.List<android.net.Uri>, int); method @CheckResult(suggest="#enforceCallingPermission(String,String)") public abstract int checkCallingPermission(@NonNull String); method @CheckResult(suggest="#enforceCallingUriPermission(Uri,int,String)") public abstract int checkCallingUriPermission(android.net.Uri, int); + method @NonNull public int[] checkCallingUriPermissions(@NonNull java.util.List<android.net.Uri>, int); method @CheckResult(suggest="#enforcePermission(String,int,int,String)") public abstract int checkPermission(@NonNull String, int, int); method public abstract int checkSelfPermission(@NonNull String); method @CheckResult(suggest="#enforceUriPermission(Uri,int,int,String)") public abstract int checkUriPermission(android.net.Uri, int, int, int); method @CheckResult(suggest="#enforceUriPermission(Uri,String,String,int,int,int,String)") public abstract int checkUriPermission(@Nullable android.net.Uri, @Nullable String, @Nullable String, int, int, int); + method @NonNull public int[] checkUriPermissions(@NonNull java.util.List<android.net.Uri>, int, int, int); method @Deprecated public abstract void clearWallpaper() throws java.io.IOException; method @NonNull public android.content.Context createAttributionContext(@Nullable String); method public abstract android.content.Context createConfigurationContext(@NonNull android.content.res.Configuration); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 9a20e0fefd33..85fb543a3967 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -16,6 +16,7 @@ package android.app; +import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.StrictMode.vmIncorrectContextUseEnabled; @@ -105,6 +106,7 @@ import java.lang.annotation.RetentionPolicy; import java.nio.ByteOrder; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; @@ -2181,6 +2183,18 @@ class ContextImpl extends Context { } } + @NonNull + @Override + public int[] checkUriPermissions(@NonNull List<Uri> uris, int pid, int uid, + int modeFlags) { + try { + return ActivityManager.getService().checkUriPermissions(uris, pid, uid, modeFlags, + null); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ @Override public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) { @@ -2207,12 +2221,30 @@ class ContextImpl extends Context { return PackageManager.PERMISSION_DENIED; } + @NonNull + @Override + public int[] checkCallingUriPermissions(@NonNull List<Uri> uris, int modeFlags) { + int pid = Binder.getCallingPid(); + if (pid != Process.myPid()) { + return checkUriPermissions(uris, pid, Binder.getCallingUid(), modeFlags); + } + int[] res = new int[uris.size()]; + Arrays.fill(res, PERMISSION_DENIED); + return res; + } + @Override public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) { return checkUriPermission(uri, Binder.getCallingPid(), Binder.getCallingUid(), modeFlags); } + @NonNull + @Override + public int[] checkCallingOrSelfUriPermissions(@NonNull List<Uri> uris, int modeFlags) { + return checkUriPermissions(uris, Binder.getCallingPid(), Binder.getCallingUid(), modeFlags); + } + @Override public int checkUriPermission(Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags) { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index e73636fe7fd0..4ad13e1932dd 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -220,6 +220,8 @@ interface IActivityManager { int getProcessLimit(); int checkUriPermission(in Uri uri, int pid, int uid, int mode, int userId, in IBinder callerToken); + int[] checkUriPermissions(in List<Uri> uris, int pid, int uid, int mode, + in IBinder callerToken); void grantUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri, int mode, int userId); void revokeUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 025d777f2053..24b76292fb7b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -93,6 +93,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.List; import java.util.concurrent.Executor; /** @@ -5725,6 +5726,32 @@ public abstract class Context { public abstract int checkUriPermission(Uri uri, int pid, int uid, @Intent.AccessUriMode int modeFlags); + /** + * Determine whether a particular process and user ID has been granted + * permission to access a list of URIs. This only checks for permissions + * that have been explicitly granted -- if the given process/uid has + * more general access to the URI's content provider then this check will + * always fail. + * + * @param uris The list of URIs that is being checked. + * @param pid The process ID being checked against. Must be > 0. + * @param uid The user ID being checked against. A uid of 0 is the root + * user, which will pass every permission check. + * @param modeFlags The access modes to check for the list of uris + * + * @return Array of permission grants corresponding to each entry in the list of uris. + * {@link PackageManager#PERMISSION_GRANTED} if the given pid/uid is allowed to access that uri, + * or {@link PackageManager#PERMISSION_DENIED} if it is not. + * + * @see #checkCallingUriPermission + */ + @NonNull + @PackageManager.PermissionResult + public int[] checkUriPermissions(@NonNull List<Uri> uris, int pid, int uid, + @Intent.AccessUriMode int modeFlags) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + /** @hide */ @SuppressWarnings("HiddenAbstractMethod") @PackageManager.PermissionResult @@ -5755,6 +5782,32 @@ public abstract class Context { public abstract int checkCallingUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags); /** + * Determine whether the calling process and user ID has been + * granted permission to access a list of URIs. This is basically + * the same as calling {@link #checkUriPermissions(List, int, int, int)} + * with the pid and uid returned by {@link + * android.os.Binder#getCallingPid} and {@link + * android.os.Binder#getCallingUid}. One important difference is + * that if you are not currently processing an IPC, this function + * will always fail. + * + * @param uris The list of URIs that is being checked. + * @param modeFlags The access modes to check. + * + * @return Array of permission grants corresponding to each entry in the list of uris. + * {@link PackageManager#PERMISSION_GRANTED} if the given pid/uid is allowed to access that uri, + * or {@link PackageManager#PERMISSION_DENIED} if it is not. + * + * @see #checkUriPermission(Uri, int, int, int) + */ + @NonNull + @PackageManager.PermissionResult + public int[] checkCallingUriPermissions(@NonNull List<Uri> uris, + @Intent.AccessUriMode int modeFlags) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + + /** * Determine whether the calling process of an IPC <em>or you</em> has been granted * permission to access a specific URI. This is the same as * {@link #checkCallingUriPermission}, except it grants your own permissions @@ -5775,6 +5828,28 @@ public abstract class Context { @Intent.AccessUriMode int modeFlags); /** + * Determine whether the calling process of an IPC <em>or you</em> has been granted + * permission to access a list of URIs. This is the same as + * {@link #checkCallingUriPermission}, except it grants your own permissions + * if you are not currently processing an IPC. Use with care! + * + * @param uris The list of URIs that is being checked. + * @param modeFlags The access modes to check. + * + * @return Array of permission grants corresponding to each entry in the list of uris. + * {@link PackageManager#PERMISSION_GRANTED} if the given pid/uid is allowed to access that uri, + * or {@link PackageManager#PERMISSION_DENIED} if it is not. + * + * @see #checkCallingUriPermission + */ + @NonNull + @PackageManager.PermissionResult + public int[] checkCallingOrSelfUriPermissions(@NonNull List<Uri> uris, + @Intent.AccessUriMode int modeFlags) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + + /** * Check both a Uri and normal permission. This allows you to perform * both {@link #checkPermission} and {@link #checkUriPermission} in one * call. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index c1c213eee81b..b71fb2712c24 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -53,6 +53,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.List; import java.util.concurrent.Executor; /** @@ -905,6 +906,13 @@ public class ContextWrapper extends Context { return mBase.checkUriPermission(uri, pid, uid, modeFlags); } + @NonNull + @Override + public int[] checkUriPermissions(@NonNull List<Uri> uris, int pid, int uid, + int modeFlags) { + return mBase.checkUriPermissions(uris, pid, uid, modeFlags); + } + /** @hide */ @Override public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) { @@ -916,11 +924,23 @@ public class ContextWrapper extends Context { return mBase.checkCallingUriPermission(uri, modeFlags); } + @NonNull + @Override + public int[] checkCallingUriPermissions(@NonNull List<Uri> uris, int modeFlags) { + return mBase.checkCallingUriPermissions(uris, modeFlags); + } + @Override public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) { return mBase.checkCallingOrSelfUriPermission(uri, modeFlags); } + @NonNull + @Override + public int[] checkCallingOrSelfUriPermissions(@NonNull List<Uri> uris, int modeFlags) { + return mBase.checkCallingOrSelfUriPermissions(uris, modeFlags); + } + @Override public int checkUriPermission(@Nullable Uri uri, @Nullable String readPermission, @Nullable String writePermission, int pid, int uid, int modeFlags) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bedd19b6864a..163845c2e0a8 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -186,6 +186,7 @@ import android.content.BroadcastReceiver; import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.ContentCaptureOptions; +import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.IIntentReceiver; @@ -5626,6 +5627,23 @@ public class ActivityManagerService extends IActivityManager.Stub ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED; } + @Override + public int[] checkUriPermissions(@NonNull List<Uri> uris, int pid, int uid, + final int modeFlags, IBinder callerToken) { + final int size = uris.size(); + int[] res = new int[size]; + // Default value DENIED. + Arrays.fill(res, PackageManager.PERMISSION_DENIED); + + for (int i = 0; i < size; i++) { + final Uri uri = uris.get(i); + final int userId = ContentProvider.getUserIdFromUri(uri, mContext.getUserId()); + res[i] = checkUriPermission(ContentProvider.getUriWithoutUserId(uri), pid, uid, + modeFlags, userId, callerToken); + } + return res; + } + /** * @param uri This uri must NOT contain an embedded userId. * @param userId The userId in which the uri is to be resolved. |