RFR: 8352728: InternalError loading java.security due to Windows parent folder permissions [v14]

Weijun Wang weijun at openjdk.org
Thu Dec 11 01:13:26 UTC 2025


On Wed, 10 Dec 2025 23:00:11 GMT, Francisco Ferrari Bihurriet <fferrari at openjdk.org> wrote:

>> I'm a little confused. Now that we have agreed to no longer revolve symlinks, `/tmp/a/b/../f2` should indeed be `/tmp/a/f2`. Since it does not exist, we simply fail. Why is this a problem? Did I miss anything?
>
> Hmm, I also got confused for a moment, it seems important to make a distinction between file links and directory links, and how each platform handles each of them.
> 
> We are no longer resolving any type of link, here:
> 
> https://github.com/openjdk/jdk/blob/c33bf62c2831acefd90ec476fcfb6d853be873ee/src/java.base/share/classes/java/security/Security.java#L250-L258
> 
> `currentPath.resolveSibling(path)` is equivalent to `currentPath.getParent().resolve(path)` when `currentPath` has a parent.
> 
> If `currentPath` is `/tmp/a/b/f1` and `path` is `../f2`, after line 257, path will be `/tmp/a/b/../f2`.
> 
> In the [previous _Linux_ example](#discussion_r2607247993), `/tmp/a/b` is a **directory** symbolic link to `/tmp/x/y`, so `/tmp/a/b/../f2` still reads `/tmp/x/f2` (at the OS level) when opening the file.
> 
> <details>
> <summary>Extension of that <em>Linux</em> example's <code>jshell</code> snippet showing how <code>/tmp/a/b/../f2</code> can be opened</summary>
> 
> 
> jshell -<<'EOF'
> Path current = Path.of("/tmp/a/b/f1");
> Path included = current.resolveSibling("../f2");
> 
> Map<String, Path> opts = new LinkedHashMap<String, Path>();
> opts.put("included", included);
> opts.put("included.toRealPath()", included.toRealPath());
> opts.put("included.toRealPath(LinkOption.NOFOLLOW_LINKS)",
>         included.toRealPath(LinkOption.NOFOLLOW_LINKS));
> opts.put("included.normalize()", included.normalize());
> 
> for (Map.Entry<String, Path> opt : opts.entrySet()) {
>     System.out.println();
>     System.out.println(opt.getKey() + " -> " + opt.getValue());
>     Files.newInputStream(opt.getValue());
>     System.out.println("succesfully opened");
> }
> EOF
> 
> 
> Output:
> 
> 
> included -> /tmp/a/b/../f2
> succesfully opened
> 
> included.toRealPath() -> /tmp/x/f2
> succesfully opened
> 
> included.toRealPath(LinkOption.NOFOLLOW_LINKS) -> /tmp/a/b/../f2
> succesfully opened
> 
> included.normalize() -> /tmp/a/f2
> Exception java.nio.file.NoSuchFileException: /tmp/a/f2
>       at UnixException.translateToIOException (UnixException.java:92)
>       at UnixException.rethrowAsIOException (UnixException.java:106)
>       at UnixException.rethrowAsIOException (UnixException.java:111)
>       at UnixFileSystemProvider.newByteChannel (UnixFileSystemProvider.java:261)
>       at Files.newByteChannel (Files.java:380)
>       at Files.newByteChannel (Files.java:432)
>       at FileSystemProvider.newInputStream (FileSystemProvider.java:420)
>       at Files.newInputStream (Files.java:160)
>       at (#8:4)
> 
> 
> </details>
> 
> With that observation, I tried to re-introduce 7abb62c069ad3...

Thanks for the detailed explanation.

I like your attitude to leave the path resolution to the simplest API. 

For debugging output, I prefer the 3rd choice for the same reason that it's the simplest. Also, it preserves the original include form. I would assume the reader wants to see this.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/24465#discussion_r2608776622


More information about the security-dev mailing list