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

Commit 0c4e6a8d authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #27532364: Security Vulnerability in IIntentSender.send

We need to make IIntentSender oneway...  but when the system is
calling that for itself, it needs to be able to return a result code.

Solution: instead of directly calling the interface, we have a new
IPC through the activity manager.  If the thing being used is the
activity manager impl, it can do the synchronous send and return
the result directly in place.  If not, you only get asynchronous
sending and thus never a failure result back (too bad for you!).

Change-Id: I4096e5b00063e8dba66230585a2dfe67e35e8092
parent 3f84c5cb
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -301,14 +301,13 @@ public final class Pm {

        private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
            @Override
            public int send(int code, Intent intent, String resolvedType,
            public void send(int code, Intent intent, String resolvedType,
                    IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
                try {
                    mResult.offer(intent, 5, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                return 0;
            }
        };

+48 −0
Original line number Diff line number Diff line
@@ -2977,6 +2977,22 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            reply.writeNoException();
            return true;
        }
        case SEND_INTENT_SENDER_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IIntentSender sender = IIntentSender.Stub.asInterface(data.readStrongBinder());
            int scode = data.readInt();
            Intent intent = data.readInt() != 0 ? Intent.CREATOR.createFromParcel(data) : null;
            String resolvedType = data.readString();
            IIntentReceiver finishedReceiver = IIntentReceiver.Stub.asInterface(
                    data.readStrongBinder());
            String requiredPermission = data.readString();
            Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = sendIntentSender(sender, scode, intent, resolvedType, finishedReceiver,
                    requiredPermission, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }
        }

        return super.onTransact(code, data, reply, flags);
@@ -6973,5 +6989,37 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
    }

    public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(target.asBinder());
        data.writeInt(code);
        if ((intent!=null)) {
            data.writeInt(1);
            intent.writeToParcel(data, 0);
        }
        else {
            data.writeInt(0);
        }
        data.writeString(resolvedType);
        data.writeStrongBinder((((finishedReceiver!=null))?(finishedReceiver.asBinder()):(null)));
        data.writeString(requiredPermission);
        if ((options!=null)) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        }
        else {
            data.writeInt(0);
        }
        mRemote.transact(SEND_INTENT_SENDER_TRANSACTION, data, reply, 0);
        final int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res;
    }

    private IBinder mRemote;
}
+5 −0
Original line number Diff line number Diff line
@@ -653,6 +653,10 @@ public interface IActivityManager extends IInterface {

    public void startConfirmDeviceCredentialIntent(Intent intent) throws RemoteException;

    public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)
            throws RemoteException;

    /*
     * Private non-Binder interfaces
     */
@@ -1038,4 +1042,5 @@ public interface IActivityManager extends IInterface {
    int NOTIFY_LOCKED_PROFILE = IBinder.FIRST_CALL_TRANSACTION + 373;
    int START_CONFIRM_DEVICE_CREDENTIAL_INTENT = IBinder.FIRST_CALL_TRANSACTION + 374;
    int SEND_IDLE_JOB_TRIGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 375;
    int SEND_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 376;
}
+2 −1
Original line number Diff line number Diff line
@@ -803,7 +803,8 @@ public final class PendingIntent implements Parcelable {
            String resolvedType = intent != null ?
                    intent.resolveTypeIfNeeded(context.getContentResolver())
                    : null;
            int res = mTarget.send(code, intent, resolvedType,
            int res = ActivityManagerNative.getDefault().sendIntentSender(
                    mTarget, code, intent, resolvedType,
                    onFinished != null
                            ? new FinishedDispatcher(this, onFinished, handler)
                            : null,
+2 −2
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import android.content.Intent;
import android.os.Bundle;

/** @hide */
interface IIntentSender {
    int send(int code, in Intent intent, String resolvedType,
oneway interface IIntentSender {
    void send(int code, in Intent intent, String resolvedType,
            IIntentReceiver finishedReceiver, String requiredPermission, in Bundle options);
}
Loading