ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2014年5月20日 星期二

Dalvik : CheckJni

Dalvik VM 有一個控制參數: checkjni

因為 jni code 比較難 debug,還有一旦出問題,就會造成整個 vm crash.
所以 android 提供一個 switch, 讓 user 決定是不是要啟動 dalvik 對 jni 的安全檢查。

ro.kernel.android.checkjni

這個 option 在 build eng type 的 image 時,會被加進 build.prop

framework 中參考這個 option 是在:framework/base/core/jni/AndroidRuntime.cpp:
 
   property_get("dalvik.vm.checkjni", propBuf, "");
    if (strcmp(propBuf, "true") == 0) {
        checkJni = true;
    } else if (strcmp(propBuf, "false") != 0) {
        /* property is neither true nor false; fall back on kernel parameter */
        property_get("ro.kernel.android.checkjni", propBuf, "");
        if (propBuf[0] == '1') {
            checkJni = true;
        }
    }
所以在 init.rc 中加上
 setprop dalvik.vm.checkjni false

也可以。

在 dalvik 的 source code 中。
vm/Jni.c:


        } else if (strcmp(optStr, "-Xcheck:jni") == 0) {
            checkJni = true;
        } else if (strncmp(optStr, "-Xjniopts:", 10) == 0) {
        ...
        
    if (checkJni) {
        dvmUseCheckedJniVm(pVM);
        pVM->useChecked = true;
    }


...

    if (vm->useChecked)
        dvmUseCheckedJniEnv(newEnv);


也就是說,一旦 enable check:jni..
vm 就會..
vm/CheckJni.c

void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
{
    assert(pEnv->funcTable != &gCheckNativeInterface);
    pEnv->baseFuncTable = pEnv->funcTable;
    pEnv->funcTable = &gCheckNativeInterface;
}


其中,gCheckNativeInterface 就是一些 check function..
static const struct JNINativeInterface gCheckNativeInterface = {
    NULL,
    NULL,
    NULL,
    NULL,

    Check_GetVersion,

    Check_DefineClass,
    Check_FindClass,

    Check_FromReflectedMethod,
    Check_FromReflectedField,
    Check_ToReflectedMethod,

    Check_GetSuperclass,
    Check_IsAssignableFrom,

    Check_ToReflectedField,

    ...
    ...

其中的一個,checkUtfString, 就是檢查 passing throught 的 string 是不是符合 modified utf 的格式。
/*
 * Verify that "bytes" points to valid "modified UTF-8" data.
 */
static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
    const char* func)
{
    const char* origBytes = bytes;
    ...
    ...
    while (*bytes != '\0') {
        u1 utf8 = *(bytes++);
        // Switch on the high four bits.
        switch (utf8 >> 4) {
            case 0x00:
            case 0x01:
            case 0x02:
            case 0x03:
            case 0x04:
            case 0x05:
            case 0x06:
            case 0x07: {
                // Bit pattern 0xxx. No need for any extra bytes.
                break;
            }
    .,,,

這個 function check fail 的話,在logcat 就會出現:
W/dalvikvm( 1044): JNI WARNING: illegal start byte 0xa6
W/dalvikvm( 1044):              string: '米??007亞洲初登場超級紀念盤 Disc 2'
W/dalvikvm( 1044):              in Landroid/media/MediaScanner;.processFile (Ljava/lang/String;Ljava
 /lang/String;Landroid/media/MediaScannerClient;)V (NewStringUTF)
..


ref:

沒有留言:

標籤

網誌存檔