Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 028ceeb4 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #14617210: Apps can gain access to any ContentProvider...

...with grantUriPermissions (no user interaction required)

Add a new path in to the activity manager to start an activity as
if it was directy started by the original calling activity.  This
is specifically for the resolver activity and chooser activity to
be able to safely launch its data after serving as an intermediary.

Access to the new method is highly restricted -- it can only be
called by an activity that is declared in the framework apk itself,
and the execute-as-the-caller behavior will only happen if the
code is running under the system uid.  (This means we could still
have these run in the client's process in some cases and still work
correctly.)

Note there is some commented out code here half-done about trying
to propagate security exceptions back to the original calling
activity.  This would be really nice, especially now with the
chooser activity running in a system process so any errors made
by the app (bad permission grants, bad intents, etc) no longer
actually appear in the app so are essentially invisible.  I'd
really like to figure out a way to propagate these exceptions back
to the app, but this is hard since the app's process may no
longer even be running at this point.

Also tweak activity manager dump output to split the recents
dump out from activities, since recents can now be super large.

Change-Id: I50410c4783faf9302c69290589a068a846e0973a
parent 26bcdf14
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -3819,6 +3819,29 @@ public class Activity extends ContextThemeWrapper
        }
    }

    /**
     * Start a new activity as if it was started by the activity that started our
     * current activity.  This is for the resolver and chooser activities, which operate
     * as intermediaries that dispatch their intent to the target the user selects -- to
     * do this, they must perform all security checks including permission grants as if
     * their launch had come from the original activity.
     * @hide
     */
    public void startActivityAsCaller(Intent intent, @Nullable Bundle options) {
        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);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, -1, ar.getResultCode(),
                ar.getResultData());
        }
    }

    /**
     * Same as calling {@link #startIntentSenderForResult(IntentSender, int,
     * Intent, int, int, int, Bundle)} with no options.
+60 −0
Original line number Diff line number Diff line
@@ -169,6 +169,31 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }

        case START_ACTIVITY_AS_CALLER_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();
            int requestCode = data.readInt();
            int startFlags = data.readInt();
            String profileFile = data.readString();
            ParcelFileDescriptor profileFd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = startActivityAsCaller(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags,
                    profileFile, profileFd, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }

        case START_ACTIVITY_AND_WAIT_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
@@ -2347,6 +2372,41 @@ class ActivityManagerProxy implements IActivityManager
        data.recycle();
        return result;
    }
    public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        data.writeString(profileFile);
        if (profileFd != null) {
            data.writeInt(1);
            profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_AS_CALLER_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }
    public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
            int requestCode, int startFlags, String profileFile,
+5 −0
Original line number Diff line number Diff line
@@ -68,6 +68,10 @@ public interface IActivityManager extends IInterface {
            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
            int requestCode, int flags, String profileFile,
            ParcelFileDescriptor profileFd, 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, String profileFile,
            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException;
    public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
            int requestCode, int flags, String profileFile,
@@ -760,4 +764,5 @@ public interface IActivityManager extends IInterface {
    int START_ACTIVITY_FROM_RECENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 229;
    int NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+230;
    int KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+231;
    int START_ACTIVITY_AS_CALLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+232;
}
+37 −0
Original line number Diff line number Diff line
@@ -1665,6 +1665,43 @@ public class Instrumentation {
        return null;
    }

    /**
     * Special version!
     * @hide
     */
    public ActivityResult execStartActivityAsCaller(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

    /*package*/ final void init(ActivityThread thread,
            Context instrContext, Context appContext, ComponentName component, 
            IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ public class ChooserActivity extends ResolverActivity {
                initialIntents[i] = in;
            }
        }
        setSafeForwardingMode(true);
        super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
                null, false);
    }
Loading