From 9797880808320e3a7bae1f59bc7e0c5a13189e5f Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 14 Oct 2014 10:48:18 -0700 Subject: Start cross profile intents as caller. The system should always be using new startActivityAsCaller() when starting activities on behalf of someone else, to ensure that security checks are enforced as the original caller. Bug: 17983737 Change-Id: Ic40816a797cfdb13c0adb48b86ed4ed7d6aae8eb --- core/java/android/app/Activity.java | 4 +-- core/java/android/app/ActivityManagerNative.java | 6 ++-- core/java/android/app/IActivityManager.java | 2 +- core/java/android/app/Instrumentation.java | 4 +-- .../android/app/admin/DevicePolicyManager.java | 14 +++++++--- .../internal/app/IntentForwarderActivity.java | 32 +++++++++++++++++----- .../com/android/internal/app/ResolverActivity.java | 2 +- .../android/server/am/ActivityManagerService.java | 8 ++++-- 8 files changed, 51 insertions(+), 21 deletions(-) diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 0e98175637cd..4b705dde1344 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3847,14 +3847,14 @@ public class Activity extends ContextThemeWrapper * their launch had come from the original activity. * @hide */ - public void startActivityAsCaller(Intent intent, @Nullable Bundle options) { + public void startActivityAsCaller(Intent intent, @Nullable Bundle options, int userId) { if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } Instrumentation.ActivityResult ar = mInstrumentation.execStartActivityAsCaller( this, mMainThread.getApplicationThread(), mToken, this, - intent, -1, options); + intent, -1, options, userId); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, -1, ar.getResultCode(), diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 6c67c0996817..4e2ff0bdb54f 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -184,8 +184,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; + int userId = data.readInt(); int result = startActivityAsCaller(app, callingPackage, intent, resolvedType, - resultTo, resultWho, requestCode, startFlags, profilerInfo, options); + resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId); reply.writeNoException(); reply.writeInt(result); return true; @@ -2435,7 +2436,7 @@ class ActivityManagerProxy implements IActivityManager } public int startActivityAsCaller(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { + int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2459,6 +2460,7 @@ class ActivityManagerProxy implements IActivityManager } else { data.writeInt(0); } + data.writeInt(userId); mRemote.transact(START_ACTIVITY_AS_CALLER_TRANSACTION, data, reply, 0); reply.readException(); int result = reply.readInt(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index b72addfa87f3..be26f3033459 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -69,7 +69,7 @@ public interface IActivityManager extends IInterface { ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException; public int startActivityAsCaller(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int flags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException; + int flags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException; public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options, diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index ba3a2344fcc4..60a013e47c94 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1671,7 +1671,7 @@ public class Instrumentation { */ public ActivityResult execStartActivityAsCaller( Context who, IBinder contextThread, IBinder token, Activity target, - Intent intent, int requestCode, Bundle options) { + Intent intent, int requestCode, Bundle options, int userId) { IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1695,7 +1695,7 @@ public class Instrumentation { .startActivityAsCaller(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, - requestCode, 0, null, options); + requestCode, 0, null, options, userId); checkStartActivityResult(result, intent); } catch (RemoteException e) { } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 2eba29a8adfe..8917928c2f80 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -439,14 +439,20 @@ public class DevicePolicyManager { = "android.app.action.SET_NEW_PASSWORD"; /** - * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a - * managed profile to its parent. + * Flag used by {@link #addCrossProfileIntentFilter} to allow access + * from a managed profile to its parent. That is, any + * matching activities in the parent profile are included in the + * disambiguation list shown when an app in the managed profile calls + * {@link Activity#startActivity(Intent)}. */ public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001; /** - * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from the - * parent to its managed profile. + * Flag used by {@link #addCrossProfileIntentFilter} to allow access + * from a parent to its managed profile. That is, any + * matching activities in the managed profile are included in the + * disambiguation list shown when an app in the parent profile calls + * {@link Activity#startActivity(Intent)}. */ public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002; diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index d949375263bf..6e2f84a3e44e 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -20,26 +20,28 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import android.app.Activity; import android.app.ActivityManagerNative; +import android.app.ActivityThread; import android.app.AppGlobals; -import android.os.Bundle; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.UserInfo; +import android.os.Bundle; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; import android.widget.Toast; + import java.util.List; -import java.util.Set; -/* - * This is used in conjunction with the {@link setCrossProfileIntentFilter} method of - * {@link DevicePolicyManager} to enable intents to be passed in and out of a managed profile. +/** + * This is used in conjunction with + * {@link DevicePolicyManager#addCrossProfileIntentFilter} to enable intents to + * be passed in and out of a managed profile. */ - public class IntentForwarderActivity extends Activity { public static String TAG = "IntentForwarderActivity"; @@ -104,7 +106,23 @@ public class IntentForwarderActivity extends Activity { final boolean shouldShowDisclosure = !UserHandle.isSameApp(ri.activityInfo.applicationInfo.uid, Process.SYSTEM_UID); - startActivityAsUser(newIntent, userDest); + try { + startActivityAsCaller(newIntent, null, userDest.getIdentifier()); + } catch (RuntimeException e) { + int launchedFromUid = -1; + String launchedFromPackage = "?"; + try { + launchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid( + getActivityToken()); + launchedFromPackage = ActivityManagerNative.getDefault().getLaunchedFromPackage( + getActivityToken()); + } catch (RemoteException ignored) { + } + + Slog.wtf(TAG, "Unable to launch as UID " + launchedFromUid + " package " + + launchedFromPackage + ", while running in " + + ActivityThread.currentProcessName(), e); + } if (shouldShowDisclosure) { Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index aa55d23c79a5..0062e2d53746 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -641,7 +641,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic return; } try { - startActivityAsCaller(intent, null); + startActivityAsCaller(intent, null, UserHandle.USER_NULL); } catch (RuntimeException e) { String launchedFromPackage; try { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 8357366ab633..8dfb3217c0af 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3561,7 +3561,7 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public final int startActivityAsCaller(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, - int startFlags, ProfilerInfo profilerInfo, Bundle options) { + int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) { // This is very dangerous -- it allows you to perform a start activity (including // permission grants) as any app that may launch one of your own activities. So @@ -3599,11 +3599,15 @@ public final class ActivityManagerService extends ActivityManagerNative targetPackage = sourceRecord.launchedFromPackage; } + if (userId == UserHandle.USER_NULL) { + userId = UserHandle.getUserId(sourceRecord.app.uid); + } + // TODO: Switch to user app stacks here. try { int ret = mStackSupervisor.startActivityMayWait(null, targetUid, targetPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, null, - null, null, options, UserHandle.getUserId(sourceRecord.app.uid), null, null); + null, null, options, userId, null, null); return ret; } catch (SecurityException e) { // XXX need to figure out how to propagate to original app. -- cgit v1.2.3-59-g8ed1b