Skip to content

Commit cd7d26f

Browse files
committed
Spec compliant substitutions for SecurityManager
Before this change the function `System#setSecurityManager` was always halting program execution with a VM error. This was inconvenient as the VM error prints an uncomprehensible error message and prevents further continuation of the program. For cases where the program is expected to throw an exception when `System#setSecurityManager` is called, execution on Native Image was not possible. Now, `System#setSecurityManager` throws an `java.lang.UnsupportedOperationException` by default. If the property `java.security.manager` is set to anything but `disallow` at program startup this function will throw a `java.lang.SecurityException` according to the Java spec.
1 parent e6e95c3 commit cd7d26f

File tree

9 files changed

+69
-25
lines changed

9 files changed

+69
-25
lines changed

docs/reference-manual/native-image/Compatibility.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ The `invokedynamic`method and method handles can introduce calls at run time or
4141

4242
Note that `invokedynamic` use cases generated by `javac` for, for example, Java lambda expressions and String concatenation that are supported because they do not change called methods at run time.
4343

44-
### Security Manager
45-
46-
Native Image will not allow a Java Security Manager to be enabled because this functionality has deprecated since Java 17.
47-
4844
## Features That May Operate Differently in a Native Image
4945

5046
Native Image implements some Java features differently to the Java VM.
5147

48+
### Security Manager
49+
50+
`java.lang.System#getSecurityManager()` always returns `null` even if the security manager is set via `-Djava.security.manager` at startup.
51+
52+
`java.lang.System#setSecurityManager(SecurityManager)` invoked with a non-null argument throws a `java.lang.SecurityException` if `-Djava.security.manager` is set to anything but `disallow` at program startup.
53+
5254
### Signal Handlers
5355

5456
Registering a signal handler requires a new thread to start that handles the signal and invokes shutdown hooks.

docs/security/native-image.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ The security report section of the native image [build output](../reference-manu
9393

9494
## Miscellaneous
9595

96+
Setting the security manager is not allowed. For more information see the [compatibility documentation](../reference-manual/native-image/Compatibility.md#security-manager).
97+
9698
Native Image provides multiple ways to specify a certificate file used to define the default TrustStore.
9799
While the default behavior for `native-image` is to capture and use the default TrustStore from the build-time host environment, this can be changed at run time by setting the "javax.net.ssl.trustStore\*" system properties.
98100
See the [documentation](../reference-manual/native-image/CertificateManagement.md) for more details.

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1414
* (GR-47937) Make the lambda-class name format in Native-Image consistent with the JDK name format.
1515
* (GR-45651) Methods, fields and constructors of `Object`, primitive classes and array classes are now registered by default for reflection.
1616
* (GR-45651) The Native Image agent now tracks calls to `ClassLoader.findSystemClass`, `ObjectInputStream.resolveClass` and `Bundles.of`, and registers resource bundles as bundle name-locale pairs.
17+
* (GR-49807) Before this change the function `System#setSecurityManager` was always halting program execution with a VM error. This was inconvenient as the VM error prints an uncomprehensible error message and prevents further continuation of the program. For cases where the program is expected to throw an exception when `System#setSecurityManager` is called, execution on Native Image was not possible. Now, `System#setSecurityManager` throws an `java.lang.UnsupportedOperationException` by default. If the property `java.security.manager` is set to anything but `disallow` at program startup this function will throw a `java.lang.SecurityException` according to the Java spec.
1718

1819
## GraalVM for JDK 21 (Internal Version 23.1.0)
1920
* (GR-35746) Lower the default aligned chunk size from 1 MB to 512 KB for the serial and epsilon GCs, reducing memory usage and image size in many cases.

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinSubstitutions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import static com.oracle.svm.core.posix.headers.darwin.DarwinTime.NoTransitions.mach_absolute_time;
2828
import static com.oracle.svm.core.posix.headers.darwin.DarwinTime.NoTransitions.mach_timebase_info;
2929

30+
import java.util.Objects;
31+
3032
import org.graalvm.nativeimage.ImageSingletons;
3133
import org.graalvm.nativeimage.Platform;
3234
import org.graalvm.nativeimage.Platforms;
@@ -52,6 +54,7 @@ private static long nanoTime() {
5254

5355
@Substitute
5456
public static String mapLibraryName(String libname) {
57+
Objects.requireNonNull(libname);
5558
return "lib" + libname + ".dylib";
5659
}
5760
}

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxSubstitutions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import com.oracle.svm.core.posix.headers.linux.LinuxTime;
3535
import com.oracle.svm.core.util.TimeUtils;
3636

37+
import java.util.Objects;
38+
3739
@TargetClass(java.lang.System.class)
3840
final class Target_java_lang_System_Linux {
3941

@@ -48,6 +50,7 @@ private static long nanoTime() {
4850

4951
@Substitute
5052
public static String mapLibraryName(String libname) {
53+
Objects.requireNonNull(libname);
5154
return "lib" + libname + ".so";
5255
}
5356
}

substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsJavaLangSubstitutions.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@
2525
package com.oracle.svm.core.windows;
2626

2727
import java.io.Console;
28+
import java.util.Objects;
2829

2930
import org.graalvm.nativeimage.Platform;
3031
import org.graalvm.nativeimage.Platforms;
3132
import org.graalvm.word.WordFactory;
3233

34+
import com.oracle.svm.core.Uninterruptible;
3335
import com.oracle.svm.core.annotate.Alias;
3436
import com.oracle.svm.core.annotate.RecomputeFieldValue;
3537
import com.oracle.svm.core.annotate.Substitute;
3638
import com.oracle.svm.core.annotate.TargetClass;
37-
import com.oracle.svm.core.Uninterruptible;
3839
import com.oracle.svm.core.jdk.Jvm;
3940

4041
@TargetClass(java.lang.System.class)
@@ -51,6 +52,7 @@ protected static long nanoTime() {
5152

5253
@Substitute
5354
public static String mapLibraryName(String libname) {
55+
Objects.requireNonNull(libname);
5456
return libname + ".dll";
5557
}
5658

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,9 @@ public static boolean useLIRBackend() {
685685
@Option(help = "Common prefix used by method symbols in image.")//
686686
public static final HostedOptionKey<String> ImageSymbolsPrefix = new HostedOptionKey<>("");
687687

688+
/**
689+
* Needs to be removed as part of GR-50210.
690+
*/
688691
@Option(help = "Fold SecurityManager getter.", stability = OptionStability.EXPERIMENTAL, type = OptionType.Expert) //
689692
public static final HostedOptionKey<Boolean> FoldSecurityManagerGetter = new HostedOptionKey<>(true);
690693

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@
7373
import java.util.Optional;
7474
import java.util.StringJoiner;
7575

76-
import jdk.graal.compiler.api.replacements.Fold;
77-
import jdk.graal.compiler.core.common.NumUtil;
78-
import jdk.graal.compiler.core.common.SuppressFBWarnings;
7976
import org.graalvm.nativeimage.AnnotationAccess;
8077
import org.graalvm.nativeimage.ImageSingletons;
8178
import org.graalvm.nativeimage.Platform;
@@ -119,6 +116,9 @@
119116
import com.oracle.svm.util.ReflectionUtil;
120117
import com.oracle.svm.util.ReflectionUtil.ReflectionUtilError;
121118

119+
import jdk.graal.compiler.api.replacements.Fold;
120+
import jdk.graal.compiler.core.common.NumUtil;
121+
import jdk.graal.compiler.core.common.SuppressFBWarnings;
122122
import jdk.internal.access.JavaLangReflectAccess;
123123
import jdk.internal.misc.Unsafe;
124124
import jdk.internal.reflect.CallerSensitive;
@@ -1228,6 +1228,14 @@ private void checkPackageAccess(SecurityManager sm, ClassLoader ccl, boolean che
12281228
/* No runtime access checks. */
12291229
}
12301230

1231+
/**
1232+
* Never called as it is partially evaluated away due to SecurityManager.
1233+
*/
1234+
@KeepOriginal
1235+
@SuppressWarnings({"deprecation", "unused"})
1236+
private static native void checkPackageAccessForPermittedSubclasses(@SuppressWarnings("removal") SecurityManager sm,
1237+
ClassLoader ccl, Class<?>[] subClasses);
1238+
12311239
@Substitute
12321240
private static ReflectionFactory getReflectionFactory() {
12331241
return Target_jdk_internal_reflect_ReflectionFactory.getReflectionFactory();

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.io.InputStream;
3333
import java.io.PrintStream;
3434
import java.net.URL;
35+
import java.security.Permission;
3536
import java.util.Arrays;
3637
import java.util.Enumeration;
3738
import java.util.List;
@@ -42,10 +43,6 @@
4243
import java.util.function.BooleanSupplier;
4344
import java.util.stream.Stream;
4445

45-
import jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode;
46-
import jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
47-
import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode;
48-
import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
4946
import org.graalvm.nativeimage.ImageSingletons;
5047
import org.graalvm.nativeimage.Platform;
5148
import org.graalvm.nativeimage.Platforms;
@@ -75,6 +72,10 @@
7572
import com.oracle.svm.core.util.VMError;
7673
import com.oracle.svm.util.ReflectionUtil;
7774

75+
import jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode;
76+
import jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
77+
import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode;
78+
import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
7879
import jdk.internal.loader.ClassLoaderValue;
7980
import jdk.internal.module.ServicesCatalog;
8081

@@ -402,23 +403,34 @@ private static String getProperty(String key, String def) {
402403
@Alias
403404
private static native void checkKey(String key);
404405

405-
/*
406-
* Note that there is no substitution for getSecurityManager, but instead getSecurityManager it
407-
* is intrinsified in SubstrateGraphBuilderPlugins to always return null. This allows better
408-
* constant folding of SecurityManager code already during static analysis.
406+
/**
407+
* Force System.Never in case it was set at build time via the `-Djava.security.manager=allow`
408+
* passed to the image builder.
409+
*/
410+
@Alias @RecomputeFieldValue(kind = Kind.FromAlias, isFinal = true) //
411+
private static int allowSecurityManager = 1;
412+
413+
/**
414+
* We do not support the {@link SecurityManager} so this method must throw a
415+
* {@link SecurityException} when 'java.security.manager' is set to anything but
416+
* <code>disallow</code>.
417+
*
418+
* @see System#setSecurityManager(SecurityManager)
419+
* @see SecurityManager
409420
*/
410421
@Substitute
411-
private static void setSecurityManager(SecurityManager s) {
412-
if (s != null) {
413-
/*
414-
* We deliberately treat this as a non-recoverable fatal error. We want to prevent bugs
415-
* where an exception is silently ignored by an application and then necessary security
416-
* checks are not in place.
417-
*/
418-
throw VMError.shouldNotReachHere("Installing a SecurityManager is not yet supported");
422+
private static void setSecurityManager(SecurityManager sm) {
423+
if (sm != null) {
424+
/* Read the property collected at isolate creation as that is what happens on the JVM */
425+
String smp = SystemPropertiesSupport.singleton().getSavedProperties().get("java.security.manager");
426+
if (smp != null && !smp.equals("disallow")) {
427+
throw new SecurityException("Setting the SecurityManager is not supported by Native Image");
428+
} else {
429+
throw new UnsupportedOperationException(
430+
"The Security Manager is deprecated and will be removed in a future release");
431+
}
419432
}
420433
}
421-
422434
}
423435

424436
final class NotAArch64 implements BooleanSupplier {
@@ -624,6 +636,14 @@ public static Enumeration<URL> findResources(String name) {
624636
// Checkstyle: resume
625637
}
626638

639+
@TargetClass(value = jdk.internal.logger.LoggerFinderLoader.class)
640+
final class Target_jdk_internal_logger_LoggerFinderLoader {
641+
// Checkstyle: stop
642+
@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset, isFinal = true)//
643+
static Permission READ_PERMISSION;
644+
// Checkstyle: resume
645+
}
646+
627647
final class ClassLoaderValueMapFieldValueTransformer implements FieldValueTransformer {
628648
@Override
629649
public Object transform(Object receiver, Object originalValue) {

0 commit comments

Comments
 (0)