summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2016-05-17 18:19:34 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-05-17 18:19:36 +0000
commit607844efa59f79bd9fab55eb75f217d21cd15f5f (patch)
tree4aaf55e563eb870781a5616f4cb3ddc5db180a63
parentc5887ea7a0b82cc5909743ce14cbda1dcf1dfc82 (diff)
parent0c4e6a8da3405f742e5cef8afdf579d58b6f1246 (diff)
Merge "Fix issue #27532364: Security Vulnerability in IIntentSender.send" into nyc-dev
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java3
-rw-r--r--core/java/android/app/ActivityManagerNative.java48
-rw-r--r--core/java/android/app/IActivityManager.java5
-rw-r--r--core/java/android/app/PendingIntent.java3
-rw-r--r--core/java/android/content/IIntentSender.aidl4
-rw-r--r--core/java/android/content/IntentSender.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java26
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java24
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java3
9 files changed, 103 insertions, 20 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 19cb927bd582..4470eda0a2fa 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -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;
}
};
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a4f404f18ed6..6ba6b0f07bc5 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -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;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 2fcad0d3ced0..81788da78e83 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -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;
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 412b098a5872..cb15392b6a8a 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -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,
diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl
index f3affa7dc853..45c62d491625 100644
--- a/core/java/android/content/IIntentSender.aidl
+++ b/core/java/android/content/IIntentSender.aidl
@@ -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);
}
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 13a767e5dbac..32ca6c2d4bac 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -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,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b9cbdbb34ed4..23d5fb63d68a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7051,6 +7051,32 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@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)) {
return;
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index b8f45bc342a8..1f8d26bc55d0 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -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;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 4de8b57d4087..1eeff14568c6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -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;
}
};