Merge "Fix issue #27532364: Security Vulnerability in IIntentSender.send" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
607844efa5
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -17,10 +17,6 @@
|
||||
package android.content;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IIntentSender;
|
||||
import android.content.IIntentReceiver;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Handler;
|
||||
@ -191,7 +187,8 @@ public class IntentSender 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,
|
||||
|
@ -7050,6 +7050,32 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
return rec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
|
||||
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
|
||||
if (target instanceof PendingIntentRecord) {
|
||||
return ((PendingIntentRecord)target).sendWithResult(code, intent, resolvedType,
|
||||
finishedReceiver, requiredPermission, options);
|
||||
} else {
|
||||
try {
|
||||
target.send(code, intent, resolvedType, null, requiredPermission, options);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
// Platform code can rely on getting a result back when the send is done, but if
|
||||
// this intent sender is from outside of the system we can't rely on it doing that.
|
||||
// So instead we don't give it the result receiver, and instead just directly
|
||||
// report the finish immediately.
|
||||
if (finishedReceiver != null) {
|
||||
try {
|
||||
finishedReceiver.performReceive(intent, 0,
|
||||
null, null, false, false, UserHandle.getCallingUserId());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelIntentSender(IIntentSender sender) {
|
||||
if (!(sender instanceof PendingIntentRecord)) {
|
||||
|
@ -198,16 +198,21 @@ final class PendingIntentRecord extends IIntentSender.Stub {
|
||||
ref = new WeakReference<PendingIntentRecord>(this);
|
||||
}
|
||||
|
||||
public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
|
||||
String requiredPermission, Bundle options) throws TransactionTooLargeException {
|
||||
public void send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
|
||||
String requiredPermission, Bundle options) {
|
||||
sendInner(code, intent, resolvedType, finishedReceiver,
|
||||
requiredPermission, null, null, 0, 0, 0, options, null);
|
||||
}
|
||||
|
||||
public int sendWithResult(int code, Intent intent, String resolvedType,
|
||||
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
|
||||
return sendInner(code, intent, resolvedType, finishedReceiver,
|
||||
requiredPermission, null, null, 0, 0, 0, options, null);
|
||||
}
|
||||
|
||||
int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
|
||||
String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
|
||||
int flagsMask, int flagsValues, Bundle options, IActivityContainer container)
|
||||
throws TransactionTooLargeException {
|
||||
int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
|
||||
if (intent != null) intent.setDefusable(true);
|
||||
if (options != null) options.setDefusable(true);
|
||||
|
||||
@ -253,6 +258,7 @@ final class PendingIntentRecord extends IIntentSender.Stub {
|
||||
if (userId == UserHandle.USER_CURRENT) {
|
||||
userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
|
||||
}
|
||||
int res = 0;
|
||||
switch (key.type) {
|
||||
case ActivityManager.INTENT_SENDER_ACTIVITY:
|
||||
if (options == null) {
|
||||
@ -312,21 +318,23 @@ final class PendingIntentRecord extends IIntentSender.Stub {
|
||||
resolvedType, key.packageName, userId);
|
||||
} catch (RuntimeException e) {
|
||||
Slog.w(TAG, "Unable to send startService intent", e);
|
||||
} catch (TransactionTooLargeException e) {
|
||||
res = ActivityManager.START_CANCELED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (sendFinish) {
|
||||
if (sendFinish && res != ActivityManager.START_CANCELED) {
|
||||
try {
|
||||
finishedReceiver.performReceive(new Intent(finalIntent), 0,
|
||||
null, null, false, false, key.userId);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
|
||||
return 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return ActivityManager.START_CANCELED;
|
||||
|
@ -1463,14 +1463,13 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user