/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * java.security.AccessController */ #include "Dalvik.h" #include "native/InternalNativePriv.h" /* * private static ProtectionDomain[] getStackDomains() * * Return an array of ProtectionDomain objects from the classes of the * methods on the stack. Ignore reflection frames. Stop at the first * privileged frame we see. */ static void Dalvik_java_security_AccessController_getStackDomains( const u4* args, JValue* pResult) { UNUSED_PARAMETER(args); const Method** methods = NULL; int length; /* * Get an array with the stack trace in it. */ if (!dvmCreateStackTraceArray(dvmThreadSelf()->curFrame, &methods, &length)) { LOGE("Failed to create stack trace array\n"); dvmThrowException("Ljava/lang/InternalError;", NULL); RETURN_VOID(); } //int i; //LOGI("dvmCreateStackTraceArray results:\n"); //for (i = 0; i < length; i++) // LOGI(" %2d: %s.%s\n", i, methods[i]->clazz->name, methods[i]->name); /* * Generate a list of ProtectionDomain objects from the frames that * we're interested in. Skip the first two methods (this method, and * the one that called us), and ignore reflection frames. Stop on the * frame *after* the first privileged frame we see as we walk up. * * We create a new array, probably over-allocated, and fill in the * stuff we want. We could also just run the list twice, but the * costs of the per-frame tests could be more expensive than the * second alloc. (We could also allocate it on the stack using C99 * array creation, but it's not guaranteed to fit.) * * The array we return doesn't include null ProtectionDomain objects, * so we skip those here. */ Object** subSet = (Object**) malloc((length-2) * sizeof(Object*)); if (subSet == NULL) { LOGE("Failed to allocate subSet (length=%d)\n", length); free(methods); dvmThrowException("Ljava/lang/InternalError;", NULL); RETURN_VOID(); } int idx, subIdx = 0; for (idx = 2; idx < length; idx++) { const Method* meth = methods[idx]; Object* pd; if (dvmIsReflectionMethod(meth)) continue; if (dvmIsPrivilegedMethod(meth)) { /* find nearest non-reflection frame; note we skip priv frame */ //LOGI("GSD priv frame at %s.%s\n", meth->clazz->name, meth->name); while (++idx < length && dvmIsReflectionMethod(methods[idx])) ; length = idx; // stomp length to end loop meth = methods[idx]; } /* get the pd object from the method's class */ assert(gDvm.offJavaLangClass_pd != 0); pd = dvmGetFieldObject((Object*) meth->clazz, gDvm.offJavaLangClass_pd); //LOGI("FOUND '%s' pd=%p\n", meth->clazz->name, pd); if (pd != NULL) subSet[subIdx++] = pd; } //LOGI("subSet:\n"); //for (i = 0; i < subIdx; i++) // LOGI(" %2d: %s\n", i, subSet[i]->clazz->name); /* * Create an array object to contain "subSet". */ ClassObject* pdArrayClass = NULL; ArrayObject* domains = NULL; pdArrayClass = dvmFindArrayClass("[Ljava/security/ProtectionDomain;", NULL); if (pdArrayClass == NULL) { LOGW("Unable to find ProtectionDomain class for array\n"); goto bail; } domains = dvmAllocArray(pdArrayClass, subIdx, kObjectArrayRefWidth, ALLOC_DEFAULT); if (domains == NULL) { LOGW("Unable to allocate pd array (%d elems)\n", subIdx); goto bail; } /* copy the ProtectionDomain objects out */ Object** objects = (Object**) domains->contents; for (idx = 0; idx < subIdx; idx++) *objects++ = subSet[idx]; bail: free(subSet); free(methods); dvmReleaseTrackedAlloc((Object*) domains, NULL); RETURN_PTR(domains); } const DalvikNativeMethod dvm_java_security_AccessController[] = { { "getStackDomains", "()[Ljava/security/ProtectionDomain;", Dalvik_java_security_AccessController_getStackDomains }, { NULL, NULL, NULL }, };