Security fixup for Slices
- Allow slice providers to override grant flow
- Remove overriding caller, that was a terrible idea
- Move where the same app check happens to allow for CTS
Test: CTS
Bug: 69168488
Change-Id: I61c81c0665a08420b7bc83e3660657b62b2cd6a8
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 67a72ec..1afe53d 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -32,9 +32,11 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.UserHandle;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -392,6 +394,9 @@
*/
public void enforceSlicePermission(Uri uri, String pkg, int pid, int uid) {
try {
+ if (UserHandle.isSameApp(uid, Process.myUid())) {
+ return;
+ }
if (pkg == null) {
throw new SecurityException("No pkg specified");
}
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index dd89293..bf856b7 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -37,7 +37,6 @@
import android.os.Process;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -146,18 +145,6 @@
* @hide
*/
public static final String EXTRA_PROVIDER_PKG = "provider_pkg";
- /**
- * @hide
- */
- public static final String EXTRA_OVERRIDE_PKG = "override_pkg";
- /**
- * @hide
- */
- public static final String EXTRA_OVERRIDE_UID = "override_uid";
- /**
- * @hide
- */
- public static final String EXTRA_OVERRIDE_PID = "override_pid";
private static final boolean DEBUG = false;
@@ -257,6 +244,23 @@
"This provider has not implemented intent to uri mapping");
}
+ /**
+ * Called when an app requests a slice it does not have write permission
+ * to the uri for.
+ * <p>
+ * The return value will be the action on a slice that prompts the user that
+ * the calling app wants to show slices from this app. The default implementation
+ * launches a dialog that allows the user to grant access to this slice. Apps
+ * that do not want to allow this user grant, can override this and instead
+ * launch their own dialog with different behavior.
+ *
+ * @param sliceUri the Uri of the slice attempting to be bound.
+ * @see #getCallingPackage()
+ */
+ public @NonNull PendingIntent onCreatePermissionRequest(Uri sliceUri) {
+ return createPermissionIntent(getContext(), sliceUri, getCallingPackage());
+ }
+
@Override
public final int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
@@ -312,17 +316,7 @@
String callingPackage = getCallingPackage();
int callingUid = Binder.getCallingUid();
int callingPid = Binder.getCallingPid();
- if (extras.containsKey(EXTRA_OVERRIDE_PKG)) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("Only the system can override calling pkg");
- }
- // This is safe because we would grant SYSTEM_UID access to all slices
- // and want to allow it to bind slices as if it were a less privileged app
- // to check their permission levels.
- callingPackage = extras.getString(EXTRA_OVERRIDE_PKG);
- callingUid = extras.getInt(EXTRA_OVERRIDE_UID);
- callingPid = extras.getInt(EXTRA_OVERRIDE_PID);
- }
+
Slice s = handleBindSlice(uri, supportedSpecs, callingPackage, callingUid, callingPid);
Bundle b = new Bundle();
b.putParcelable(EXTRA_SLICE, s);
@@ -406,13 +400,11 @@
// SliceManager#bindSlice.
String pkg = callingPkg != null ? callingPkg
: getContext().getPackageManager().getNameForUid(callingUid);
- if (!UserHandle.isSameApp(callingUid, Process.myUid())) {
- try {
- mSliceManager.enforceSlicePermission(sliceUri, pkg,
- callingPid, callingUid);
- } catch (SecurityException e) {
- return createPermissionSlice(getContext(), sliceUri, pkg);
- }
+ try {
+ mSliceManager.enforceSlicePermission(sliceUri, pkg,
+ callingPid, callingUid);
+ } catch (SecurityException e) {
+ return createPermissionSlice(getContext(), sliceUri, pkg);
}
mCallback = "onBindSlice";
Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
@@ -426,10 +418,18 @@
/**
* @hide
*/
- public static Slice createPermissionSlice(Context context, Uri sliceUri,
+ public Slice createPermissionSlice(Context context, Uri sliceUri,
String callingPackage) {
+ PendingIntent action;
+ mCallback = "onCreatePermissionRequest";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
+ action = onCreatePermissionRequest(sliceUri);
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
+ }
return new Slice.Builder(sliceUri)
- .addAction(createPermissionIntent(context, sliceUri, callingPackage),
+ .addAction(action,
new Slice.Builder(sliceUri.buildUpon().appendPath("permission").build())
.addText(getPermissionString(context, callingPackage), null,
Collections.emptyList())