changeset 10843:0f023dd9a5a6

8015256: Better class accessibility Summary: Improve protection domain check in forName() Reviewed-by: mchung, acorn, jdn
author coleenp
date Tue, 22 Jul 2014 16:24:48 +0400
parents b64fb9d83655
children 4d816329dd2b
files src/java.base/share/classes/java/lang/Class.java src/java.base/share/native/include/jvm.h src/java.base/share/native/libjava/Class.c
diffstat 3 files changed, 29 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/Class.java	Thu May 08 21:09:57 2014 +0400
+++ b/src/java.base/share/classes/java/lang/Class.java	Tue Jul 22 16:24:48 2014 +0400
@@ -262,8 +262,8 @@
     @CallerSensitive
     public static Class<?> forName(String className)
                 throws ClassNotFoundException {
-        return forName0(className, true,
-                        ClassLoader.getClassLoader(Reflection.getCallerClass()));
+        Class<?> caller = Reflection.getCallerClass();
+        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
     }
 
 
@@ -333,22 +333,27 @@
                                    ClassLoader loader)
         throws ClassNotFoundException
     {
-        if (sun.misc.VM.isSystemDomainLoader(loader)) {
-            SecurityManager sm = System.getSecurityManager();
-            if (sm != null) {
-                ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass());
+        Class<?> caller = null;
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            // Reflective call to get caller class is only needed if a security manager
+            // is present.  Avoid the overhead of making this call otherwise.
+            caller = Reflection.getCallerClass();
+            if (sun.misc.VM.isSystemDomainLoader(loader)) {
+                ClassLoader ccl = ClassLoader.getClassLoader(caller);
                 if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
                     sm.checkPermission(
                         SecurityConstants.GET_CLASSLOADER_PERMISSION);
                 }
             }
         }
-        return forName0(name, initialize, loader);
+        return forName0(name, initialize, loader, caller);
     }
 
-    /** Called after security checks have been made. */
+    /** Called after security check for system loader access checks have been made. */
     private static native Class<?> forName0(String name, boolean initialize,
-                                            ClassLoader loader)
+                                            ClassLoader loader,
+                                            Class<?> caller)
         throws ClassNotFoundException;
 
     /**
--- a/src/java.base/share/native/include/jvm.h	Thu May 08 21:09:57 2014 +0400
+++ b/src/java.base/share/native/include/jvm.h	Tue Jul 22 16:24:48 2014 +0400
@@ -386,6 +386,19 @@
 JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
 
 /*
+ * Find a class from a given class loader.  Throws ClassNotFoundException.
+ *  name:   name of class
+ *  init:   whether initialization is done
+ *  loader: class loader to look up the class. This may not be the same as the caller's
+ *          class loader.
+ *  caller: initiating class. The initiating class may be null when a security
+ *          manager is not installed.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init,
+                        jobject loader, jclass caller);
+
+/*
  * Find a class from a given class loader. Throw ClassNotFoundException
  * or NoClassDefFoundError depending on the value of the last
  * argument.
--- a/src/java.base/share/native/libjava/Class.c	Thu May 08 21:09:57 2014 +0400
+++ b/src/java.base/share/native/libjava/Class.c	Tue Jul 22 16:24:48 2014 +0400
@@ -93,7 +93,7 @@
 
 JNIEXPORT jclass JNICALL
 Java_java_lang_Class_forName0(JNIEnv *env, jclass this, jstring classname,
-                              jboolean initialize, jobject loader)
+                              jboolean initialize, jobject loader, jclass caller)
 {
     char *clname;
     jclass cls = 0;
@@ -131,8 +131,7 @@
         goto done;
     }
 
-    cls = JVM_FindClassFromClassLoader(env, clname, initialize,
-                                       loader, JNI_FALSE);
+    cls = JVM_FindClassFromCaller(env, clname, initialize, loader, caller);
 
  done:
     if (clname != buf) {