8352728: InternalError loading java.security due to Windows parent folder permissions

Reviewed-by: weijun, mullan
This commit is contained in:
Francisco Ferrari Bihurriet 2026-01-08 16:46:48 +00:00
parent c834e4c641
commit 7e1051bfcc
6 changed files with 273 additions and 128 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2026, 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
@ -34,6 +34,7 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
@ -112,7 +113,7 @@ public final class Security {
private static Path currentPath;
private static final Set<Path> activePaths = new HashSet<>();
private static final List<Path> activePaths = new ArrayList<>();
static void loadAll() {
// first load the master properties file to
@ -262,30 +263,40 @@ public final class Security {
}
}
private static void checkCyclicInclude(Path path) {
for (Path activePath : activePaths) {
try {
if (Files.isSameFile(path, activePath)) {
throw new InternalError(
"Cyclic include of '" + path + "'");
}
} catch (IOException e) {
if (sdebug != null) {
sdebug.println("skipped exception when checking for " +
"cyclic inclusion of " + path + ":");
e.printStackTrace();
}
}
}
}
private static void loadFromPath(Path path, LoadingMode mode)
throws IOException {
boolean isRegularFile = Files.isRegularFile(path);
if (isRegularFile) {
path = path.toRealPath();
} else if (Files.isDirectory(path)) {
if (Files.isDirectory(path)) {
throw new IOException("Is a directory");
} else {
path = path.toAbsolutePath();
}
if (activePaths.contains(path)) {
throw new InternalError("Cyclic include of '" + path + "'");
}
try (InputStream is = Files.newInputStream(path)) {
checkCyclicInclude(path);
reset(mode);
Path previousPath = currentPath;
currentPath = isRegularFile ? path : null;
currentPath = Files.isRegularFile(path) ? path : null;
activePaths.add(path);
try {
debugLoad(true, path);
props.load(is);
debugLoad(false, path);
} finally {
activePaths.remove(path);
activePaths.removeLast();
currentPath = previousPath;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2026, 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
@ -62,13 +62,13 @@ import java.util.stream.Stream;
* @test
* @summary Tests security properties passed through java.security,
* java.security.properties or included from other properties files.
* @bug 8155246 8292297 8292177 8281658 8319332
* @bug 4303068 8155246 8292297 8292177 8281658 8319332
* @modules java.base/sun.net.www
* @library /test/lib
* @run main ConfigFileTest
* @run main ExtraFileAndIncludes
*/
public class ConfigFileTest {
public class ExtraFileAndIncludes {
static final String SEPARATOR_THIN = "----------------------------";
private static void printTestHeader(String testName) {
@ -91,7 +91,8 @@ public class ConfigFileTest {
} else {
// Executed by the test JVM.
try (FilesManager filesMgr = new FilesManager()) {
for (Method m : ConfigFileTest.class.getDeclaredMethods()) {
for (Method m :
ExtraFileAndIncludes.class.getDeclaredMethods()) {
if (m.getName().startsWith("test")) {
printTestHeader(m.getName());
Executor.run(m, filesMgr);
@ -120,7 +121,7 @@ public class ConfigFileTest {
static void testIncludeBasic(Executor ex, FilesManager filesMgr)
throws Exception {
PropsFile masterFile = filesMgr.newMasterFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.FILE_URI);
PropsFile file0 = filesMgr.newFile("file0.properties");
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
PropsFile file2 = filesMgr.newFile("dir1/dir2/file2.properties");
@ -130,7 +131,7 @@ public class ConfigFileTest {
file2.addAbsoluteInclude(file1);
ex.setMasterFile(masterFile);
ex.setExtraFile(extraFile, Executor.ExtraMode.FILE_URI, false);
ex.setExtraFile(extraFile, false);
ex.assertSuccess();
}
@ -152,7 +153,7 @@ public class ConfigFileTest {
static void testIncludeWithOverrideAll(Executor ex, FilesManager filesMgr)
throws Exception {
PropsFile masterFile = filesMgr.newMasterFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
PropsFile file0 = filesMgr.newFile("file0.properties");
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
@ -160,40 +161,40 @@ public class ConfigFileTest {
extraFile.addAbsoluteInclude(file1);
ex.setMasterFile(masterFile);
ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
ex.setExtraFile(extraFile, true);
ex.assertSuccess();
}
static void extraPropertiesByHelper(Executor ex, FilesManager filesMgr,
Executor.ExtraMode mode) throws Exception {
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraMode mode) throws Exception {
ExtraPropsFile extraFile = filesMgr.newExtraFile(mode);
PropsFile file0 = filesMgr.newFile("file0.properties");
extraFile.addRelativeInclude(file0);
ex.setMasterFile(filesMgr.newMasterFile());
ex.setExtraFile(extraFile, mode, true);
ex.setExtraFile(extraFile, true);
ex.assertSuccess();
}
static void testExtraPropertiesByPathAbsolute(Executor ex,
FilesManager filesMgr) throws Exception {
extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_ABS);
extraPropertiesByHelper(ex, filesMgr, ExtraMode.PATH_ABS);
}
static void testExtraPropertiesByPathRelative(Executor ex,
FilesManager filesMgr) throws Exception {
extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_REL);
extraPropertiesByHelper(ex, filesMgr, ExtraMode.PATH_REL);
}
static void specialCharsIncludes(Executor ex, FilesManager filesMgr,
char specialChar, Executor.ExtraMode extraMode,
boolean useRelativeIncludes) throws Exception {
char specialChar, ExtraMode extraMode, boolean useRelativeIncludes)
throws Exception {
String suffix = specialChar + ".properties";
ExtraPropsFile extraFile;
PropsFile file0, file1;
try {
extraFile = filesMgr.newExtraFile("extra" + suffix);
extraFile = filesMgr.newExtraFile("extra" + suffix, extraMode);
file0 = filesMgr.newFile("file0" + suffix);
file1 = filesMgr.newFile("file1" + suffix);
} catch (InvalidPathException ipe) {
@ -210,20 +211,18 @@ public class ConfigFileTest {
extraFile.addAbsoluteInclude(file1);
ex.setMasterFile(filesMgr.newMasterFile());
ex.setExtraFile(extraFile, extraMode, false);
ex.setExtraFile(extraFile, false);
ex.assertSuccess();
}
static void testUnicodeIncludes1(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.PATH_ABS, true);
specialCharsIncludes(ex, filesMgr, '\u2022', ExtraMode.PATH_ABS, true);
}
static void testUnicodeIncludes2(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.FILE_URI, true);
specialCharsIncludes(ex, filesMgr, '\u2022', ExtraMode.FILE_URI, true);
}
static void testUnicodeIncludes3(Executor ex, FilesManager filesMgr)
@ -232,7 +231,7 @@ public class ConfigFileTest {
// file:/tmp/extra.properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.RAW_FILE_URI1, false);
ExtraMode.RAW_FILE_URI1, false);
}
static void testUnicodeIncludes4(Executor ex, FilesManager filesMgr)
@ -241,19 +240,17 @@ public class ConfigFileTest {
// file:///tmp/extra.properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.RAW_FILE_URI2, false);
ExtraMode.RAW_FILE_URI2, false);
}
static void testSpaceIncludes1(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.PATH_ABS, true);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.PATH_ABS, true);
}
static void testSpaceIncludes2(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.FILE_URI, true);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.FILE_URI, true);
}
static void testSpaceIncludes3(Executor ex, FilesManager filesMgr)
@ -261,8 +258,7 @@ public class ConfigFileTest {
// Backward compatibility check. Malformed URLs such as
// file:/tmp/extra .properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.RAW_FILE_URI1, false);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.RAW_FILE_URI1, false);
}
static void testSpaceIncludes4(Executor ex, FilesManager filesMgr)
@ -270,8 +266,7 @@ public class ConfigFileTest {
// Backward compatibility check. Malformed URLs such as
// file:///tmp/extra .properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.RAW_FILE_URI2, false);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.RAW_FILE_URI2, false);
}
static void notOverrideOnFailureHelper(Executor ex, FilesManager filesMgr,
@ -370,13 +365,13 @@ public class ConfigFileTest {
static void testCannotResolveRelativeFromHTTPServed(Executor ex,
FilesManager filesMgr) throws Exception {
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
PropsFile file0 = filesMgr.newFile("file0.properties");
extraFile.addRelativeInclude(file0);
ex.setMasterFile(filesMgr.newMasterFile());
ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
ex.setExtraFile(extraFile, true);
ex.assertError("InternalError: Cannot resolve '" + file0.fileName +
"' relative path when included from a non-regular " +
"properties file (e.g. HTTP served file)");
@ -394,14 +389,15 @@ public class ConfigFileTest {
masterFile.addRelativeInclude(file0);
ex.setMasterFile(masterFile);
ex.assertError(
"InternalError: Cyclic include of '" + masterFile.path + "'");
ex.assertError("Cyclic include");
ex.getOutputAnalyzer().stderrShouldMatch("\\QInternalError: Cyclic " +
"include of '\\E[^']+\\Q" + masterFile.fileName + "'\\E");
}
static void testCannotIncludeURL(Executor ex, FilesManager filesMgr)
throws Exception {
PropsFile masterFile = filesMgr.newMasterFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
masterFile.addRawProperty("include", extraFile.url.toString());
@ -432,8 +428,7 @@ public class ConfigFileTest {
// Launch a JDK without a master java.security file present, but with an
// extra file passed. Since the "security.overridePropertiesFile=true"
// security property is missing, it should fail anyway.
ex.setExtraFile(
filesMgr.newExtraFile(), Executor.ExtraMode.FILE_URI, true);
ex.setExtraFile(filesMgr.newExtraFile(ExtraMode.FILE_URI), true);
ex.assertError("InternalError: Error loading java.security file");
}
}
@ -455,17 +450,24 @@ sealed class PropsFile permits ExtraPropsFile {
static Include of(PropsFile propsFile, String value) {
return new Include(propsFile, value);
}
void assertProcessed(OutputAnalyzer oa) {
oa.shouldContain("processing include: '" + value + "'");
oa.shouldContain("finished processing " + propsFile.displayPath);
}
}
protected final List<Include> includes = new ArrayList<>();
protected final PrintWriter writer;
protected boolean includedFromExtra = false;
protected Path displayPath;
final String fileName;
final Path path;
PropsFile(String fileName, Path path) throws IOException {
this.fileName = fileName;
this.path = path;
this.displayPath = path;
this.writer = new PrintWriter(Files.newOutputStream(path,
StandardOpenOption.CREATE, StandardOpenOption.APPEND), true);
}
@ -513,8 +515,9 @@ sealed class PropsFile permits ExtraPropsFile {
}
void addRelativeInclude(PropsFile propsFile) {
addIncludeDefinition(Include.of(propsFile,
path.getParent().relativize(propsFile.path).toString()));
Path rel = path.getParent().relativize(propsFile.path);
addIncludeDefinition(Include.of(propsFile, rel.toString()));
propsFile.displayPath = displayPath.getParent().resolve(rel);
}
void assertApplied(OutputAnalyzer oa) {
@ -522,8 +525,7 @@ sealed class PropsFile permits ExtraPropsFile {
FilesManager.APPLIED_PROP_VALUE);
for (Include include : includes) {
include.propsFile.assertApplied(oa);
oa.shouldContain("processing include: '" + include.value + "'");
oa.shouldContain("finished processing " + include.propsFile.path);
include.assertProcessed(oa);
}
}
@ -534,8 +536,7 @@ sealed class PropsFile permits ExtraPropsFile {
if (!include.propsFile.includedFromExtra) {
include.propsFile.assertWasOverwritten(oa);
}
oa.shouldContain("processing include: '" + include.value + "'");
oa.shouldContain("finished processing " + include.propsFile.path);
include.assertProcessed(oa);
}
}
@ -556,13 +557,24 @@ sealed class PropsFile permits ExtraPropsFile {
}
}
enum ExtraMode {
HTTP_SERVED, FILE_URI, RAW_FILE_URI1, RAW_FILE_URI2, PATH_ABS, PATH_REL
}
final class ExtraPropsFile extends PropsFile {
private static final Path CWD = Path.of(".").toAbsolutePath();
private final Map<String, String> systemProps = new LinkedHashMap<>();
private final ExtraMode mode;
final URI url;
ExtraPropsFile(String fileName, URI url, Path path) throws IOException {
ExtraPropsFile(String fileName, URI url, Path path, ExtraMode mode)
throws IOException {
super(fileName, path);
this.url = url;
this.mode = mode;
if (mode == ExtraMode.PATH_REL) {
this.displayPath = CWD.relativize(path);
}
}
@Override
@ -578,14 +590,25 @@ final class ExtraPropsFile extends PropsFile {
super.addIncludeDefinition(include);
}
String getSysPropValue() {
return switch (mode) {
case HTTP_SERVED -> url.toString();
case FILE_URI -> path.toUri().toString();
case RAW_FILE_URI1 -> "file:" + path;
case RAW_FILE_URI2 ->
"file://" + (path.startsWith("/") ? "" : "/") + path;
case PATH_ABS, PATH_REL -> displayPath.toString();
};
}
Map<String, String> getSystemProperties() {
return Collections.unmodifiableMap(systemProps);
}
}
final class FilesManager implements Closeable {
private static final Path ROOT_DIR =
Path.of(ConfigFileTest.class.getSimpleName()).toAbsolutePath();
private static final Path ROOT_DIR = Path.of(
ExtraFileAndIncludes.class.getSimpleName()).toAbsolutePath();
private static final Path PROPS_DIR = ROOT_DIR.resolve("properties");
private static final Path JDK_DIR = ROOT_DIR.resolve("jdk");
private static final Path MASTER_FILE =
@ -684,11 +707,11 @@ final class FilesManager implements Closeable {
propsFile.addComment("Property to determine if this properties file " +
"was parsed and not overwritten:");
propsFile.addRawProperty(fileName, APPLIED_PROP_VALUE);
propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
propsFile.addComment(ExtraFileAndIncludes.SEPARATOR_THIN);
propsFile.addComment("Property to be overwritten by every properties " +
"file (master, extra or included):");
propsFile.addRawProperty(LAST_FILE_PROP_NAME, fileName);
propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
propsFile.addComment(ExtraFileAndIncludes.SEPARATOR_THIN);
createdFiles.add(propsFile);
return propsFile;
}
@ -702,16 +725,17 @@ final class FilesManager implements Closeable {
return newFile(MASTER_FILE, PropsFile::new);
}
ExtraPropsFile newExtraFile() throws IOException {
return newExtraFile("extra.properties");
ExtraPropsFile newExtraFile(ExtraMode mode) throws IOException {
return newExtraFile("extra.properties", mode);
}
ExtraPropsFile newExtraFile(String extraFileName) throws IOException {
ExtraPropsFile newExtraFile(String extraFileName, ExtraMode mode)
throws IOException {
return (ExtraPropsFile) newFile(PROPS_DIR.resolve(extraFileName),
(fileName, path) -> {
URI uri = serverUri.resolve(ParseUtil.encodePath(
ROOT_DIR.relativize(path).toString()));
return new ExtraPropsFile(fileName, uri, path);
return new ExtraPropsFile(fileName, uri, path, mode);
});
}
@ -719,7 +743,7 @@ final class FilesManager implements Closeable {
for (PropsFile propsFile : createdFiles) {
System.err.println();
System.err.println(propsFile.path.toString());
System.err.println(ConfigFileTest.SEPARATOR_THIN.repeat(3));
System.err.println(ExtraFileAndIncludes.SEPARATOR_THIN.repeat(3));
try (Stream<String> lines = Files.lines(propsFile.path)) {
long lineNumber = 1L;
Iterator<String> it = lines.iterator();
@ -757,9 +781,6 @@ final class FilesManager implements Closeable {
}
final class Executor {
enum ExtraMode {
HTTP_SERVED, FILE_URI, RAW_FILE_URI1, RAW_FILE_URI2, PATH_ABS, PATH_REL
}
static final String RUNNER_ARG = "runner";
static final String INITIAL_PROP_LOG_MSG = "Initial security property: ";
private static final String OVERRIDING_LOG_MSG =
@ -769,7 +790,6 @@ final class Executor {
INITIAL_PROP_LOG_MSG + "postInitTest=shouldNotRecord",
INITIAL_PROP_LOG_MSG + "include=",
};
private static final Path CWD = Path.of(".").toAbsolutePath();
private static final String JAVA_SEC_PROPS = "java.security.properties";
private static final String CLASS_PATH = Objects.requireNonNull(
System.getProperty("test.classes"), "unspecified test.classes");
@ -812,20 +832,10 @@ final class Executor {
this.masterPropsFile = masterPropsFile;
}
void setExtraFile(ExtraPropsFile extraPropsFile, ExtraMode mode,
boolean overrideAll) {
void setExtraFile(ExtraPropsFile extraPropsFile, boolean overrideAll) {
this.extraPropsFile = extraPropsFile;
expectedOverrideAll = overrideAll;
setRawExtraFile(switch (mode) {
case HTTP_SERVED -> extraPropsFile.url.toString();
case FILE_URI -> extraPropsFile.path.toUri().toString();
case RAW_FILE_URI1 -> "file:" + extraPropsFile.path;
case RAW_FILE_URI2 -> "file://" +
(extraPropsFile.path.startsWith("/") ? "" : "/") +
extraPropsFile.path;
case PATH_ABS -> extraPropsFile.path.toString();
case PATH_REL -> CWD.relativize(extraPropsFile.path).toString();
}, overrideAll);
setRawExtraFile(extraPropsFile.getSysPropValue(), overrideAll);
}
void setIgnoredExtraFile(String extraPropsFile, boolean overrideAll) {
@ -841,7 +851,7 @@ final class Executor {
List<String> command = new ArrayList<>(jvmArgs);
Collections.addAll(command, Utils.getTestJavaOpts());
addSystemPropertiesAsJvmArgs(command);
command.add(ConfigFileTest.class.getSimpleName());
command.add(ExtraFileAndIncludes.class.getSimpleName());
command.add(RUNNER_ARG);
oa = ProcessTools.executeProcess(new ProcessBuilder(command));
oa.shouldHaveExitValue(successExpected ? 0 : 1);

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2026, Red Hat, Inc.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.process.ProcessTools;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
/*
* @test
* @summary Ensures the java executable is able to load extra security
* properties files from anonymous files and pipes.
* @bug 8352728
* @requires os.family == "linux"
* @modules java.base/java.io:+open
* @library /test/lib
* @run main LinuxAnonymousFiles
*/
public class LinuxAnonymousFiles {
private static final String TEST_PROP = "property.name=PROPERTY_VALUE";
private static final class AnonymousFile implements AutoCloseable {
public final Path fdPath;
private final FileInputStream fis;
private AnonymousFile(CharSequence content) throws Exception {
Path tmp = Files.createTempFile("anonymous-file-", "");
Files.writeString(tmp, content + System.lineSeparator());
fis = new FileInputStream(tmp.toFile());
Files.delete(tmp);
// Now the file is regular but anonymous, and will be unlinked
// when we close the last file descriptor referring to it. The
// fis instance ensures we keep it alive until close() is invoked.
Field field = FileDescriptor.class.getDeclaredField("fd");
field.setAccessible(true);
int fd = field.getInt(fis.getFD());
fdPath = Path.of("/proc/self").toRealPath().resolve("fd/" + fd);
}
@Override
public void close() throws IOException {
fis.close();
}
}
public static void main(String[] args) throws Exception {
Path java = Path.of(System.getProperty("test.jdk"), "bin", "java");
try (AnonymousFile af = new AnonymousFile("include /dev/stdin")) {
ProcessTools.executeProcess(new ProcessBuilder(java.toString(),
"-Djava.security.debug=properties",
"-Djava.security.properties=" + af.fdPath,
"-XshowSettings:security:properties", "-version"),
TEST_PROP).shouldHaveExitValue(0).shouldContain(TEST_PROP);
}
System.out.println("TEST PASS - OK");
}
}

View File

@ -1 +0,0 @@
policy.url.2=file:${test.src}/SecurityPropFile.policy

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2001, 2024, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 4303068
* @summary be allowed to specify the security properties file
* as a -D system property
*
* @run main/othervm -Djava.security.properties=${test.src}/SecurityPropFile.file -Djava.security.debug=properties SecurityPropFile
*/
public class SecurityPropFile {
public static void main(String[] args) {
System.out.println(java.security.Security.getProperty
("policy.provider"));
System.out.println(java.security.Security.getProperty
("policy.url.1"));
System.out.println(java.security.Security.getProperty
("policy.url.2"));
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2026, Red Hat, Inc.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.util.FileUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryType;
import java.nio.file.attribute.AclFileAttributeView;
import java.util.List;
/*
* @test
* @summary Ensures java.security is loadable in Windows, even when the user
* does not have permissions on one of the parent directories.
* @bug 8352728
* @requires os.family == "windows"
* @library /test/lib
* @run main WindowsParentDirPermissions
*/
public class WindowsParentDirPermissions {
private static AutoCloseable restrictedAcl(Path path) throws IOException {
AclFileAttributeView view =
Files.getFileAttributeView(path, AclFileAttributeView.class);
List<AclEntry> originalAcl = List.copyOf(view.getAcl());
view.setAcl(List.of(AclEntry.newBuilder().setType(AclEntryType.DENY)
.setPrincipal(Files.getOwner(path)).build()));
return () -> view.setAcl(originalAcl);
}
public static void main(String[] args) throws Exception {
Path temp = Files.createTempDirectory("JDK-8352728-tmp-");
try (AutoCloseable a1 = () -> FileUtils.deleteFileTreeUnchecked(temp)) {
// Copy the jdk to a different directory
Path originalJdk = Path.of(System.getProperty("test.jdk"));
Path jdk = temp.resolve("jdk-parent-dir", "jdk");
Files.createDirectories(jdk);
FileUtils.copyDirectory(originalJdk, jdk);
// Remove current user permissions from jdk-parent-dir
try (AutoCloseable a2 = restrictedAcl(jdk.getParent())) {
// Make sure the permissions are affecting the current user
try {
jdk.toRealPath();
throw new jtreg.SkippedException("Must run non-elevated!");
} catch (IOException expected) { }
// Execute the copied jdk, ensuring java.security.Security is
// loaded (i.e. use -XshowSettings:security:properties)
ProcessTools.executeProcess(new ProcessBuilder(
List.of(jdk.resolve("bin", "java.exe").toString(),
"-Djava.security.debug=properties",
"-XshowSettings:security:properties",
"-version"))).shouldHaveExitValue(0);
}
}
System.out.println("TEST PASS - OK");
}
}