Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit ef4ba22

Browse files
committed
8268349: Provide clear run-time warnings about Security Manager deprecation
Reviewed-by: lancea, mullan, alanb
1 parent 4099810 commit ef4ba22

File tree

6 files changed

+144
-75
lines changed

6 files changed

+144
-75
lines changed

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

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,16 @@
4444
import java.lang.reflect.Method;
4545
import java.lang.reflect.Modifier;
4646
import java.net.URI;
47+
import java.net.URL;
4748
import java.nio.charset.CharacterCodingException;
48-
import java.security.AccessControlContext;
49-
import java.security.ProtectionDomain;
50-
import java.security.AccessController;
51-
import java.security.PrivilegedAction;
5249
import java.nio.channels.Channel;
5350
import java.nio.channels.spi.SelectorProvider;
5451
import java.nio.charset.Charset;
52+
import java.security.AccessControlContext;
53+
import java.security.AccessController;
54+
import java.security.CodeSource;
55+
import java.security.PrivilegedAction;
56+
import java.security.ProtectionDomain;
5557
import java.util.List;
5658
import java.util.Map;
5759
import java.util.Objects;
@@ -324,6 +326,16 @@ private static void checkIO() {
324326
private static native void setOut0(PrintStream out);
325327
private static native void setErr0(PrintStream err);
326328

329+
// Remember initial System.err. setSecurityManager() warning goes here
330+
private static volatile @Stable PrintStream initialErrStream;
331+
332+
private static URL codeSource(Class<?> clazz) {
333+
PrivilegedAction<ProtectionDomain> pa = clazz::getProtectionDomain;
334+
@SuppressWarnings("removal")
335+
CodeSource cs = AccessController.doPrivileged(pa).getCodeSource();
336+
return (cs != null) ? cs.getLocation() : null;
337+
}
338+
327339
/**
328340
* Sets the system-wide security manager.
329341
*
@@ -362,16 +374,29 @@ private static void checkIO() {
362374
* method.
363375
*/
364376
@Deprecated(since="17", forRemoval=true)
377+
@CallerSensitive
365378
public static void setSecurityManager(@SuppressWarnings("removal") SecurityManager sm) {
366379
if (allowSecurityManager()) {
367-
System.err.println("WARNING: java.lang.System::setSecurityManager" +
368-
" is deprecated and will be removed in a future release.");
380+
var callerClass = Reflection.getCallerClass();
381+
URL url = codeSource(callerClass);
382+
final String source;
383+
if (url == null) {
384+
source = callerClass.getName();
385+
} else {
386+
source = callerClass.getName() + " (" + url + ")";
387+
}
388+
initialErrStream.printf("""
389+
WARNING: A terminally deprecated method in java.lang.System has been called
390+
WARNING: System::setSecurityManager has been called by %s
391+
WARNING: Please consider reporting this to the maintainers of %s
392+
WARNING: System::setSecurityManager will be removed in a future release
393+
""", source, callerClass.getName());
369394
implSetSecurityManager(sm);
370395
} else {
371396
// security manager not allowed
372397
if (sm != null) {
373398
throw new UnsupportedOperationException(
374-
"Runtime configured to disallow security manager");
399+
"The Security Manager is deprecated and will be removed in a future release");
375400
}
376401
}
377402
}
@@ -2191,10 +2216,13 @@ private static void initPhase3() {
21912216
}
21922217

21932218
if (needWarning) {
2194-
System.err.println("WARNING: The Security Manager is deprecated" +
2195-
" and will be removed in a future release.");
2219+
System.err.println("""
2220+
WARNING: A command line option has enabled the Security Manager
2221+
WARNING: The Security Manager is deprecated and will be removed in a future release""");
21962222
}
21972223

2224+
initialErrStream = System.err;
2225+
21982226
// initializing the system class loader
21992227
VM.initLevel(3);
22002228

test/jdk/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.HashMap;
3737
import java.util.Map;
3838
import java.util.ResourceBundle;
39+
import java.util.stream.Collectors;
3940
import java.util.stream.Stream;
4041
import java.util.concurrent.ConcurrentHashMap;
4142
import java.util.concurrent.atomic.AtomicBoolean;
@@ -44,15 +45,11 @@
4445
import java.lang.System.LoggerFinder;
4546
import java.lang.System.Logger;
4647
import java.lang.System.Logger.Level;
47-
import java.security.AccessController;
48-
import java.security.PrivilegedAction;
4948
import java.util.EnumSet;
5049
import java.util.Iterator;
5150
import java.util.Locale;
52-
import java.util.ServiceConfigurationError;
5351
import java.util.ServiceLoader;
5452
import java.util.concurrent.atomic.AtomicReference;
55-
import jdk.internal.logger.SimpleConsoleLogger;
5653

5754
/**
5855
* @test
@@ -202,6 +199,10 @@ static void setSecurityManager() {
202199
}
203200
}
204201

202+
private static String withoutWarning(String in) {
203+
return in.lines().filter(s -> !s.startsWith("WARNING:")).collect(Collectors.joining());
204+
}
205+
205206
static LoggerFinder getLoggerFinder(Class<?> expectedClass,
206207
String errorPolicy, boolean singleton) {
207208
LoggerFinder provider = null;
@@ -235,12 +236,7 @@ static LoggerFinder getLoggerFinder(Class<?> expectedClass,
235236
}
236237
} else if ("QUIET".equals(errorPolicy.toUpperCase(Locale.ROOT))) {
237238
String warning = ErrorStream.errorStream.peek();
238-
String smDeprecationWarning
239-
= "WARNING: java.lang.System::setSecurityManager is deprecated and will be removed in a future release."
240-
+ System.getProperty("line.separator");
241-
if (warning.startsWith(smDeprecationWarning)) {
242-
warning = warning.substring(smDeprecationWarning.length());
243-
}
239+
warning = withoutWarning(warning);
244240
if (!warning.isEmpty()) {
245241
throw new RuntimeException("Unexpected error message found: "
246242
+ ErrorStream.errorStream.peek());

test/jdk/java/lang/System/SecurityManagerWarnings.java

Lines changed: 89 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,70 +23,116 @@
2323

2424
/*
2525
* @test
26-
* @bug 8266459
26+
* @bug 8266459 8268349
2727
* @summary check various warnings
2828
* @library /test/lib
2929
*/
3030

31+
import jdk.test.lib.JDKToolFinder;
3132
import jdk.test.lib.process.OutputAnalyzer;
3233
import jdk.test.lib.process.ProcessTools;
34+
import jdk.test.lib.util.JarUtils;
3335

34-
import java.security.Permission;
36+
import java.io.ByteArrayOutputStream;
37+
import java.io.File;
38+
import java.io.PrintStream;
39+
import java.nio.file.Files;
40+
import java.nio.file.Path;
3541

3642
public class SecurityManagerWarnings {
43+
3744
public static void main(String args[]) throws Exception {
3845
if (args.length == 0) {
39-
run(null)
40-
.shouldHaveExitValue(0)
41-
.shouldContain("SM is enabled: false")
42-
.shouldNotContain("Security Manager is deprecated")
43-
.shouldContain("setSecurityManager is deprecated");
44-
run("allow")
45-
.shouldHaveExitValue(0)
46-
.shouldContain("SM is enabled: false")
47-
.shouldNotContain("Security Manager is deprecated")
48-
.shouldContain("setSecurityManager is deprecated");
49-
run("disallow")
50-
.shouldNotHaveExitValue(0)
51-
.shouldContain("SM is enabled: false")
52-
.shouldNotContain("Security Manager is deprecated")
53-
.shouldContain("UnsupportedOperationException");
54-
run("SecurityManagerWarnings$MySM")
55-
.shouldHaveExitValue(0)
56-
.shouldContain("SM is enabled: true")
57-
.shouldContain("Security Manager is deprecated")
58-
.shouldContain("setSecurityManager is deprecated");
59-
run("")
60-
.shouldNotHaveExitValue(0)
61-
.shouldContain("SM is enabled: true")
62-
.shouldContain("Security Manager is deprecated")
63-
.shouldContain("AccessControlException");
64-
run("default")
65-
.shouldNotHaveExitValue(0)
66-
.shouldContain("SM is enabled: true")
67-
.shouldContain("Security Manager is deprecated")
68-
.shouldContain("AccessControlException");
46+
Files.writeString(Path.of("policy"), """
47+
grant {
48+
permission java.lang.RuntimePermission "setIO";
49+
permission java.lang.RuntimePermission "createSecurityManager";
50+
permission java.lang.RuntimePermission "setSecurityManager";
51+
};
52+
""");
53+
54+
String testClasses = System.getProperty("test.classes");
55+
56+
allowTest(null, testClasses);
57+
allowTest("allow", testClasses);
58+
disallowTest("disallow", testClasses);
59+
enableTest("", testClasses);
60+
enableTest("default", testClasses);
61+
enableTest("java.lang.SecurityManager", testClasses);
62+
63+
JarUtils.createJarFile(Path.of("a.jar"),
64+
Path.of(testClasses),
65+
Path.of("SecurityManagerWarnings.class"));
66+
67+
allowTest(null, "a.jar");
6968
} else {
7069
System.out.println("SM is enabled: " + (System.getSecurityManager() != null));
71-
System.setSecurityManager(new SecurityManager());
70+
PrintStream oldErr = System.err;
71+
// Modify System.err, thus make sure warnings are always printed
72+
// to the original System.err and will not be swallowed.
73+
System.setErr(new PrintStream(new ByteArrayOutputStream()));
74+
try {
75+
System.setSecurityManager(new SecurityManager());
76+
} catch (Exception e) {
77+
// Exception messages must show in original stderr
78+
e.printStackTrace(oldErr);
79+
throw e;
80+
}
7281
}
7382
}
7483

75-
static OutputAnalyzer run(String prop) throws Exception {
84+
// When SM is allowed, no startup warning, has setSM warning
85+
static void allowTest(String prop, String cp) throws Exception {
86+
checkInstallMessage(run(prop, cp), cp)
87+
.shouldHaveExitValue(0)
88+
.stdoutShouldContain("SM is enabled: false")
89+
.shouldNotContain("A command line option");
90+
}
91+
92+
// When SM is disallowed, no startup warning, setSM fails
93+
static void disallowTest(String prop, String cp) throws Exception {
94+
run(prop, cp)
95+
.shouldNotHaveExitValue(0)
96+
.stdoutShouldContain("SM is enabled: false")
97+
.shouldNotContain("A command line option")
98+
.shouldNotContain("A terminally deprecated method")
99+
.stderrShouldContain("UnsupportedOperationException: The Security Manager is deprecated and will be removed in a future release");
100+
}
101+
102+
// When SM is allowed, has startup warning, has setSM warning
103+
static void enableTest(String prop, String cp) throws Exception {
104+
checkInstallMessage(run(prop, cp), cp)
105+
.shouldHaveExitValue(0)
106+
.stdoutShouldContain("SM is enabled: true")
107+
.stderrShouldContain("WARNING: A command line option has enabled the Security Manager")
108+
.stderrShouldContain("WARNING: The Security Manager is deprecated and will be removed in a future release");
109+
}
110+
111+
// Check the setSM warning
112+
static OutputAnalyzer checkInstallMessage(OutputAnalyzer oa, String cp) {
113+
String uri = new File(cp).toURI().toString();
114+
return oa
115+
.stderrShouldContain("WARNING: A terminally deprecated method in java.lang.System has been called")
116+
.stderrShouldContain("WARNING: System::setSecurityManager has been called by SecurityManagerWarnings (" + uri + ")")
117+
.stderrShouldContain("WARNING: Please consider reporting this to the maintainers of SecurityManagerWarnings")
118+
.stderrShouldContain("WARNING: System::setSecurityManager will be removed in a future release");
119+
}
120+
121+
static OutputAnalyzer run(String prop, String cp) throws Exception {
122+
ProcessBuilder pb;
76123
if (prop == null) {
77-
return ProcessTools.executeTestJvm(
124+
pb = new ProcessBuilder(
125+
JDKToolFinder.getJDKTool("java"),
126+
"-cp", cp,
78127
"SecurityManagerWarnings", "run");
79128
} else {
80-
return ProcessTools.executeTestJvm(
129+
pb = new ProcessBuilder(
130+
JDKToolFinder.getJDKTool("java"),
131+
"-cp", cp,
81132
"-Djava.security.manager=" + prop,
133+
"-Djava.security.policy=policy",
82134
"SecurityManagerWarnings", "run");
83135
}
84-
}
85-
86-
// This SecurityManager allows everything!
87-
public static class MySM extends SecurityManager {
88-
@Override
89-
public void checkPermission(Permission perm) {
90-
}
136+
return ProcessTools.executeProcess(pb);
91137
}
92138
}

test/jdk/java/lang/invoke/lambda/LogGeneratedClassesTest.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,8 @@ public void testDumpDirNotExist() throws IOException {
147147
"-Djdk.internal.lambda.dumpProxyClasses=notExist",
148148
"com.example.TestLambda");
149149
assertEquals(tr.testOutput.stream()
150-
.filter(s -> !s.contains("setSecurityManager is deprecated"))
151150
.filter(s -> s.startsWith("WARNING"))
152-
.peek(s -> assertTrue(s.contains("does not exist")))
151+
.filter(s -> s.contains("does not exist"))
153152
.count(),
154153
1, "only show error once");
155154
tr.assertZero("Should still return 0");
@@ -164,9 +163,8 @@ public void testDumpDirIsFile() throws IOException {
164163
"-Djdk.internal.lambda.dumpProxyClasses=file",
165164
"com.example.TestLambda");
166165
assertEquals(tr.testOutput.stream()
167-
.filter(s -> !s.contains("setSecurityManager is deprecated"))
168166
.filter(s -> s.startsWith("WARNING"))
169-
.peek(s -> assertTrue(s.contains("not a directory")))
167+
.filter(s -> s.contains("not a directory"))
170168
.count(),
171169
1, "only show error once");
172170
tr.assertZero("Should still return 0");
@@ -224,9 +222,8 @@ public void testDumpDirNotWritable() throws IOException {
224222
"-Djdk.internal.lambda.dumpProxyClasses=readOnly",
225223
"com.example.TestLambda");
226224
assertEquals(tr.testOutput.stream()
227-
.filter(s -> !s.contains("setSecurityManager is deprecated"))
228225
.filter(s -> s.startsWith("WARNING"))
229-
.peek(s -> assertTrue(s.contains("not writable")))
226+
.filter(s -> s.contains("not writable"))
230227
.count(),
231228
1, "only show error once");
232229
tr.assertZero("Should still return 0");

test/jdk/java/net/spi/URLStreamHandlerProvider/Basic.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,14 @@ public static void main(String[] args) throws Throwable {
8686
static final String SECURITY_MANAGER_DEPRECATED
8787
= "WARNING: The Security Manager is deprecated and will be removed in a future release."
8888
+ System.getProperty("line.separator");
89+
90+
private static String withoutWarning(String in) {
91+
return in.lines().filter(s -> !s.startsWith("WARNING:")).collect(Collectors.joining());
92+
}
93+
8994
static final Consumer<Result> KNOWN = r -> {
90-
if (r.exitValue != 0 ||
91-
(!r.output.isEmpty() && !r.output.equals(SECURITY_MANAGER_DEPRECATED)))
92-
throw new RuntimeException(r.output);
95+
if (r.exitValue != 0 || !withoutWarning(r.output).isEmpty())
96+
throw new RuntimeException("[" + r.output + "]");
9397
};
9498
static final Consumer<Result> UNKNOWN = r -> {
9599
if (r.exitValue == 0 ||

test/jdk/java/security/ProtectionDomain/RecursionDebug.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 4947618
26+
* @bug 4947618 8268349
2727
* @summary Recursion problem in security manager and policy code
2828
*
2929
* @run main/othervm/policy=Recursion.policy -Djava.security.debug=domain RecursionDebug
@@ -87,7 +87,5 @@ public static void main(String[] args) throws Exception {
8787
throw new Exception
8888
("Test with custom non-bootclass SecurityManager failed");
8989
}
90-
91-
System.setSecurityManager(null);
9290
}
9391
}

0 commit comments

Comments
 (0)