Skip to content

Commit 308479d

Browse files
committed
8352728: InternalError loading java.security due to Windows parent folder permissions
1 parent 5f2a604 commit 308479d

File tree

2 files changed

+98
-5
lines changed

2 files changed

+98
-5
lines changed

src/java.base/share/classes/java/security/Security.java

+11-5
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,19 @@ static void loadInclude(String propFile) {
265265
private static void loadFromPath(Path path, LoadingMode mode)
266266
throws IOException {
267267
boolean isRegularFile = Files.isRegularFile(path);
268-
if (isRegularFile) {
269-
path = path.toRealPath();
270-
} else if (Files.isDirectory(path)) {
268+
if (!isRegularFile && Files.isDirectory(path)) {
271269
throw new IOException("Is a directory");
272-
} else {
273-
path = path.toAbsolutePath();
274270
}
271+
// For path canonicalization, we prefer
272+
// java.io.File::getCanonicalPath over
273+
// java.nio.file.Path::toRealPath because of the following reasons:
274+
// 1. In Windows, File::getCanonicalPath handles restricted
275+
// permissions in parent directories. Contrarily,
276+
// Path::toRealPath fails with AccessDeniedException.
277+
// 2. In Linux, File::getCanonicalPath handles non-regular files
278+
// (e.g. /dev/stdin). Contrarily, Path::toRealPath fails with
279+
// NoSuchFileException.
280+
path = Path.of(path.toFile().getCanonicalPath());
275281
if (activePaths.contains(path)) {
276282
throw new InternalError("Cyclic include of '" + path + "'");
277283
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) 2025, Red Hat, Inc.
3+
*
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
import jdk.test.lib.process.ProcessTools;
26+
import jdk.test.lib.util.FileUtils;
27+
28+
import java.io.IOException;
29+
import java.nio.file.Files;
30+
import java.nio.file.Path;
31+
import java.nio.file.attribute.AclEntry;
32+
import java.nio.file.attribute.AclEntryType;
33+
import java.nio.file.attribute.AclFileAttributeView;
34+
import java.util.List;
35+
36+
/*
37+
* @test
38+
* @summary Ensures java.security is loadable in Windows, even when the user
39+
* does not have permissions on one of the parent directories.
40+
* @bug 8352728
41+
* @requires os.family == "windows"
42+
* @library /test/lib
43+
* @run main ConfigFileTestDirPermissions
44+
*/
45+
46+
public class ConfigFileTestDirPermissions {
47+
public static void main(String[] args) throws Exception {
48+
Path temp = Files.createTempDirectory("JDK-8352728-tmp-");
49+
try {
50+
// Copy the jdk to a different directory
51+
Path originalJdk = Path.of(System.getProperty("test.jdk"));
52+
Path jdk = temp.resolve("jdk-parent-dir", "jdk");
53+
Files.createDirectories(jdk);
54+
FileUtils.copyDirectory(originalJdk, jdk);
55+
56+
// Remove current user permissions from jdk-parent-dir
57+
Path parent = jdk.getParent();
58+
AclFileAttributeView view = Files.getFileAttributeView(parent,
59+
AclFileAttributeView.class);
60+
List<AclEntry> originalAcl = List.copyOf(view.getAcl());
61+
view.setAcl(List.of(AclEntry.newBuilder().setType(AclEntryType.DENY)
62+
.setPrincipal(Files.getOwner(parent)).build()));
63+
64+
try {
65+
// Make sure the permissions are affecting the current user
66+
try {
67+
jdk.toRealPath();
68+
throw new jtreg.SkippedException("Must run non-elevated!");
69+
} catch (IOException expected) { }
70+
71+
// Execute the copied jdk, ensuring java.security.Security is
72+
// loaded (i.e. use -XshowSettings:security:properties)
73+
ProcessTools.executeProcess(new ProcessBuilder(
74+
List.of(jdk.resolve("bin", "java.exe").toString(),
75+
"-Djava.security.debug=properties",
76+
"-XshowSettings:security:properties",
77+
"-version"))).shouldHaveExitValue(0);
78+
} finally {
79+
view.setAcl(originalAcl);
80+
}
81+
} finally {
82+
FileUtils.deleteFileTreeUnchecked(temp);
83+
}
84+
85+
System.out.println("TEST PASS - OK");
86+
}
87+
}

0 commit comments

Comments
 (0)