/* * 比较名称。以较特定的方法,参数、内容和返回值,如果他们相等或者不等于0,则返回0 * */ static inline int compareMethodHelper(Method* method, const char* methodName, const char* returnType, size_t argCount, const char** argTypes) { DexParameterIterator iterator; const DexProto* proto; if (strcmp(methodName, method->name) != 0) { return 1; } proto = &method->prototype; if (strcmp(returnType, dexProtoGetReturnType(proto)) != 0) { return 1; } if (dexProtoGetParameterCount(proto) != argCount) { return 1; } dexParameterIteratorInit(&iterator, proto); for (/*argCount*/; argCount != 0; argCount--, argTypes++) { const char* argType = *argTypes; const char* paramType = dexParameterIteratorNextDescriptor(&iterator); if (paramType == NULL) { /* Param list ended early; no match */ break; } else if (strcmp(argType, paramType) != 0) { /* Types aren't the same; no match. */ break; } } if (argCount == 0) { /* We ran through all the given arguments... */ if (dexParameterIteratorNextDescriptor(&iterator) == NULL) { /* ...and through all the method's arguments; success! */ return 0; } } return 1; }
/* Used to propagate taint for JNI methods * Two types of propagation: * 1) simple conservative propagation based on parameters * 2) propagation based on function profile policies */ void dvmTaintPropJniMethod(const u4* args, JValue* pResult, const Method* method, const int nativeTaint) { const DexProto* proto = &method->prototype; DexParameterIterator pIterator; int nParams = dexProtoGetParameterCount(proto); int pStart = (dvmIsStaticMethod(method)?0:1); /* index where params start */ /* Consider 3 arguments. [x] indicates return taint index * 0 1 2 [3] 4 5 6 */ int nArgs = method->insSize; u4* rtaint = (u4*) &args[nArgs]; /* The return taint value */ int tStart = nArgs+1; /* index of args[] where taint values start */ int tEnd = nArgs*2; /* index of args[] where taint values end */ u4 tag = TAINT_CLEAR; int i; #if 0 { char *desc = dexProtoCopyMethodDescriptor(proto); ALOGW("Jni: %s.%s%s, descriptor: %s", method->clazz->descriptor, method->name, dvmIsStaticMethod(method)?"[static]":"", desc); free(desc); } #endif #ifdef TAINT_JNI_LOG /* JNI logging for debugging purposes */ if (gJniLog) { u4 hash; int len; char *inStr, *outStr; len = strlen(method->clazz->descriptor) + 1 + strlen(method->name); inStr = (char*) malloc(len+1); strcpy(inStr, method->clazz->descriptor); strcat(inStr, "."); strcat(inStr, method->name); hash = dvmComputeUtf8Hash(inStr); dvmHashTableLock(gJniLogSeen); outStr = (char*) dvmHashTableLookup(gJniLogSeen, hash, inStr, (HashCompareFunc) strcmp, false); if (outStr == NULL) { /* New method! */ /* add it */ dvmHashTableLookup(gJniLogSeen, hash, inStr, (HashCompareFunc) strcmp, true); } else { free(inStr); /* don't need this anymore */ } dvmHashTableUnlock(gJniLogSeen); } #endif /* Union the taint tags, this includes object ref tags * - we don't need to worry about static vs. not static, because getting * the taint tag on the "this" object reference is a good * - we don't need to worry about wide registers, because the stack * interleaving of taint tags makes it transparent */ /*for (i = tStart; i <= tEnd; i++) { tag |= args[i]; if (args[i]!=0 && args[i]!=TAINT_ACCELEROMETER) //found a taint, and its not the accelerometer spam either ALOGD("dvmTaintPropJNIMethod found taint %08x in method=%s:%s(%s) for arg[%d]=%08x", args[i], method->clazz->descriptor, method->name, method->shorty, i-nArgs, args[i-nArgs]); }*/ /* If not static, pull any taint from the "this" object */ /*if (!dvmIsStaticMethod(method)) { tag |= getObjectTaint((Object*)args[0], method->clazz->descriptor); }*/ /* Union taint from Objects we care about */ dexParameterIteratorInit(&pIterator, proto); for (i=pStart; ; i++) { const char* desc = dexParameterIteratorNextDescriptor(&pIterator); if (desc == NULL) { break; } if (desc[0] == '[' || desc[0] == 'L') { tag |= getObjectTaint((Object*) args[i], desc); } if (desc[0] == 'J' || desc[0] == 'D') { /* wide argument, increment index one more */ i++; } } /* Look at the taint policy profiles (may have return taint) */ //tag |= propMethodProfile(args, method); /* Update return taint according to the return type */ //Native Tainting: get taint Value from native code //if (tag) { if (nativeTaint) { const char* desc = dexProtoGetReturnType(proto); //setReturnTaint(tag, rtaint, pResult, desc); ALOGD("dvmTaintPropJniMethod: setting result taint to %x", nativeTaint); setReturnTaint(nativeTaint, rtaint, pResult, desc); } }
/* * Return a new Object[] array with the contents of "args". We determine * the number and types of values in "args" based on the method signature. * Primitive types are boxed. * * Returns NULL if the method takes no arguments. * * The caller must call dvmReleaseTrackedAlloc() on the return value. * * On failure, returns with an appropriate exception raised. */ static ArrayObject* boxMethodArgs(const Method* method, const u4* args) { const char* desc = &method->shorty[1]; // [0] is the return type. ArrayObject* argArray = NULL; int argCount; Object** argObjects; bool failed = true; /* count args */ argCount = dexProtoGetParameterCount(&method->prototype); /* allocate storage */ argArray = dvmAllocArray(gDvm.classJavaLangObjectArray, argCount, kObjectArrayRefWidth, ALLOC_DEFAULT); if (argArray == NULL) goto bail; argObjects = (Object**) argArray->contents; /* * Fill in the array. */ int srcIndex = 0; argCount = 0; while (*desc != '\0') { char descChar = *(desc++); JValue value; switch (descChar) { case 'Z': case 'C': case 'F': case 'B': case 'S': case 'I': value.i = args[srcIndex++]; argObjects[argCount] = (Object*) dvmWrapPrimitive(value, dvmFindPrimitiveClass(descChar)); /* argObjects is tracked, don't need to hold this too */ dvmReleaseTrackedAlloc(argObjects[argCount], NULL); argCount++; break; case 'D': case 'J': value.j = dvmGetArgLong(args, srcIndex); srcIndex += 2; argObjects[argCount] = (Object*) dvmWrapPrimitive(value, dvmFindPrimitiveClass(descChar)); dvmReleaseTrackedAlloc(argObjects[argCount], NULL); argCount++; break; case '[': case 'L': argObjects[argCount++] = (Object*) args[srcIndex++]; break; } } failed = false; bail: if (failed) { dvmReleaseTrackedAlloc((Object*)argArray, NULL); argArray = NULL; } return argArray; }