diff options
author | 2019-02-08 13:05:25 -0800 | |
---|---|---|
committer | 2019-02-16 12:08:25 -0800 | |
commit | 0d05e48371c67ce0e95faf0915e96b97361770f5 (patch) | |
tree | 18f7d894d74a8c7072c3c0a186345ff53819f0b8 | |
parent | 3661808cb75bfa1c6cb429994fbe91755f191e6f (diff) |
Check same uid for permission and app-op
In permission checker we used to check the permission for the passed in
uid but the opp-op for the Binder.getCallingUid. In the case the calling
identity was cleared, PermissionChecker ended up checking the app-op of the
current process (often the system server).
Now we check the uid for both the permission and the app-op.
Test: Called PermissionChecker.checkPermission with the calling indentity
cleared.
Fixes: 124116218
Change-Id: Ic0b766f6c75bba1b9dae3e91c6adce85a76ae68f
-rw-r--r-- | api/system-current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/AppOpsManager.java | 40 | ||||
-rw-r--r-- | core/java/android/content/PermissionChecker.java | 6 |
3 files changed, 43 insertions, 4 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 33b15863b5e2..6ee7a4a64bf8 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -309,6 +309,7 @@ package android.app { method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]); + method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int); method public static int opToDefaultMode(@NonNull String); method @Nullable public static String opToPermission(@NonNull String); method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index f76f7b9a7fc7..13eec580ec14 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -4291,12 +4291,35 @@ public class AppOpsManager { /** * Like {@link #noteProxyOp(String, String)} but instead * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. + * + * <p>This API requires the package with the {@code proxiedPackageName} to belongs to + * {@link Binder#getCallingUid()}. */ public int noteProxyOpNoThrow(String op, String proxiedPackageName) { return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName); } /** + * Like {@link #noteProxyOp(String, String)} but instead + * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. + * + * <p>This API requires package with the {@code proxiedPackageName} to belong to + * {@code proxiedUid}. + * + * @param op The op to note + * @param proxiedPackageName The package to note the op for or {@code null} if the op should be + * noted for the "android" package + * @param proxiedUid The uid the package belongs to + * + * @hide + */ + @SystemApi + public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName, + int proxiedUid) { + return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid); + } + + /** * Report that an application has started executing a long-running operation. Note that you * must pass in both the uid and name of the application to be checked; this function will * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call @@ -4495,17 +4518,30 @@ public class AppOpsManager { * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. * @hide */ - public int noteProxyOpNoThrow(int op, String proxiedPackageName) { + public int noteProxyOpNoThrow(int op, String proxiedPackageName, int proxiedUid) { logOperationIfNeeded(op, mContext.getOpPackageName(), proxiedPackageName); try { return mService.noteProxyOperation(op, Process.myUid(), mContext.getOpPackageName(), - Binder.getCallingUid(), proxiedPackageName); + proxiedUid, proxiedPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** + * Like {@link #noteProxyOp(int, String)} but instead + * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. + * + * <p>This API requires the package with {@code proxiedPackageName} to belongs to + * {@link Binder#getCallingUid()}. + * + * @hide + */ + public int noteProxyOpNoThrow(int op, String proxiedPackageName) { + return noteProxyOpNoThrow(op, proxiedPackageName, Binder.getCallingUid()); + } + + /** * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it * returns {@link #MODE_ERRORED}. * @hide diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java index 9f5c877e7081..6fe6e991fb1e 100644 --- a/core/java/android/content/PermissionChecker.java +++ b/core/java/android/content/PermissionChecker.java @@ -108,8 +108,7 @@ public final class PermissionChecker { packageName = packageNames[0]; } - if (appOpsManager.noteProxyOpNoThrow(op, packageName) - != AppOpsManager.MODE_ALLOWED) { + if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) { return PERMISSION_DENIED_APP_OP; } @@ -120,6 +119,9 @@ public final class PermissionChecker { * Checks whether your app has a given permission and whether the app op * that corresponds to this permission is allowed. * + * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as + * {@link Process#myUid()}. + * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} |