8238460: Provide warnings about the use of JNI RegisterNatives to rebind native methods for boot/platform classes in other classloaders
Reviewed-by: jwilhelm, lfoltan
This commit is contained in:
parent
ccbd819a01
commit
9f21d809ab
@ -2811,6 +2811,20 @@ JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz,
|
||||
|
||||
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
|
||||
|
||||
// There are no restrictions on native code registering native methods, which
|
||||
// allows agents to redefine the bindings to native methods. But we issue a
|
||||
// warning if any code running outside of the boot/platform loader is rebinding
|
||||
// any native methods in classes loaded by the boot/platform loader.
|
||||
Klass* caller = thread->security_get_caller_class(1);
|
||||
bool do_warning = false;
|
||||
oop cl = k->class_loader();
|
||||
if (cl == NULL || SystemDictionary::is_platform_class_loader(cl)) {
|
||||
// If no caller class, or caller class has a different loader, then
|
||||
// issue a warning below.
|
||||
do_warning = (caller == NULL) || caller->class_loader() != cl;
|
||||
}
|
||||
|
||||
|
||||
for (int index = 0; index < nMethods; index++) {
|
||||
const char* meth_name = methods[index].name;
|
||||
const char* meth_sig = methods[index].signature;
|
||||
@ -2823,13 +2837,19 @@ JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz,
|
||||
TempNewSymbol signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig));
|
||||
|
||||
if (name == NULL || signature == NULL) {
|
||||
ResourceMark rm;
|
||||
ResourceMark rm(THREAD);
|
||||
stringStream st;
|
||||
st.print("Method %s.%s%s not found", k->external_name(), meth_name, meth_sig);
|
||||
// Must return negative value on failure
|
||||
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1);
|
||||
}
|
||||
|
||||
if (do_warning) {
|
||||
ResourceMark rm(THREAD);
|
||||
log_warning(jni, resolve)("Re-registering of platform native method: %s.%s%s "
|
||||
"from code in a different classloader", k->external_name(), meth_name, meth_sig);
|
||||
}
|
||||
|
||||
bool res = Method::register_native(k, name, signature,
|
||||
(address) methods[index].fnPtr, THREAD);
|
||||
if (!res) {
|
||||
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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 jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8238460
|
||||
* @summary Check that re-registering a native method of a boot class
|
||||
* generates a warning when not done from a boot class
|
||||
*
|
||||
* @library /test/lib
|
||||
* @run main/othervm/native TestRegisterNativesWarning
|
||||
*/
|
||||
|
||||
public class TestRegisterNativesWarning {
|
||||
|
||||
static {
|
||||
System.loadLibrary("registerNativesWarning");
|
||||
}
|
||||
|
||||
/*
|
||||
* We will replace:
|
||||
* java/lang/Thread.java: public static native void yield();
|
||||
*
|
||||
* as it is simple and innocuous.
|
||||
*/
|
||||
native static void test(Class<?> jlThread);
|
||||
|
||||
// Using a nested class that invokes an enclosing method makes it
|
||||
// easier to setup and use the native library.
|
||||
static class Tester {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Running test() in class loader " +
|
||||
Tester.class.getClassLoader());
|
||||
test(Thread.class);
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String warning = "Re-registering of platform native method: java.lang.Thread.yield()V from code in a different classloader";
|
||||
|
||||
OutputAnalyzer output = ProcessTools.executeTestJvm(Tester.class.getName());
|
||||
output.shouldContain(warning);
|
||||
output.shouldHaveExitValue(0);
|
||||
output.reportDiagnosticSummary();
|
||||
|
||||
// If we run everything from the "boot" loader there should be no warning
|
||||
String cp = System.getProperty("test.class.path");
|
||||
String libp = System.getProperty("java.library.path");
|
||||
output = ProcessTools.executeTestJvm("-Xbootclasspath/a:" + cp,
|
||||
"-Dsun.boot.library.path=" + libp,
|
||||
Tester.class.getName());
|
||||
output.shouldNotContain(warning);
|
||||
output.shouldHaveExitValue(0);
|
||||
output.reportDiagnosticSummary();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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 "jni.h"
|
||||
#include "jni_util.h"
|
||||
|
||||
/*
|
||||
* We will replace:
|
||||
* java/lang/Thread.java: public static native void yield();
|
||||
*
|
||||
* as it is simple and innocuous.
|
||||
*/
|
||||
static void myYield(JNIEnv* env, jclass cls) {
|
||||
printf("myYield executed\n");
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_TestRegisterNativesWarning_test
|
||||
(JNIEnv *env, jclass cls, jclass jlThread) {
|
||||
JNINativeMethod nativeMethods[] = {
|
||||
{
|
||||
(char*) "yield", // name
|
||||
(char*) "()V", // sig
|
||||
(void*) myYield // native method ptr
|
||||
}
|
||||
};
|
||||
(*env)->RegisterNatives(env, jlThread, nativeMethods, 1);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user