Add mechanism for Parcel to not allow FDs to be written to it.

This is to help implement issue #5224703.

Change-Id: I026a5890495537d15b57fe61227a640aac806d46
This commit is contained in:
Dianne Hackborn
2011-09-28 23:19:47 -04:00
parent 8ebf1efd66
commit 9ecebbfbf7
14 changed files with 134 additions and 33 deletions

View File

@@ -3246,6 +3246,7 @@ public class Activity extends ContextThemeWrapper
try {
String resolvedType = null;
if (fillInIntent != null) {
fillInIntent.setAllowFds(false);
resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -3370,6 +3371,7 @@ public class Activity extends ContextThemeWrapper
if (mParent == null) {
int result = IActivityManager.START_RETURN_INTENT_TO_CALLER;
try {
intent.setAllowFds(false);
result = ActivityManagerNative.getDefault()
.startActivity(mMainThread.getApplicationThread(),
intent, intent.resolveTypeIfNeeded(
@@ -3419,6 +3421,7 @@ public class Activity extends ContextThemeWrapper
public boolean startNextMatchingActivity(Intent intent) {
if (mParent == null) {
try {
intent.setAllowFds(false);
return ActivityManagerNative.getDefault()
.startNextMatchingActivity(mToken, intent);
} catch (RemoteException e) {
@@ -3692,6 +3695,9 @@ public class Activity extends ContextThemeWrapper
}
if (false) Log.v(TAG, "Finishing self: token=" + mToken);
try {
if (resultData != null) {
resultData.setAllowFds(false);
}
if (ActivityManagerNative.getDefault()
.finishActivity(mToken, resultCode, resultData)) {
mFinished = true;
@@ -3812,6 +3818,7 @@ public class Activity extends ContextThemeWrapper
int flags) {
String packageName = getPackageName();
try {
data.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName,

View File

@@ -2674,6 +2674,7 @@ public final class ActivityThread {
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
state = new Bundle();
state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
r.state = state;
}
@@ -2775,6 +2776,7 @@ public final class ActivityThread {
if (!r.activity.mFinished && saveState) {
if (r.state == null) {
state = new Bundle();
state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
r.state = state;
} else {
@@ -3306,6 +3308,7 @@ public final class ActivityThread {
}
if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
r.state = new Bundle();
r.state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
}

View File

@@ -874,6 +874,7 @@ class ContextImpl extends Context {
try {
String resolvedType = null;
if (fillInIntent != null) {
fillInIntent.setAllowFds(false);
resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -892,6 +893,7 @@ class ContextImpl extends Context {
public void sendBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, false);
@@ -903,6 +905,7 @@ class ContextImpl extends Context {
public void sendBroadcast(Intent intent, String receiverPermission) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, false, false);
@@ -915,6 +918,7 @@ class ContextImpl extends Context {
String receiverPermission) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, true, false);
@@ -946,6 +950,7 @@ class ContextImpl extends Context {
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermission,
@@ -958,6 +963,7 @@ class ContextImpl extends Context {
public void sendStickyBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, true);
@@ -989,6 +995,7 @@ class ContextImpl extends Context {
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, null,
@@ -1005,6 +1012,7 @@ class ContextImpl extends Context {
intent.setDataAndType(intent.getData(), resolvedType);
}
try {
intent.setAllowFds(false);
ActivityManagerNative.getDefault().unbroadcastIntent(
mMainThread.getApplicationThread(), intent);
} catch (RemoteException e) {
@@ -1069,6 +1077,7 @@ class ContextImpl extends Context {
@Override
public ComponentName startService(Intent service) {
try {
service.setAllowFds(false);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
@@ -1086,6 +1095,7 @@ class ContextImpl extends Context {
@Override
public boolean stopService(Intent service) {
try {
service.setAllowFds(false);
int res = ActivityManagerNative.getDefault().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
@@ -1116,6 +1126,7 @@ class ContextImpl extends Context {
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.setAllowFds(false);
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
@@ -1148,6 +1159,9 @@ class ContextImpl extends Context {
public boolean startInstrumentation(ComponentName className,
String profileFile, Bundle arguments) {
try {
if (arguments != null) {
arguments.setAllowFds(false);
}
return ActivityManagerNative.getDefault().startInstrumentation(
className, profileFile, 0, arguments, null);
} catch (RemoteException e) {

View File

@@ -1375,6 +1375,7 @@ public class Instrumentation {
}
}
try {
intent.setAllowFds(false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
@@ -1415,6 +1416,7 @@ public class Instrumentation {
try {
String[] resolvedTypes = new String[intents.length];
for (int i=0; i<intents.length; i++) {
intents[i].setAllowFds(false);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -1471,6 +1473,7 @@ public class Instrumentation {
}
}
try {
intent.setAllowFds(false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),

View File

@@ -661,6 +661,9 @@ public final class LoadedApk {
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false);
} catch (RemoteException e) {
Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");

View File

@@ -192,6 +192,7 @@ public final class PendingIntent implements Parcelable {
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_ACTIVITY, packageName,
@@ -249,6 +250,7 @@ public final class PendingIntent implements Parcelable {
String packageName = context.getPackageName();
String[] resolvedTypes = new String[intents.length];
for (int i=0; i<intents.length; i++) {
intents[i].setAllowFds(false);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
}
try {
@@ -287,6 +289,7 @@ public final class PendingIntent implements Parcelable {
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_BROADCAST, packageName,
@@ -324,6 +327,7 @@ public final class PendingIntent implements Parcelable {
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_SERVICE, packageName,

View File

@@ -366,6 +366,9 @@ public abstract class BroadcastReceiver {
mFinished = true;
try {
if (mResultExtras != null) {
mResultExtras.setAllowFds(false);
}
if (mOrderedHint) {
am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
mAbortBroadcast);
@@ -462,6 +465,7 @@ public abstract class BroadcastReceiver {
IActivityManager am = ActivityManagerNative.getDefault();
IBinder binder = null;
try {
service.setAllowFds(false);
binder = am.peekService(service, service.resolveTypeIfNeeded(
myContext.getContentResolver()));
} catch (RemoteException e) {

View File

@@ -3568,6 +3568,13 @@ public class Intent implements Parcelable, Cloneable {
return mExtras != null && mExtras.hasFileDescriptors();
}
/** @hide */
public void setAllowFds(boolean allowFds) {
if (mExtras != null) {
mExtras.setAllowFds(allowFds);
}
}
/**
* Retrieve extended data from the intent.
*

View File

@@ -54,6 +54,7 @@ public final class Bundle implements Parcelable, Cloneable {
private boolean mHasFds = false;
private boolean mFdsKnown = true;
private boolean mAllowFds = true;
/**
* The ClassLoader used when unparcelling data from mParcelledData.
@@ -186,7 +187,14 @@ public final class Bundle implements Parcelable, Cloneable {
public ClassLoader getClassLoader() {
return mClassLoader;
}
/** @hide */
public boolean setAllowFds(boolean allowFds) {
boolean orig = mAllowFds;
mAllowFds = allowFds;
return orig;
}
/**
* Clones the current Bundle. The internal map is cloned, but the keys and
* values to which it refers are copied by reference.
@@ -1589,24 +1597,29 @@ public final class Bundle implements Parcelable, Cloneable {
* @param parcel The parcel to copy this bundle to.
*/
public void writeToParcel(Parcel parcel, int flags) {
if (mParcelledData != null) {
int length = mParcelledData.dataSize();
parcel.writeInt(length);
parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
parcel.appendFrom(mParcelledData, 0, length);
} else {
parcel.writeInt(-1); // dummy, will hold length
parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
int oldPos = parcel.dataPosition();
parcel.writeMapInternal(mMap);
int newPos = parcel.dataPosition();
// Backpatch length
parcel.setDataPosition(oldPos - 8);
int length = newPos - oldPos;
parcel.writeInt(length);
parcel.setDataPosition(newPos);
final boolean oldAllowFds = parcel.setAllowFds(mAllowFds);
try {
if (mParcelledData != null) {
int length = mParcelledData.dataSize();
parcel.writeInt(length);
parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
parcel.appendFrom(mParcelledData, 0, length);
} else {
parcel.writeInt(-1); // dummy, will hold length
parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
int oldPos = parcel.dataPosition();
parcel.writeMapInternal(mMap);
int newPos = parcel.dataPosition();
// Backpatch length
parcel.setDataPosition(oldPos - 8);
int length = newPos - oldPos;
parcel.writeInt(length);
parcel.setDataPosition(newPos);
}
} finally {
parcel.setAllowFds(oldAllowFds);
}
}

View File

@@ -323,6 +323,9 @@ public final class Parcel {
*/
public final native void setDataCapacity(int size);
/** @hide */
public final native boolean setAllowFds(boolean allowFds);
/**
* Returns the raw bytes of the parcel.
*

View File

@@ -697,6 +697,10 @@ void signalExceptionForError(JNIEnv* env, jobject obj, status_t err)
LOGE("!!! FAILED BINDER TRANSACTION !!!");
//jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large");
break;
case FDS_NOT_ALLOWED:
jniThrowException(env, "java/lang/RuntimeException",
"Not allowed to write file descriptors here");
break;
default:
LOGE("Unknown binder error code. 0x%x", err);
}
@@ -1275,7 +1279,7 @@ static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size)
if (parcel != NULL) {
const status_t err = parcel->setDataSize(size);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1294,11 +1298,21 @@ static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint s
if (parcel != NULL) {
const status_t err = parcel->setDataCapacity(size);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
static jboolean android_os_Parcel_setAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
jboolean ret = JNI_TRUE;
if (parcel != NULL) {
ret = (jboolean)parcel->setAllowFds((bool)allowFds);
}
return ret;
}
static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
jobject data, jint offset,
jint length)
@@ -1310,12 +1324,13 @@ static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
const status_t err = parcel->writeInt32(length);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
return;
}
void* dest = parcel->writeInplace(length);
if (dest == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, NO_MEMORY);
return;
}
@@ -1333,7 +1348,7 @@ static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
if (parcel != NULL) {
const status_t err = parcel->writeInt32(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1344,7 +1359,7 @@ static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
if (parcel != NULL) {
const status_t err = parcel->writeInt64(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1355,7 +1370,7 @@ static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
if (parcel != NULL) {
const status_t err = parcel->writeFloat(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1366,7 +1381,7 @@ static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble va
if (parcel != NULL) {
const status_t err = parcel->writeDouble(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1386,7 +1401,7 @@ static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring va
err = parcel->writeString16(NULL, 0);
}
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1397,7 +1412,7 @@ static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobj
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1409,7 +1424,7 @@ static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jo
const status_t err =
parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
signalExceptionForError(env, clazz, err);
}
}
}
@@ -1717,7 +1732,10 @@ static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject par
return;
}
(void) thisParcel->appendFrom(otherParcel, offset, length);
status_t err = thisParcel->appendFrom(otherParcel, offset, length);
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
@@ -1792,6 +1810,7 @@ static const JNINativeMethod gParcelMethods[] = {
{"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
{"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
{"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
{"setAllowFds", "(Z)Z", (void*)android_os_Parcel_setAllowFds},
{"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
{"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
{"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},

View File

@@ -46,7 +46,7 @@ public:
size_t dataAvail() const;
size_t dataPosition() const;
size_t dataCapacity() const;
status_t setDataSize(size_t size);
void setDataPosition(size_t pos) const;
status_t setDataCapacity(size_t size);
@@ -56,6 +56,8 @@ public:
status_t appendFrom(const Parcel *parcel,
size_t start, size_t len);
bool setAllowFds(bool allowFds);
bool hasFileDescriptors() const;
// Writes the RPC header.
@@ -212,6 +214,7 @@ private:
mutable bool mFdsKnown;
mutable bool mHasFds;
bool mAllowFds;
release_func mOwner;
void* mOwnerCookie;

View File

@@ -72,6 +72,7 @@ enum {
TIMED_OUT = 0x80000005,
UNKNOWN_TRANSACTION = 0x80000006,
#endif
FDS_NOT_ALLOWED = 0x80000007,
};
// Restore define; enumeration is in "android" namespace, so the value defined

View File

@@ -399,6 +399,8 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
mDataPos += len;
mDataSize += len;
err = NO_ERROR;
if (numObjects > 0) {
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
@@ -430,11 +432,21 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
flat->handle = dup(flat->handle);
flat->cookie = (void*)1;
mHasFds = mFdsKnown = true;
if (!mAllowFds) {
err = FDS_NOT_ALLOWED;
}
}
}
}
return NO_ERROR;
return err;
}
bool Parcel::setAllowFds(bool allowFds)
{
const bool origValue = mAllowFds;
mAllowFds = allowFds;
return origValue;
}
bool Parcel::hasFileDescriptors() const
@@ -759,6 +771,9 @@ restart_write:
// remember if it's a file descriptor
if (val.type == BINDER_TYPE_FD) {
if (!mAllowFds) {
return FDS_NOT_ALLOWED;
}
mHasFds = mFdsKnown = true;
}
@@ -1283,6 +1298,7 @@ status_t Parcel::restartWrite(size_t desired)
mNextObjectHint = 0;
mHasFds = false;
mFdsKnown = true;
mAllowFds = true;
return NO_ERROR;
}
@@ -1434,6 +1450,7 @@ void Parcel::initState()
mNextObjectHint = 0;
mHasFds = false;
mFdsKnown = true;
mAllowFds = true;
mOwner = NULL;
}