Skip to content

Commit 20d8f58

Browse files
committed
8331671: Implement JEP 472: Prepare to Restrict the Use of JNI
Reviewed-by: jpai, prr, ihse, kcr, alanb
1 parent ce83f6a commit 20d8f58

File tree

107 files changed

+552
-183
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+552
-183
lines changed

make/conf/module-loader-map.conf

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -94,48 +94,26 @@ PLATFORM_MODULES_windows= \
9494

9595
NATIVE_ACCESS_MODULES= \
9696
java.base \
97-
java.datatransfer \
9897
java.desktop \
9998
java.instrument \
100-
java.logging \
10199
java.management \
102-
java.management.rmi \
103-
java.naming \
104-
java.net.http \
105100
java.prefs \
106101
java.rmi \
107-
java.scripting \
108-
java.se \
109102
java.security.jgss \
110-
java.security.sasl \
111103
java.smartcardio \
112-
java.sql \
113-
java.sql.rowset \
114-
java.transaction.xa \
115-
java.xml \
116-
java.xml.crypto \
117104
jdk.accessibility \
118-
jdk.charsets \
105+
jdk.attach \
119106
jdk.crypto.cryptoki \
120-
jdk.dynalink \
121-
jdk.httpserver \
122-
jdk.incubator.vector \
107+
jdk.crypto.mscapi \
108+
jdk.hotspot.agent \
123109
jdk.internal.le \
124110
jdk.internal.vm.ci \
111+
jdk.jdi \
125112
jdk.jfr \
126-
jdk.jsobject \
127-
jdk.localedata \
113+
jdk.jpackage \
128114
jdk.management \
129115
jdk.management.agent \
130-
jdk.management.jfr \
131-
jdk.naming.dns \
132-
jdk.naming.rmi \
133116
jdk.net \
134-
jdk.nio.mapmode \
135117
jdk.sctp \
136118
jdk.security.auth \
137-
jdk.security.jgss \
138-
jdk.unsupported \
139-
jdk.xml.dom \
140-
jdk.zipfs \
141119
#

make/test/BuildTestLib.gmk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ $(eval $(call SetupJavaCompilation, BUILD_TEST_LIB_JAR, \
6464
BIN := $(TEST_LIB_SUPPORT)/test-lib_classes, \
6565
HEADERS := $(TEST_LIB_SUPPORT)/test-lib_headers, \
6666
JAR := $(TEST_LIB_SUPPORT)/test-lib.jar, \
67-
DISABLED_WARNINGS := try deprecation rawtypes unchecked serial cast removal preview dangling-doc-comments, \
67+
DISABLED_WARNINGS := try deprecation rawtypes unchecked serial cast removal preview restricted dangling-doc-comments, \
6868
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
6969
--add-exports java.base/jdk.internal.classfile=ALL-UNNAMED \
7070
--add-exports java.base/jdk.internal.classfile.attribute=ALL-UNNAMED \

src/hotspot/share/classfile/vmClassMacros.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
do_klass(StackOverflowError_klass, java_lang_StackOverflowError ) \
7878
do_klass(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException ) \
7979
do_klass(Reference_klass, java_lang_ref_Reference ) \
80+
do_klass(IllegalCallerException_klass, java_lang_IllegalCallerException ) \
8081
\
8182
/* ref klasses and set reference types */ \
8283
do_klass(SoftReference_klass, java_lang_ref_SoftReference ) \

src/hotspot/share/classfile/vmSymbols.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ class SerializeClosure;
203203
template(java_lang_CloneNotSupportedException, "java/lang/CloneNotSupportedException") \
204204
template(java_lang_IllegalAccessException, "java/lang/IllegalAccessException") \
205205
template(java_lang_IllegalArgumentException, "java/lang/IllegalArgumentException") \
206+
template(java_lang_IllegalCallerException, "java/lang/IllegalCallerException") \
206207
template(java_lang_IllegalStateException, "java/lang/IllegalStateException") \
207208
template(java_lang_IllegalMonitorStateException, "java/lang/IllegalMonitorStateException") \
208209
template(java_lang_IllegalThreadStateException, "java/lang/IllegalThreadStateException") \
@@ -588,7 +589,7 @@ class SerializeClosure;
588589
template(string_boolean_class_signature, "(Ljava/lang/String;Z)Ljava/lang/Class;") \
589590
template(object_object_object_signature, "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
590591
template(string_string_signature, "(Ljava/lang/String;)Ljava/lang/String;") \
591-
template(classloader_string_long_signature, "(Ljava/lang/ClassLoader;Ljava/lang/String;)J") \
592+
template(classloader_class_string_string_long_signature, "(Ljava/lang/ClassLoader;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)J") \
592593
template(byte_array_void_signature, "([B)V") \
593594
template(long_long_void_signature, "(JJ)V") \
594595
template(void_byte_array_signature, "()[B") \

src/hotspot/share/prims/nativeLookup.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,16 +273,22 @@ address NativeLookup::lookup_style(const methodHandle& method, char* pure_name,
273273

274274
// Otherwise call static method findNative in ClassLoader
275275
Klass* klass = vmClasses::ClassLoader_klass();
276-
Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL);
276+
Handle jni_class(THREAD, method->method_holder()->java_mirror());
277+
Handle jni_name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL);
278+
Handle java_name_arg = java_lang_String::create_from_str(method->name()->as_C_string(), CHECK_NULL);
279+
280+
JavaCallArguments args;
281+
args.push_oop(loader);
282+
args.push_oop(jni_class);
283+
args.push_oop(jni_name_arg);
284+
args.push_oop(java_name_arg);
277285

278286
JavaValue result(T_LONG);
279287
JavaCalls::call_static(&result,
280288
klass,
281289
vmSymbols::findNative_name(),
282-
vmSymbols::classloader_string_long_signature(),
283-
// Arguments
284-
loader,
285-
name_arg,
290+
vmSymbols::classloader_class_string_string_long_signature(),
291+
&args,
286292
CHECK_NULL);
287293
entry = (address) (intptr_t) result.get_jlong();
288294

@@ -409,6 +415,14 @@ address NativeLookup::lookup_base(const methodHandle& method, TRAPS) {
409415
entry = lookup_entry_prefixed(method, CHECK_NULL);
410416
if (entry != nullptr) return entry;
411417

418+
if (THREAD->has_pending_exception()) {
419+
oop exception = THREAD->pending_exception();
420+
if (exception->is_a(vmClasses::IllegalCallerException_klass())) {
421+
// we already have a pending exception from the restricted method check, just return
422+
return nullptr;
423+
}
424+
}
425+
412426
// Native function not found, throw UnsatisfiedLinkError
413427
stringStream ss;
414428
ss.print("'");

src/hotspot/share/runtime/arguments.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ bool needs_module_property_warning = false;
305305
#define UPGRADE_PATH_LEN 12
306306
#define ENABLE_NATIVE_ACCESS "enable.native.access"
307307
#define ENABLE_NATIVE_ACCESS_LEN 20
308+
#define ILLEGAL_NATIVE_ACCESS "illegal.native.access"
309+
#define ILLEGAL_NATIVE_ACCESS_LEN 21
308310

309311
// Return TRUE if option matches 'property', or 'property=', or 'property.'.
310312
static bool matches_property_suffix(const char* option, const char* property, size_t len) {
@@ -326,6 +328,7 @@ bool Arguments::is_internal_module_property(const char* property) {
326328
matches_property_suffix(property_suffix, LIMITMODS, LIMITMODS_LEN) ||
327329
matches_property_suffix(property_suffix, PATH, PATH_LEN) ||
328330
matches_property_suffix(property_suffix, UPGRADE_PATH, UPGRADE_PATH_LEN) ||
331+
matches_property_suffix(property_suffix, ILLEGAL_NATIVE_ACCESS, ILLEGAL_NATIVE_ACCESS_LEN) ||
329332
matches_property_suffix(property_suffix, ENABLE_NATIVE_ACCESS, ENABLE_NATIVE_ACCESS_LEN)) {
330333
return true;
331334
}
@@ -2243,6 +2246,10 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m
22432246
if (!create_numbered_module_property("jdk.module.enable.native.access", tail, enable_native_access_count++)) {
22442247
return JNI_ENOMEM;
22452248
}
2249+
} else if (match_option(option, "--illegal-native-access=", &tail)) {
2250+
if (!create_module_property("jdk.module.illegal.native.access", tail, InternalProperty)) {
2251+
return JNI_ENOMEM;
2252+
}
22462253
} else if (match_option(option, "--limit-modules=", &tail)) {
22472254
if (!create_module_property("jdk.module.limitmods", tail, InternalProperty)) {
22482255
return JNI_ENOMEM;

src/java.base/share/classes/java/lang/ClassLoader.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,10 +2442,27 @@ static NativeLibrary loadLibrary(Class<?> fromClass, String name) {
24422442
" in java.library.path: " + StaticProperty.javaLibraryPath());
24432443
}
24442444

2445-
/*
2445+
/**
24462446
* Invoked in the VM class linking code.
2447+
* @param loader the class loader used to look up the native library symbol
2448+
* @param clazz the class in which the native method is declared
2449+
* @param entryName the native method's mangled name (this is the name used for the native lookup)
2450+
* @param javaName the native method's declared name
2451+
*/
2452+
static long findNative(ClassLoader loader, Class<?> clazz, String entryName, String javaName) {
2453+
long addr = findNativeInternal(loader, entryName);
2454+
if (addr != 0 && loader != null) {
2455+
Reflection.ensureNativeAccess(clazz, clazz, javaName, true);
2456+
}
2457+
return addr;
2458+
}
2459+
2460+
/*
2461+
* This is also called by SymbolLookup::loaderLookup. In that case, we need
2462+
* to avoid a restricted check, as that check has already been performed when
2463+
* obtaining the lookup.
24472464
*/
2448-
static long findNative(ClassLoader loader, String entryName) {
2465+
static long findNativeInternal(ClassLoader loader, String entryName) {
24492466
if (loader == null) {
24502467
return BootLoader.getNativeLibraries().find(entryName);
24512468
} else {

src/java.base/share/classes/java/lang/Module.java

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@
6262
import jdk.internal.loader.ClassLoaders;
6363
import jdk.internal.misc.CDS;
6464
import jdk.internal.misc.Unsafe;
65+
import jdk.internal.misc.VM;
6566
import jdk.internal.module.ModuleBootstrap;
67+
import jdk.internal.module.ModuleBootstrap.IllegalNativeAccess;
6668
import jdk.internal.module.ModuleLoaderMap;
6769
import jdk.internal.module.ServicesCatalog;
6870
import jdk.internal.module.Resources;
@@ -300,26 +302,43 @@ private Module moduleForNativeAccess() {
300302
}
301303

302304
// This is invoked from Reflection.ensureNativeAccess
303-
void ensureNativeAccess(Class<?> owner, String methodName, Class<?> currentClass) {
305+
void ensureNativeAccess(Class<?> owner, String methodName, Class<?> currentClass, boolean jni) {
304306
// The target module whose enableNativeAccess flag is ensured
305307
Module target = moduleForNativeAccess();
306-
if (!EnableNativeAccess.isNativeAccessEnabled(target)) {
307-
if (ModuleBootstrap.hasEnableNativeAccessFlag()) {
308-
throw new IllegalCallerException("Illegal native access from: " + this);
308+
ModuleBootstrap.IllegalNativeAccess illegalNativeAccess = ModuleBootstrap.illegalNativeAccess();
309+
if (illegalNativeAccess != ModuleBootstrap.IllegalNativeAccess.ALLOW &&
310+
!EnableNativeAccess.isNativeAccessEnabled(target)) {
311+
String mod = isNamed() ? "module " + getName() : "an unnamed module";
312+
if (currentClass != null) {
313+
// try to extract location of the current class (e.g. jar or folder)
314+
URL url = System.codeSource(currentClass);
315+
if (url != null) {
316+
mod += " (" + url + ")";
317+
}
309318
}
310-
if (EnableNativeAccess.trySetEnableNativeAccess(target)) {
319+
if (illegalNativeAccess == ModuleBootstrap.IllegalNativeAccess.DENY) {
320+
throw new IllegalCallerException("Illegal native access from " + mod);
321+
} else if (EnableNativeAccess.trySetEnableNativeAccess(target)) {
311322
// warn and set flag, so that only one warning is reported per module
312323
String cls = owner.getName();
313324
String mtd = cls + "::" + methodName;
314-
String mod = isNamed() ? "module " + getName() : "an unnamed module";
315325
String modflag = isNamed() ? getName() : "ALL-UNNAMED";
316326
String caller = currentClass != null ? currentClass.getName() : "code";
317-
System.err.printf("""
318-
WARNING: A restricted method in %s has been called
319-
WARNING: %s has been called by %s in %s
320-
WARNING: Use --enable-native-access=%s to avoid a warning for callers in this module
321-
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
322-
%n""", cls, mtd, caller, mod, modflag);
327+
if (jni) {
328+
VM.initialErr().printf("""
329+
WARNING: A native method in %s has been bound
330+
WARNING: %s is declared in %s
331+
WARNING: Use --enable-native-access=%s to avoid a warning for native methods declared in this module
332+
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
333+
%n""", cls, mtd, mod, modflag);
334+
} else {
335+
VM.initialErr().printf("""
336+
WARNING: A restricted method in %s has been called
337+
WARNING: %s has been called by %s in %s
338+
WARNING: Use --enable-native-access=%s to avoid a warning for callers in this module
339+
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
340+
%n""", cls, mtd, caller, mod, modflag);
341+
}
323342
}
324343
}
325344
}

src/java.base/share/classes/java/lang/ModuleLayer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ public Controller addOpens(Module source, String pn, Module target) {
323323
public Controller enableNativeAccess(Module target) {
324324
ensureInLayer(target);
325325
Reflection.ensureNativeAccess(Reflection.getCallerClass(), Module.class,
326-
"enableNativeAccess");
326+
"enableNativeAccess", false);
327327
target.implAddEnableNativeAccess();
328328
return this;
329329
}

src/java.base/share/classes/java/lang/Runtime.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2019, Azul Systems, Inc. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -36,6 +36,7 @@
3636
import java.util.StringTokenizer;
3737

3838
import jdk.internal.access.SharedSecrets;
39+
import jdk.internal.javac.Restricted;
3940
import jdk.internal.reflect.CallerSensitive;
4041
import jdk.internal.reflect.Reflection;
4142

@@ -828,14 +829,19 @@ public void runFinalization() {
828829
* a native library image by the host system.
829830
* @throws NullPointerException if {@code filename} is
830831
* {@code null}
832+
* @throws IllegalCallerException if the caller is in a module that
833+
* does not have native access enabled.
831834
* @spec jni/index.html Java Native Interface Specification
832835
* @see java.lang.Runtime#getRuntime()
833836
* @see java.lang.SecurityException
834837
* @see java.lang.SecurityManager#checkLink(java.lang.String)
835838
*/
836839
@CallerSensitive
840+
@Restricted
837841
public void load(String filename) {
838-
load0(Reflection.getCallerClass(), filename);
842+
Class<?> caller = Reflection.getCallerClass();
843+
Reflection.ensureNativeAccess(caller, Runtime.class, "load", false);
844+
load0(caller, filename);
839845
}
840846

841847
void load0(Class<?> fromClass, String filename) {
@@ -894,13 +900,18 @@ void load0(Class<?> fromClass, String filename) {
894900
* native library image by the host system.
895901
* @throws NullPointerException if {@code libname} is
896902
* {@code null}
903+
* @throws IllegalCallerException if the caller is in a module that
904+
* does not have native access enabled.
897905
* @spec jni/index.html Java Native Interface Specification
898906
* @see java.lang.SecurityException
899907
* @see java.lang.SecurityManager#checkLink(java.lang.String)
900908
*/
901909
@CallerSensitive
910+
@Restricted
902911
public void loadLibrary(String libname) {
903-
loadLibrary0(Reflection.getCallerClass(), libname);
912+
Class<?> caller = Reflection.getCallerClass();
913+
Reflection.ensureNativeAccess(caller, Runtime.class, "loadLibrary", false);
914+
loadLibrary0(caller, libname);
904915
}
905916

906917
void loadLibrary0(Class<?> fromClass, String libname) {

src/java.base/share/classes/java/lang/System.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import java.util.concurrent.ConcurrentHashMap;
7070
import java.util.stream.Stream;
7171

72+
import jdk.internal.javac.Restricted;
7273
import jdk.internal.logger.LoggerFinderLoader.TemporaryLoggerFinder;
7374
import jdk.internal.misc.Blocker;
7475
import jdk.internal.misc.CarrierThreadLocal;
@@ -355,7 +356,7 @@ private static class CallersHolder {
355356
= Collections.synchronizedMap(new WeakHashMap<>());
356357
}
357358

358-
private static URL codeSource(Class<?> clazz) {
359+
static URL codeSource(Class<?> clazz) {
359360
PrivilegedAction<ProtectionDomain> pa = clazz::getProtectionDomain;
360361
@SuppressWarnings("removal")
361362
CodeSource cs = AccessController.doPrivileged(pa).getCodeSource();
@@ -2017,14 +2018,19 @@ public static void runFinalization() {
20172018
* linked with the VM, or the library cannot be mapped to
20182019
* a native library image by the host system.
20192020
* @throws NullPointerException if {@code filename} is {@code null}
2021+
* @throws IllegalCallerException if the caller is in a module that
2022+
* does not have native access enabled.
20202023
*
20212024
* @spec jni/index.html Java Native Interface Specification
20222025
* @see java.lang.Runtime#load(java.lang.String)
20232026
* @see java.lang.SecurityManager#checkLink(java.lang.String)
20242027
*/
20252028
@CallerSensitive
2029+
@Restricted
20262030
public static void load(String filename) {
2027-
Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
2031+
Class<?> caller = Reflection.getCallerClass();
2032+
Reflection.ensureNativeAccess(caller, System.class, "load", false);
2033+
Runtime.getRuntime().load0(caller, filename);
20282034
}
20292035

20302036
/**
@@ -2055,14 +2061,19 @@ public static void load(String filename) {
20552061
* linked with the VM, or the library cannot be mapped to a
20562062
* native library image by the host system.
20572063
* @throws NullPointerException if {@code libname} is {@code null}
2064+
* @throws IllegalCallerException if the caller is in a module that
2065+
* does not have native access enabled.
20582066
*
20592067
* @spec jni/index.html Java Native Interface Specification
20602068
* @see java.lang.Runtime#loadLibrary(java.lang.String)
20612069
* @see java.lang.SecurityManager#checkLink(java.lang.String)
20622070
*/
20632071
@CallerSensitive
2072+
@Restricted
20642073
public static void loadLibrary(String libname) {
2065-
Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
2074+
Class<?> caller = Reflection.getCallerClass();
2075+
Reflection.ensureNativeAccess(caller, System.class, "loadLibrary", false);
2076+
Runtime.getRuntime().loadLibrary0(caller, libname);
20662077
}
20672078

20682079
/**
@@ -2539,8 +2550,8 @@ public boolean addEnableNativeAccess(ModuleLayer layer, String name) {
25392550
public void addEnableNativeAccessToAllUnnamed() {
25402551
Module.implAddEnableNativeAccessToAllUnnamed();
25412552
}
2542-
public void ensureNativeAccess(Module m, Class<?> owner, String methodName, Class<?> currentClass) {
2543-
m.ensureNativeAccess(owner, methodName, currentClass);
2553+
public void ensureNativeAccess(Module m, Class<?> owner, String methodName, Class<?> currentClass, boolean jni) {
2554+
m.ensureNativeAccess(owner, methodName, currentClass, jni);
25442555
}
25452556
public ServicesCatalog getServicesCatalog(ModuleLayer layer) {
25462557
return layer.getServicesCatalog();
@@ -2645,7 +2656,7 @@ public Object classData(Class<?> c) {
26452656

26462657
@Override
26472658
public long findNative(ClassLoader loader, String entry) {
2648-
return ClassLoader.findNative(loader, entry);
2659+
return ClassLoader.findNativeInternal(loader, entry);
26492660
}
26502661

26512662
@Override

0 commit comments

Comments
 (0)