8268349: Provide clear run-time warnings about Security Manager deprecation
Reviewed-by: lancea, mullan, alanb
This commit is contained in:
parent
4099810b29
commit
ef4ba224c4
src/java.base/share/classes/java/lang
test/jdk/java
lang
System
invoke/lambda
net/spi/URLStreamHandlerProvider
security/ProtectionDomain
@ -44,14 +44,16 @@ import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.nio.channels.Channel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -324,6 +326,16 @@ public final class System {
|
||||
private static native void setOut0(PrintStream out);
|
||||
private static native void setErr0(PrintStream err);
|
||||
|
||||
// Remember initial System.err. setSecurityManager() warning goes here
|
||||
private static volatile @Stable PrintStream initialErrStream;
|
||||
|
||||
private static URL codeSource(Class<?> clazz) {
|
||||
PrivilegedAction<ProtectionDomain> pa = clazz::getProtectionDomain;
|
||||
@SuppressWarnings("removal")
|
||||
CodeSource cs = AccessController.doPrivileged(pa).getCodeSource();
|
||||
return (cs != null) ? cs.getLocation() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system-wide security manager.
|
||||
*
|
||||
@ -362,16 +374,29 @@ public final class System {
|
||||
* method.
|
||||
*/
|
||||
@Deprecated(since="17", forRemoval=true)
|
||||
@CallerSensitive
|
||||
public static void setSecurityManager(@SuppressWarnings("removal") SecurityManager sm) {
|
||||
if (allowSecurityManager()) {
|
||||
System.err.println("WARNING: java.lang.System::setSecurityManager" +
|
||||
" is deprecated and will be removed in a future release.");
|
||||
var callerClass = Reflection.getCallerClass();
|
||||
URL url = codeSource(callerClass);
|
||||
final String source;
|
||||
if (url == null) {
|
||||
source = callerClass.getName();
|
||||
} else {
|
||||
source = callerClass.getName() + " (" + url + ")";
|
||||
}
|
||||
initialErrStream.printf("""
|
||||
WARNING: A terminally deprecated method in java.lang.System has been called
|
||||
WARNING: System::setSecurityManager has been called by %s
|
||||
WARNING: Please consider reporting this to the maintainers of %s
|
||||
WARNING: System::setSecurityManager will be removed in a future release
|
||||
""", source, callerClass.getName());
|
||||
implSetSecurityManager(sm);
|
||||
} else {
|
||||
// security manager not allowed
|
||||
if (sm != null) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Runtime configured to disallow security manager");
|
||||
"The Security Manager is deprecated and will be removed in a future release");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2191,10 +2216,13 @@ public final class System {
|
||||
}
|
||||
|
||||
if (needWarning) {
|
||||
System.err.println("WARNING: The Security Manager is deprecated" +
|
||||
" and will be removed in a future release.");
|
||||
System.err.println("""
|
||||
WARNING: A command line option has enabled the Security Manager
|
||||
WARNING: The Security Manager is deprecated and will be removed in a future release""");
|
||||
}
|
||||
|
||||
initialErrStream = System.err;
|
||||
|
||||
// initializing the system class loader
|
||||
VM.initLevel(3);
|
||||
|
||||
|
16
test/jdk/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java
16
test/jdk/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java
@ -36,6 +36,7 @@ import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -44,15 +45,11 @@ import java.util.function.Supplier;
|
||||
import java.lang.System.LoggerFinder;
|
||||
import java.lang.System.Logger;
|
||||
import java.lang.System.Logger.Level;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import jdk.internal.logger.SimpleConsoleLogger;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -202,6 +199,10 @@ public class LoggerFinderLoaderTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static String withoutWarning(String in) {
|
||||
return in.lines().filter(s -> !s.startsWith("WARNING:")).collect(Collectors.joining());
|
||||
}
|
||||
|
||||
static LoggerFinder getLoggerFinder(Class<?> expectedClass,
|
||||
String errorPolicy, boolean singleton) {
|
||||
LoggerFinder provider = null;
|
||||
@ -235,12 +236,7 @@ public class LoggerFinderLoaderTest {
|
||||
}
|
||||
} else if ("QUIET".equals(errorPolicy.toUpperCase(Locale.ROOT))) {
|
||||
String warning = ErrorStream.errorStream.peek();
|
||||
String smDeprecationWarning
|
||||
= "WARNING: java.lang.System::setSecurityManager is deprecated and will be removed in a future release."
|
||||
+ System.getProperty("line.separator");
|
||||
if (warning.startsWith(smDeprecationWarning)) {
|
||||
warning = warning.substring(smDeprecationWarning.length());
|
||||
}
|
||||
warning = withoutWarning(warning);
|
||||
if (!warning.isEmpty()) {
|
||||
throw new RuntimeException("Unexpected error message found: "
|
||||
+ ErrorStream.errorStream.peek());
|
||||
|
@ -23,70 +23,116 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8266459
|
||||
* @bug 8266459 8268349
|
||||
* @summary check various warnings
|
||||
* @library /test/lib
|
||||
*/
|
||||
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
|
||||
import java.security.Permission;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class SecurityManagerWarnings {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
if (args.length == 0) {
|
||||
run(null)
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("SM is enabled: false")
|
||||
.shouldNotContain("Security Manager is deprecated")
|
||||
.shouldContain("setSecurityManager is deprecated");
|
||||
run("allow")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("SM is enabled: false")
|
||||
.shouldNotContain("Security Manager is deprecated")
|
||||
.shouldContain("setSecurityManager is deprecated");
|
||||
run("disallow")
|
||||
.shouldNotHaveExitValue(0)
|
||||
.shouldContain("SM is enabled: false")
|
||||
.shouldNotContain("Security Manager is deprecated")
|
||||
.shouldContain("UnsupportedOperationException");
|
||||
run("SecurityManagerWarnings$MySM")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("SM is enabled: true")
|
||||
.shouldContain("Security Manager is deprecated")
|
||||
.shouldContain("setSecurityManager is deprecated");
|
||||
run("")
|
||||
.shouldNotHaveExitValue(0)
|
||||
.shouldContain("SM is enabled: true")
|
||||
.shouldContain("Security Manager is deprecated")
|
||||
.shouldContain("AccessControlException");
|
||||
run("default")
|
||||
.shouldNotHaveExitValue(0)
|
||||
.shouldContain("SM is enabled: true")
|
||||
.shouldContain("Security Manager is deprecated")
|
||||
.shouldContain("AccessControlException");
|
||||
Files.writeString(Path.of("policy"), """
|
||||
grant {
|
||||
permission java.lang.RuntimePermission "setIO";
|
||||
permission java.lang.RuntimePermission "createSecurityManager";
|
||||
permission java.lang.RuntimePermission "setSecurityManager";
|
||||
};
|
||||
""");
|
||||
|
||||
String testClasses = System.getProperty("test.classes");
|
||||
|
||||
allowTest(null, testClasses);
|
||||
allowTest("allow", testClasses);
|
||||
disallowTest("disallow", testClasses);
|
||||
enableTest("", testClasses);
|
||||
enableTest("default", testClasses);
|
||||
enableTest("java.lang.SecurityManager", testClasses);
|
||||
|
||||
JarUtils.createJarFile(Path.of("a.jar"),
|
||||
Path.of(testClasses),
|
||||
Path.of("SecurityManagerWarnings.class"));
|
||||
|
||||
allowTest(null, "a.jar");
|
||||
} else {
|
||||
System.out.println("SM is enabled: " + (System.getSecurityManager() != null));
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
PrintStream oldErr = System.err;
|
||||
// Modify System.err, thus make sure warnings are always printed
|
||||
// to the original System.err and will not be swallowed.
|
||||
System.setErr(new PrintStream(new ByteArrayOutputStream()));
|
||||
try {
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
} catch (Exception e) {
|
||||
// Exception messages must show in original stderr
|
||||
e.printStackTrace(oldErr);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static OutputAnalyzer run(String prop) throws Exception {
|
||||
// When SM is allowed, no startup warning, has setSM warning
|
||||
static void allowTest(String prop, String cp) throws Exception {
|
||||
checkInstallMessage(run(prop, cp), cp)
|
||||
.shouldHaveExitValue(0)
|
||||
.stdoutShouldContain("SM is enabled: false")
|
||||
.shouldNotContain("A command line option");
|
||||
}
|
||||
|
||||
// When SM is disallowed, no startup warning, setSM fails
|
||||
static void disallowTest(String prop, String cp) throws Exception {
|
||||
run(prop, cp)
|
||||
.shouldNotHaveExitValue(0)
|
||||
.stdoutShouldContain("SM is enabled: false")
|
||||
.shouldNotContain("A command line option")
|
||||
.shouldNotContain("A terminally deprecated method")
|
||||
.stderrShouldContain("UnsupportedOperationException: The Security Manager is deprecated and will be removed in a future release");
|
||||
}
|
||||
|
||||
// When SM is allowed, has startup warning, has setSM warning
|
||||
static void enableTest(String prop, String cp) throws Exception {
|
||||
checkInstallMessage(run(prop, cp), cp)
|
||||
.shouldHaveExitValue(0)
|
||||
.stdoutShouldContain("SM is enabled: true")
|
||||
.stderrShouldContain("WARNING: A command line option has enabled the Security Manager")
|
||||
.stderrShouldContain("WARNING: The Security Manager is deprecated and will be removed in a future release");
|
||||
}
|
||||
|
||||
// Check the setSM warning
|
||||
static OutputAnalyzer checkInstallMessage(OutputAnalyzer oa, String cp) {
|
||||
String uri = new File(cp).toURI().toString();
|
||||
return oa
|
||||
.stderrShouldContain("WARNING: A terminally deprecated method in java.lang.System has been called")
|
||||
.stderrShouldContain("WARNING: System::setSecurityManager has been called by SecurityManagerWarnings (" + uri + ")")
|
||||
.stderrShouldContain("WARNING: Please consider reporting this to the maintainers of SecurityManagerWarnings")
|
||||
.stderrShouldContain("WARNING: System::setSecurityManager will be removed in a future release");
|
||||
}
|
||||
|
||||
static OutputAnalyzer run(String prop, String cp) throws Exception {
|
||||
ProcessBuilder pb;
|
||||
if (prop == null) {
|
||||
return ProcessTools.executeTestJvm(
|
||||
pb = new ProcessBuilder(
|
||||
JDKToolFinder.getJDKTool("java"),
|
||||
"-cp", cp,
|
||||
"SecurityManagerWarnings", "run");
|
||||
} else {
|
||||
return ProcessTools.executeTestJvm(
|
||||
pb = new ProcessBuilder(
|
||||
JDKToolFinder.getJDKTool("java"),
|
||||
"-cp", cp,
|
||||
"-Djava.security.manager=" + prop,
|
||||
"-Djava.security.policy=policy",
|
||||
"SecurityManagerWarnings", "run");
|
||||
}
|
||||
}
|
||||
|
||||
// This SecurityManager allows everything!
|
||||
public static class MySM extends SecurityManager {
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
}
|
||||
return ProcessTools.executeProcess(pb);
|
||||
}
|
||||
}
|
||||
|
@ -147,9 +147,8 @@ public class LogGeneratedClassesTest extends LUtils {
|
||||
"-Djdk.internal.lambda.dumpProxyClasses=notExist",
|
||||
"com.example.TestLambda");
|
||||
assertEquals(tr.testOutput.stream()
|
||||
.filter(s -> !s.contains("setSecurityManager is deprecated"))
|
||||
.filter(s -> s.startsWith("WARNING"))
|
||||
.peek(s -> assertTrue(s.contains("does not exist")))
|
||||
.filter(s -> s.contains("does not exist"))
|
||||
.count(),
|
||||
1, "only show error once");
|
||||
tr.assertZero("Should still return 0");
|
||||
@ -164,9 +163,8 @@ public class LogGeneratedClassesTest extends LUtils {
|
||||
"-Djdk.internal.lambda.dumpProxyClasses=file",
|
||||
"com.example.TestLambda");
|
||||
assertEquals(tr.testOutput.stream()
|
||||
.filter(s -> !s.contains("setSecurityManager is deprecated"))
|
||||
.filter(s -> s.startsWith("WARNING"))
|
||||
.peek(s -> assertTrue(s.contains("not a directory")))
|
||||
.filter(s -> s.contains("not a directory"))
|
||||
.count(),
|
||||
1, "only show error once");
|
||||
tr.assertZero("Should still return 0");
|
||||
@ -224,9 +222,8 @@ public class LogGeneratedClassesTest extends LUtils {
|
||||
"-Djdk.internal.lambda.dumpProxyClasses=readOnly",
|
||||
"com.example.TestLambda");
|
||||
assertEquals(tr.testOutput.stream()
|
||||
.filter(s -> !s.contains("setSecurityManager is deprecated"))
|
||||
.filter(s -> s.startsWith("WARNING"))
|
||||
.peek(s -> assertTrue(s.contains("not writable")))
|
||||
.filter(s -> s.contains("not writable"))
|
||||
.count(),
|
||||
1, "only show error once");
|
||||
tr.assertZero("Should still return 0");
|
||||
|
@ -86,10 +86,14 @@ public class Basic {
|
||||
static final String SECURITY_MANAGER_DEPRECATED
|
||||
= "WARNING: The Security Manager is deprecated and will be removed in a future release."
|
||||
+ System.getProperty("line.separator");
|
||||
|
||||
private static String withoutWarning(String in) {
|
||||
return in.lines().filter(s -> !s.startsWith("WARNING:")).collect(Collectors.joining());
|
||||
}
|
||||
|
||||
static final Consumer<Result> KNOWN = r -> {
|
||||
if (r.exitValue != 0 ||
|
||||
(!r.output.isEmpty() && !r.output.equals(SECURITY_MANAGER_DEPRECATED)))
|
||||
throw new RuntimeException(r.output);
|
||||
if (r.exitValue != 0 || !withoutWarning(r.output).isEmpty())
|
||||
throw new RuntimeException("[" + r.output + "]");
|
||||
};
|
||||
static final Consumer<Result> UNKNOWN = r -> {
|
||||
if (r.exitValue == 0 ||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4947618
|
||||
* @bug 4947618 8268349
|
||||
* @summary Recursion problem in security manager and policy code
|
||||
*
|
||||
* @run main/othervm/policy=Recursion.policy -Djava.security.debug=domain RecursionDebug
|
||||
@ -87,7 +87,5 @@ public class RecursionDebug {
|
||||
throw new Exception
|
||||
("Test with custom non-bootclass SecurityManager failed");
|
||||
}
|
||||
|
||||
System.setSecurityManager(null);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user