Skip to content

Commit 5a13ce9

Browse files
committed
New substitution for setSecurityManager
1 parent e3a9c73 commit 5a13ce9

File tree

7 files changed

+60
-44
lines changed

7 files changed

+60
-44
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ Note that `invokedynamic` use cases generated by `javac` for, for example, Java
4343

4444
### Security Manager
4545

46-
Native Image will not allow setting `-Djava.security.manager` to anything but `"disallow"` at image build time or image run time.
46+
Native Image will produce images as if `-Djava.security.manager` was set to `disallow`.
47+
At image run time, calls to `java.lang.System#setSecurityManager` exit the program with error code `255` if `-Djava.security.manager` is set to anything but `disallow` at program startup.
4748

4849
## Features That May Operate Differently in a Native Image
4950

substratevm/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +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 `allow` the program will print a user-readable stack trace and exit with code `99`.
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 `allow` the program will print a user-readable stack trace and exit with code `99`. Value of `java.security.manager` that would be set at build time is completely ignored at run time.
1818

1919
## GraalVM for JDK 21 (Internal Version 23.1.0)
2020
* (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/src/com/oracle/svm/core/JavaMainWrapper.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.List;
3636
import java.util.function.BooleanSupplier;
3737

38+
import jdk.graal.compiler.word.Word;
3839
import org.graalvm.nativeimage.CurrentIsolate;
3940
import org.graalvm.nativeimage.ImageSingletons;
4041
import org.graalvm.nativeimage.Isolate;
@@ -80,8 +81,6 @@
8081
import com.oracle.svm.util.ClassUtil;
8182
import com.oracle.svm.util.ReflectionUtil;
8283

83-
import jdk.graal.compiler.word.Word;
84-
8584
@InternalVMMethod
8685
public class JavaMainWrapper {
8786
/*
@@ -225,13 +224,6 @@ private static int runCore0() {
225224
// Ensure that native code using JNI_GetCreatedJavaVMs finds this isolate.
226225
JNIJavaVMList.addJavaVM(JNIFunctionTables.singleton().getGlobalJavaVM());
227226

228-
String smp = System.getProperty("java.security.manager");
229-
if (smp != null && !"disallow".equals(smp)) {
230-
System.err.println("Error: Property '-Djava.security.manager' is set. SecurityManager is not supported by Native Image. Please unset this property. " +
231-
"Exiting the program to prevent misinterpretation of the set SecurityManager.");
232-
System.exit(-1);
233-
}
234-
235227
/*
236228
* Invoke the application's main method. Invoking the main method via a method handle
237229
* preserves exceptions, while invoking the main method via reflection would wrap

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,8 +1228,8 @@ private void checkPackageAccess(SecurityManager sm, ClassLoader ccl, boolean che
12281228
}
12291229

12301230
/**
1231-
* Never called, but consider reachable by a that happens bug in an interaction between PE
1232-
* and @Delete in analysis.
1231+
* GR-49983: Never called and partially evaluated, but fails if removed. Can be removed when
1232+
* GR-49983 is fixed.
12331233
*/
12341234
@KeepOriginal
12351235
@SuppressWarnings({"deprecation", "unused"})

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

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.util.stream.Stream;
4545

4646
import org.graalvm.nativeimage.ImageSingletons;
47+
import org.graalvm.nativeimage.LogHandler;
4748
import org.graalvm.nativeimage.Platform;
4849
import org.graalvm.nativeimage.Platforms;
4950
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
@@ -66,12 +67,14 @@
6667
import com.oracle.svm.core.hub.DynamicHub;
6768
import com.oracle.svm.core.jdk.JavaLangSubstitutions.ClassValueSupport;
6869
import com.oracle.svm.core.monitor.MonitorSupport;
70+
import com.oracle.svm.core.option.HostedOptionKey;
6971
import com.oracle.svm.core.snippets.SubstrateForeignCallTarget;
7072
import com.oracle.svm.core.thread.JavaThreads;
7173
import com.oracle.svm.core.thread.VMOperation;
7274
import com.oracle.svm.core.util.VMError;
7375
import com.oracle.svm.util.ReflectionUtil;
7476

77+
import jdk.graal.compiler.options.Option;
7578
import jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode;
7679
import jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
7780
import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode;
@@ -342,21 +345,6 @@ final class Target_java_lang_System {
342345
@Alias private static PrintStream err;
343346
@Alias private static InputStream in;
344347

345-
/**
346-
* This substitution can be removed when the warning for setting `-Djava.security.manager=allow`
347-
* in the image build is converted into an error.
348-
*/
349-
@Substitute
350-
private static boolean allowSecurityManager() {
351-
if (SystemPropertiesSupport.singleton().isSecurityManagerAllowed()) {
352-
/* Fail fatally in case someone tried to set the SM at build time */
353-
System.err.println("Error: Property '-Djava.security.manager' was set at build time. Security manager is not supported by native image. Please unset this property. " +
354-
"Exiting the program to prevent misinterpretation of the set SecurityManager.");
355-
System.exit(-1);
356-
}
357-
return false;
358-
}
359-
360348
@Substitute
361349
private static void setIn(InputStream is) {
362350
in = is;
@@ -417,6 +405,41 @@ private static String getProperty(String key, String def) {
417405

418406
@Alias
419407
private static native void checkKey(String key);
408+
409+
/**
410+
* Force System.Never in case it was set at build time via the `-Djava.security.manager=allow`
411+
* passed to the image builder.
412+
*/
413+
@Alias @RecomputeFieldValue(kind = Kind.FromAlias, isFinal = true) //
414+
private static int allowSecurityManager = 1;
415+
416+
@Substitute
417+
@TargetElement(onlyWith = JavaLangSubstitutions.UseSecurityManagerPropertyAtRuntime.class)
418+
private static void setSecurityManager(SecurityManager s) {
419+
/* We read properties interpreted at isolate creation as that is what happens on the JVM */
420+
String smp = SystemPropertiesSupport.singleton().getSavedProperties().get("java.security.manager");
421+
if (smp != null && !smp.equals("disallow")) {
422+
/*
423+
* The strict failure is needed as the security precaution: In case a user does not read
424+
* our documentation, uses this deprecated API marked for removal, and passes
425+
* "-Djava.security.manager=allow" at runtime, and accidentally catches the
426+
* UnsupportedOperationException, we don't want to compromise their security.
427+
*/
428+
System.err.println("""
429+
Fatal error: Property '-Djava.security.manager' is set, but SecurityManager is not supported by Native Image. Please unset this property.
430+
Exiting the program to prevent misinterpretation of the set SecurityManager at:""");
431+
432+
for (var traceElement : new UnsupportedOperationException().getStackTrace()) {
433+
System.err.println("\tat " + traceElement);
434+
}
435+
436+
/* bypasses possible filters on System.exit */
437+
ImageSingletons.lookup(LogHandler.class).fatalError();
438+
}
439+
440+
throw new UnsupportedOperationException(
441+
"The Security Manager is deprecated and will be removed in a future release");
442+
}
420443
}
421444

422445
final class NotAArch64 implements BooleanSupplier {
@@ -622,6 +645,9 @@ public static Enumeration<URL> findResources(String name) {
622645
// Checkstyle: resume
623646
}
624647

648+
/**
649+
* This substitution should not be needed: GR-49983.
650+
*/
625651
@TargetClass(value = jdk.internal.logger.LoggerFinderLoader.class)
626652
final class Target_jdk_internal_logger_LoggerFinderLoader {
627653
// Checkstyle: stop
@@ -660,6 +686,18 @@ public Object transform(Object receiver, Object originalValue) {
660686
/** Dummy class to have a class with the file's name. */
661687
public final class JavaLangSubstitutions {
662688

689+
public static class UseSecurityManagerPropertyAtRuntime implements BooleanSupplier {
690+
public static class Options {
691+
@Option(help = "Used only for testing as exiting the program shadows other working tests, please do not use in production.")//
692+
public static final HostedOptionKey<Boolean> TestingSecurityViolationUseSecurityManagerPropertyAtRuntime = new HostedOptionKey<>(true);
693+
}
694+
695+
@Override
696+
public boolean getAsBoolean() {
697+
return Options.TestingSecurityViolationUseSecurityManagerPropertyAtRuntime.getValue();
698+
}
699+
}
700+
663701
public static final class StringUtil {
664702
/**
665703
* Returns a character from a string at {@code index} position based on the encoding format.

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Properties;
3131
import java.util.function.Supplier;
3232

33+
import jdk.graal.compiler.api.replacements.Fold;
3334
import org.graalvm.nativeimage.ImageInfo;
3435
import org.graalvm.nativeimage.ImageSingletons;
3536
import org.graalvm.nativeimage.Platform;
@@ -40,8 +41,6 @@
4041
import com.oracle.svm.core.config.ConfigurationValues;
4142
import com.oracle.svm.core.util.VMError;
4243

43-
import jdk.graal.compiler.api.replacements.Fold;
44-
4544
/**
4645
* This class maintains the system properties at run time.
4746
*
@@ -90,8 +89,6 @@ public abstract class SystemPropertiesSupport implements RuntimeSystemProperties
9089
private final String hostOS = System.getProperty("os.name");
9190
// needed as fallback for platforms that don't implement osNameValue
9291

93-
private final boolean securityManagerAllowed = System.getProperty("java.security.manager") != null && !"disallow".equals(System.getProperty("java.security.manager"));
94-
9592
private volatile boolean fullyInitialized;
9693

9794
@Fold
@@ -319,9 +316,4 @@ protected String osNameValue() {
319316
}
320317

321318
protected abstract String osVersionValue();
322-
323-
@Fold
324-
public boolean isSecurityManagerAllowed() {
325-
return securityManagerAllowed;
326-
}
327319
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,6 @@ public void run() {
132132
throw UserError.abort("Unknown options: %s", String.join(" ", remainingArguments));
133133
}
134134

135-
var smp = System.getProperty("java.security.manager");
136-
if (smp != null && !"disallow".equals(smp)) {
137-
/* Warning will be promoted to an `UserError.abort` in future builds. */
138-
LogUtils.warning("The flag '-Djava.security.manager' was passed to the image builder which is not allowed." +
139-
" Native Image does not allow setting the security manager at runtime so this feature must be disabled. In the future release this warning will become an error.");
140-
}
141-
142135
Integer checkDependencies = SubstrateOptions.CheckBootModuleDependencies.getValue(imageClassLoader.classLoaderSupport.getParsedHostedOptions());
143136
if (checkDependencies > 0) {
144137
checkBootModuleDependencies(checkDependencies > 1);

0 commit comments

Comments
 (0)