Loading core/java/android/os/Binder.java +24 −1 Original line number Diff line number Diff line Loading @@ -102,6 +102,29 @@ public class Binder implements IBinder { */ public static final native void restoreCallingIdentity(long token); /** * Sets the native thread-local StrictMode policy mask. * * <p>The StrictMode settings are kept in two places: a Java-level * threadlocal for libcore/Dalvik, and a native threadlocal (set * here) for propagation via Binder calls. This is a little * unfortunate, but necessary to break otherwise more unfortunate * dependencies either of Dalvik on Android, or Android * native-only code on Dalvik. * * @see StrictMode * @hide */ public static final native void setThreadStrictModePolicy(int policyMask); /** * Gets the current native thread-local StrictMode policy mask. * * @see #setThreadStrictModePolicy * @hide */ public static final native int getThreadStrictModePolicy(); /** * Flush any Binder commands pending in the current thread to the kernel * driver. This can be Loading core/java/android/os/StrictMode.java +51 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,17 @@ public final class StrictMode { */ public static final int PENALTY_DROPBOX = 0x80; /** * Non-public penalty mode which overrides all the other penalty * bits and signals that we're in a Binder call and we should * ignore the other penalty bits and instead serialize back all * our offending stack traces to the caller to ultimately handle * in the originating process. * * @hide */ public static final int PENALTY_GATHER = 0x100; /** @hide */ public static final int PENALTY_MASK = PENALTY_LOG | PENALTY_DIALOG | Loading @@ -81,6 +92,19 @@ public final class StrictMode { * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values. */ public static void setThreadBlockingPolicy(final int policyMask) { // In addition to the Java-level thread-local in Dalvik's // BlockGuard, we also need to keep a native thread-local in // Binder in order to propagate the value across Binder calls, // even across native-only processes. The two are kept in // sync via the callback to onStrictModePolicyChange, below. setBlockGuardPolicy(policyMask); // And set the Android native version... Binder.setThreadStrictModePolicy(policyMask); } // Sets the policy in Dalvik/libcore (BlockGuard) private static void setBlockGuardPolicy(final int policyMask) { if (policyMask == 0) { BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); return; Loading Loading @@ -189,6 +213,11 @@ public final class StrictMode { new ApplicationErrorReport.CrashInfo(violation); crashInfo.durationMillis = durationMillis; if ((policy & PENALTY_GATHER) != 0) { Log.d(TAG, "StrictMode violation via Binder call; ignoring for now."); return; } // Not perfect, but fast and good enough for dup suppression. Integer crashFingerprint = crashInfo.stackTrace.hashCode(); long lastViolationTime = 0; Loading Loading @@ -227,13 +256,23 @@ public final class StrictMode { if (violationMask != 0) { violationMask |= violation.getPolicyViolation(); final int savedPolicy = getThreadBlockingPolicy(); try { // First, remove any policy before we call into the Activity Manager, // otherwise we'll infinite recurse as we try to log policy violations // to disk, thus violating policy, thus requiring logging, etc... // We restore the current policy below, in the finally block. setThreadBlockingPolicy(0); ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( RuntimeInit.getApplicationObject(), violationMask, new ApplicationErrorReport.CrashInfo(violation)); } catch (RemoteException e) { Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); } finally { // Restore the policy. setThreadBlockingPolicy(savedPolicy); } } Loading @@ -244,4 +283,16 @@ public final class StrictMode { } } } /** * Called from android_util_Binder.cpp's * android_os_Parcel_enforceInterface when an incoming Binder call * requires changing the StrictMode policy mask. The role of this * function is to ask Binder for its current (native) thread-local * policy value and synchronize it to libcore's (Java) * thread-local policy value. */ private static void onBinderStrictModePolicyChange(int newPolicy) { setBlockGuardPolicy(newPolicy); } } core/jni/android_util_Binder.cpp +67 −1 Original line number Diff line number Diff line Loading @@ -134,6 +134,12 @@ static struct parcel_file_descriptor_offsets_t jmethodID mConstructor; } gParcelFileDescriptorOffsets; static struct strict_mode_callback_offsets_t { jclass mClass; jmethodID mCallback; } gStrictModeCallbackOffsets; // **************************************************************************** // **************************************************************************** // **************************************************************************** Loading Loading @@ -214,6 +220,15 @@ bail: env->DeleteLocalRef(msgstr); } static void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy) { // Call back into android.os.StrictMode#onBinderStrictModePolicyChange // to sync our state back to it. See the comments in StrictMode.java. env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass, gStrictModeCallbackOffsets.mCallback, strict_policy); } class JavaBBinderHolder; class JavaBBinder : public BBinder Loading Loading @@ -253,12 +268,28 @@ protected: LOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); IPCThreadState* thread_state = IPCThreadState::self(); const int strict_policy_before = thread_state->getStrictModePolicy(); //printf("Transact from %p to Java code sending: ", this); //data.print(); //printf("\n"); jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, (int32_t)&data, (int32_t)reply, flags); jthrowable excep = env->ExceptionOccurred(); // Restore the Java binder thread's state if it changed while // processing a call (as it would if the Parcel's header had a // new policy mask and Parcel.enforceInterface() changed // it...) const int strict_policy_after = thread_state->getStrictModePolicy(); if (strict_policy_after != strict_policy_before) { // Our thread-local... thread_state->setStrictModePolicy(strict_policy_before); // And the Java-level thread-local... set_dalvik_blockguard_policy(env, strict_policy_before); } if (excep) { report_exception(env, excep, "*** Uncaught remote exception! " Loading Loading @@ -574,6 +605,16 @@ static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, IPCThreadState::self()->restoreCallingIdentity(token); } static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask) { IPCThreadState::self()->setStrictModePolicy(policyMask); } static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz) { return IPCThreadState::self()->getStrictModePolicy(); } static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) { IPCThreadState::self()->flushCommands(); Loading Loading @@ -618,6 +659,8 @@ static const JNINativeMethod gBinderMethods[] = { { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, { "init", "()V", (void*)android_os_Binder_init }, { "destroy", "()V", (void*)android_os_Binder_destroy } Loading Loading @@ -1523,9 +1566,24 @@ static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstri if (parcel != NULL) { const jchar* str = env->GetStringCritical(name, 0); if (str) { bool isValid = parcel->enforceInterface(String16(str, env->GetStringLength(name))); const int32_t old_strict_policy = IPCThreadState::self()->getStrictModePolicy(); int32_t strict_policy; bool isValid = parcel->enforceInterface( String16(str, env->GetStringLength(name)), &strict_policy); env->ReleaseStringCritical(name, str); if (isValid) { if (old_strict_policy != strict_policy) { // Need to keep the Java-level thread-local strict // mode policy in sync for the libcore // enforcements, which involves an upcall back // into Java. (We can't modify the // Parcel.enforceInterface signature, as it's // pseudo-public, and used via AIDL // auto-generation...) set_dalvik_blockguard_policy(env, strict_policy); } return; // everything was correct -> return silently } } Loading Loading @@ -1611,6 +1669,14 @@ static int int_register_android_os_Parcel(JNIEnv* env) gParcelOffsets.mOwnObject = env->GetFieldID(clazz, "mOwnObject", "I"); clazz = env->FindClass("android/os/StrictMode"); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode"); gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID( clazz, "onBinderStrictModePolicyChange", "(I)V"); LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL, "Unable to find strict mode callback."); return AndroidRuntime::registerNativeMethods( env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods)); Loading include/binder/Parcel.h +5 −1 Original line number Diff line number Diff line Loading @@ -58,9 +58,13 @@ public: // Writes the RPC header. status_t writeInterfaceToken(const String16& interface); // Parses the RPC header, returning true if the interface name // in the header matches the expected interface from the caller. bool enforceInterface(const String16& interface) const; // If strict_policy_out is non-NULL, the RPC header's StrictMode policy // mask is returned. bool enforceInterface(const String16& interface, int32_t* strict_policy_out = NULL) const; bool checkInterface(IBinder*) const; void freeData(); Loading libs/binder/IPCThreadState.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -372,8 +372,8 @@ void IPCThreadState::setStrictModePolicy(int32_t policy) mStrictModePolicy = policy; } int32_t IPCThreadState::getStrictModePolicy() const { int32_t IPCThreadState::getStrictModePolicy() const { return mStrictModePolicy; } Loading Loading
core/java/android/os/Binder.java +24 −1 Original line number Diff line number Diff line Loading @@ -102,6 +102,29 @@ public class Binder implements IBinder { */ public static final native void restoreCallingIdentity(long token); /** * Sets the native thread-local StrictMode policy mask. * * <p>The StrictMode settings are kept in two places: a Java-level * threadlocal for libcore/Dalvik, and a native threadlocal (set * here) for propagation via Binder calls. This is a little * unfortunate, but necessary to break otherwise more unfortunate * dependencies either of Dalvik on Android, or Android * native-only code on Dalvik. * * @see StrictMode * @hide */ public static final native void setThreadStrictModePolicy(int policyMask); /** * Gets the current native thread-local StrictMode policy mask. * * @see #setThreadStrictModePolicy * @hide */ public static final native int getThreadStrictModePolicy(); /** * Flush any Binder commands pending in the current thread to the kernel * driver. This can be Loading
core/java/android/os/StrictMode.java +51 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,17 @@ public final class StrictMode { */ public static final int PENALTY_DROPBOX = 0x80; /** * Non-public penalty mode which overrides all the other penalty * bits and signals that we're in a Binder call and we should * ignore the other penalty bits and instead serialize back all * our offending stack traces to the caller to ultimately handle * in the originating process. * * @hide */ public static final int PENALTY_GATHER = 0x100; /** @hide */ public static final int PENALTY_MASK = PENALTY_LOG | PENALTY_DIALOG | Loading @@ -81,6 +92,19 @@ public final class StrictMode { * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values. */ public static void setThreadBlockingPolicy(final int policyMask) { // In addition to the Java-level thread-local in Dalvik's // BlockGuard, we also need to keep a native thread-local in // Binder in order to propagate the value across Binder calls, // even across native-only processes. The two are kept in // sync via the callback to onStrictModePolicyChange, below. setBlockGuardPolicy(policyMask); // And set the Android native version... Binder.setThreadStrictModePolicy(policyMask); } // Sets the policy in Dalvik/libcore (BlockGuard) private static void setBlockGuardPolicy(final int policyMask) { if (policyMask == 0) { BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY); return; Loading Loading @@ -189,6 +213,11 @@ public final class StrictMode { new ApplicationErrorReport.CrashInfo(violation); crashInfo.durationMillis = durationMillis; if ((policy & PENALTY_GATHER) != 0) { Log.d(TAG, "StrictMode violation via Binder call; ignoring for now."); return; } // Not perfect, but fast and good enough for dup suppression. Integer crashFingerprint = crashInfo.stackTrace.hashCode(); long lastViolationTime = 0; Loading Loading @@ -227,13 +256,23 @@ public final class StrictMode { if (violationMask != 0) { violationMask |= violation.getPolicyViolation(); final int savedPolicy = getThreadBlockingPolicy(); try { // First, remove any policy before we call into the Activity Manager, // otherwise we'll infinite recurse as we try to log policy violations // to disk, thus violating policy, thus requiring logging, etc... // We restore the current policy below, in the finally block. setThreadBlockingPolicy(0); ActivityManagerNative.getDefault().handleApplicationStrictModeViolation( RuntimeInit.getApplicationObject(), violationMask, new ApplicationErrorReport.CrashInfo(violation)); } catch (RemoteException e) { Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); } finally { // Restore the policy. setThreadBlockingPolicy(savedPolicy); } } Loading @@ -244,4 +283,16 @@ public final class StrictMode { } } } /** * Called from android_util_Binder.cpp's * android_os_Parcel_enforceInterface when an incoming Binder call * requires changing the StrictMode policy mask. The role of this * function is to ask Binder for its current (native) thread-local * policy value and synchronize it to libcore's (Java) * thread-local policy value. */ private static void onBinderStrictModePolicyChange(int newPolicy) { setBlockGuardPolicy(newPolicy); } }
core/jni/android_util_Binder.cpp +67 −1 Original line number Diff line number Diff line Loading @@ -134,6 +134,12 @@ static struct parcel_file_descriptor_offsets_t jmethodID mConstructor; } gParcelFileDescriptorOffsets; static struct strict_mode_callback_offsets_t { jclass mClass; jmethodID mCallback; } gStrictModeCallbackOffsets; // **************************************************************************** // **************************************************************************** // **************************************************************************** Loading Loading @@ -214,6 +220,15 @@ bail: env->DeleteLocalRef(msgstr); } static void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy) { // Call back into android.os.StrictMode#onBinderStrictModePolicyChange // to sync our state back to it. See the comments in StrictMode.java. env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass, gStrictModeCallbackOffsets.mCallback, strict_policy); } class JavaBBinderHolder; class JavaBBinder : public BBinder Loading Loading @@ -253,12 +268,28 @@ protected: LOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); IPCThreadState* thread_state = IPCThreadState::self(); const int strict_policy_before = thread_state->getStrictModePolicy(); //printf("Transact from %p to Java code sending: ", this); //data.print(); //printf("\n"); jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, (int32_t)&data, (int32_t)reply, flags); jthrowable excep = env->ExceptionOccurred(); // Restore the Java binder thread's state if it changed while // processing a call (as it would if the Parcel's header had a // new policy mask and Parcel.enforceInterface() changed // it...) const int strict_policy_after = thread_state->getStrictModePolicy(); if (strict_policy_after != strict_policy_before) { // Our thread-local... thread_state->setStrictModePolicy(strict_policy_before); // And the Java-level thread-local... set_dalvik_blockguard_policy(env, strict_policy_before); } if (excep) { report_exception(env, excep, "*** Uncaught remote exception! " Loading Loading @@ -574,6 +605,16 @@ static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, IPCThreadState::self()->restoreCallingIdentity(token); } static void android_os_Binder_setThreadStrictModePolicy(JNIEnv* env, jobject clazz, jint policyMask) { IPCThreadState::self()->setStrictModePolicy(policyMask); } static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject clazz) { return IPCThreadState::self()->getStrictModePolicy(); } static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) { IPCThreadState::self()->flushCommands(); Loading Loading @@ -618,6 +659,8 @@ static const JNINativeMethod gBinderMethods[] = { { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, { "init", "()V", (void*)android_os_Binder_init }, { "destroy", "()V", (void*)android_os_Binder_destroy } Loading Loading @@ -1523,9 +1566,24 @@ static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstri if (parcel != NULL) { const jchar* str = env->GetStringCritical(name, 0); if (str) { bool isValid = parcel->enforceInterface(String16(str, env->GetStringLength(name))); const int32_t old_strict_policy = IPCThreadState::self()->getStrictModePolicy(); int32_t strict_policy; bool isValid = parcel->enforceInterface( String16(str, env->GetStringLength(name)), &strict_policy); env->ReleaseStringCritical(name, str); if (isValid) { if (old_strict_policy != strict_policy) { // Need to keep the Java-level thread-local strict // mode policy in sync for the libcore // enforcements, which involves an upcall back // into Java. (We can't modify the // Parcel.enforceInterface signature, as it's // pseudo-public, and used via AIDL // auto-generation...) set_dalvik_blockguard_policy(env, strict_policy); } return; // everything was correct -> return silently } } Loading Loading @@ -1611,6 +1669,14 @@ static int int_register_android_os_Parcel(JNIEnv* env) gParcelOffsets.mOwnObject = env->GetFieldID(clazz, "mOwnObject", "I"); clazz = env->FindClass("android/os/StrictMode"); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode"); gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID( clazz, "onBinderStrictModePolicyChange", "(I)V"); LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL, "Unable to find strict mode callback."); return AndroidRuntime::registerNativeMethods( env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods)); Loading
include/binder/Parcel.h +5 −1 Original line number Diff line number Diff line Loading @@ -58,9 +58,13 @@ public: // Writes the RPC header. status_t writeInterfaceToken(const String16& interface); // Parses the RPC header, returning true if the interface name // in the header matches the expected interface from the caller. bool enforceInterface(const String16& interface) const; // If strict_policy_out is non-NULL, the RPC header's StrictMode policy // mask is returned. bool enforceInterface(const String16& interface, int32_t* strict_policy_out = NULL) const; bool checkInterface(IBinder*) const; void freeData(); Loading
libs/binder/IPCThreadState.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -372,8 +372,8 @@ void IPCThreadState::setStrictModePolicy(int32_t policy) mStrictModePolicy = policy; } int32_t IPCThreadState::getStrictModePolicy() const { int32_t IPCThreadState::getStrictModePolicy() const { return mStrictModePolicy; } Loading