8189193: FindClass should only see classes from the boot loader called from its associated native library
authormchung
Thu, 19 Oct 2017 17:27:34 -0700
changeset 47662 2493edd8b479
parent 47661 92bcf2ab0cb3
child 47664 3f1d3f8c8407
8189193: FindClass should only see classes from the boot loader called from its associated native library Reviewed-by: coleenp, dholmes
make/test/JtregNativeHotspot.gmk
src/hotspot/share/prims/jni.cpp
test/hotspot/jtreg/runtime/jni/FindClass/BootLoaderTest.java
test/hotspot/jtreg/runtime/jni/FindClass/FindClassFromBoot.java
test/hotspot/jtreg/runtime/jni/FindClass/java.base/java/lang/BootNativeLibrary.java
test/hotspot/jtreg/runtime/jni/FindClass/libbootLoaderTest.c
--- a/make/test/JtregNativeHotspot.gmk	Thu Oct 19 11:31:52 2017 -0700
+++ b/make/test/JtregNativeHotspot.gmk	Thu Oct 19 17:27:34 2017 -0700
@@ -50,6 +50,7 @@
     $(TOPDIR)/test/hotspot/jtreg/runtime/jni/8025979 \
     $(TOPDIR)/test/hotspot/jtreg/runtime/jni/8033445 \
     $(TOPDIR)/test/hotspot/jtreg/runtime/jni/checked \
+    $(TOPDIR)/test/hotspot/jtreg/runtime/jni/FindClass \
     $(TOPDIR)/test/hotspot/jtreg/runtime/jni/PrivateInterfaceMethods \
     $(TOPDIR)/test/hotspot/jtreg/runtime/jni/ToStringInInterfaceTest \
     $(TOPDIR)/test/hotspot/jtreg/runtime/jni/CalleeSavedRegisters \
--- a/src/hotspot/share/prims/jni.cpp	Thu Oct 19 11:31:52 2017 -0700
+++ b/src/hotspot/share/prims/jni.cpp	Thu Oct 19 17:27:34 2017 -0700
@@ -396,10 +396,11 @@
   }
 
   //%note jni_3
-  Handle loader;
   Handle protection_domain;
   // Find calling class
   Klass* k = thread->security_get_caller_class(0);
+  // default to the system loader when no context
+  Handle loader(THREAD, SystemDictionary::java_system_loader());
   if (k != NULL) {
     // Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed
     // in the correct class context.
@@ -424,11 +425,6 @@
     }
   }
 
-  if (loader.is_null()) {
-    // No context and use the system class loader
-    loader = Handle(THREAD, SystemDictionary::java_system_loader());
-  }
-
   TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);
   result = find_class_from_class_loader(env, sym, true, loader,
                                         protection_domain, true, thread);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/jni/FindClass/BootLoaderTest.java	Thu Oct 19 17:27:34 2017 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+import java.lang.BootNativeLibrary;
+
+/*
+ * This is called from FindClassFromBoot class.
+ */
+public class BootLoaderTest {
+    public static void main(String... args) throws Exception {
+        testJNIFindClass("java/lang/String", String.class);
+        testJNIFindClass("java/lang/BootNativeLibrary", BootNativeLibrary.class);
+        testJNIFindClass("BootLoaderTest", null);
+    }
+
+    /*
+     * Call JNI FindClass with null loader as the context
+     */
+    static void testJNIFindClass(String name, Class<?> expected) {
+        Class<?> c = BootNativeLibrary.findClass(name);
+        if (c != expected) {
+            throw new RuntimeException("FindClass " + c + " expected: " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/jni/FindClass/FindClassFromBoot.java	Thu Oct 19 17:27:34 2017 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8189193
+ * @library /test/lib
+ * @build jdk.test.lib.process.ProcessTools
+ * @build java.base/java.lang.BootNativeLibrary BootLoaderTest FindClassFromBoot
+ * @run main/othervm/native -Xcheck:jni FindClassFromBoot
+ * @summary verify if the native library loaded by the boot loader
+ *          can only find classes visible to the boot loader
+ */
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.process.ProcessTools;
+
+public class FindClassFromBoot {
+    public static void main(String... args) throws Exception {
+        Path patches = Paths.get(System.getProperty("test.classes"), "patches", "java.base");
+        String syspaths = System.getProperty("sun.boot.library.path") +
+                              File.pathSeparator + System.getProperty("java.library.path");
+        ProcessTools.executeTestJvm("-Dsun.boot.library.path=" + syspaths,
+                                    "--patch-module", "java.base=" + patches.toString(),
+                                    "BootLoaderTest")
+                    .shouldHaveExitValue(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/jni/FindClass/java.base/java/lang/BootNativeLibrary.java	Thu Oct 19 17:27:34 2017 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+public class BootNativeLibrary {
+    static {
+        System.loadLibrary("bootLoaderTest");
+    }
+
+    public static native Class<?> findClass(String name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/jni/FindClass/libbootLoaderTest.c	Thu Oct 19 17:27:34 2017 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "jni.h"
+#include "jni_util.h"
+
+JNIEXPORT jclass JNICALL
+Java_java_lang_BootNativeLibrary_findClass
+(JNIEnv *env, jclass cls, jstring name) {
+    jclass ncdfe;
+    jthrowable t;
+
+    const char* classname = (*env)->GetStringUTFChars(env, name, JNI_FALSE);
+    jclass c = (*env)->FindClass(env, classname);
+    (*env)->ReleaseStringUTFChars(env, name, classname);
+
+    if (c == NULL) {
+        // clear NCDFE
+        t = (*env)->ExceptionOccurred(env);
+        ncdfe = (*env)->FindClass(env, "java/lang/NoClassDefFoundError");
+        if (t != NULL && (*env)->IsInstanceOf(env, t, ncdfe)) {
+            (*env)->ExceptionClear(env);
+        }
+    }
+    return c;
+}