changeset 9835:cb621c3e79a1

8015256: Better class accessibility Summary: Improve protection domain check in forName() Reviewed-by: mchung, acorn, jdn
author coleenp
date Thu, 08 May 2014 15:05:28 -0400
parents 759555060220
children 0ed398b58106
files src/share/classes/java/lang/Class.java src/share/javavm/export/jvm.h src/share/native/java/lang/Class.c
diffstat 3 files changed, 32 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/Class.java	Thu May 08 19:18:36 2014 +0400
+++ b/src/share/classes/java/lang/Class.java	Thu May 08 15:05:28 2014 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -256,8 +256,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);
     }
 
 
@@ -327,22 +327,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/share/javavm/export/jvm.h	Thu May 08 19:18:36 2014 +0400
+++ b/src/share/javavm/export/jvm.h	Thu May 08 15:05:28 2014 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -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/share/native/java/lang/Class.c	Thu May 08 19:18:36 2014 +0400
+++ b/src/share/native/java/lang/Class.c	Thu May 08 15:05:28 2014 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,7 +97,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;
@@ -135,8 +135,7 @@
         goto done;
     }
 
-    cls = JVM_FindClassFromClassLoader(env, clname, initialize,
-                                       loader, JNI_FALSE);
+    cls = JVM_FindClassFromCaller(env, clname, initialize, loader, caller);
 
  done:
     if (clname != buf) {