Hello core-libs-dev,
I was asked to help look into JDK-8232092 by Christian Stein (the bug
reporter), and since I don't have an OpenJDK account yet I'm sharing my
findings on the issue here. I looked into two separate issues that might cause
FileSystemProvider.checkAccess to return an incorrect result as reported.
The first issue seems related to substituted directories with volumes, or
virtual drives on Windows. The problem happens if the Windows
GetVolumePathNameW API is called with a virtual drive letter in the path,
causing the API to return ERROR_INVALID_PARAMETER or error code 87. The code in
WindowsFileStore::create makes a call to WindowsLinkSupport::getFinalPath,
however the getFinalPath method will avoid expanding the virtual drive path, by
calling GetFinalPathNameByHandle, because the path isn't a symbolic link. The
existing code in WindowsFileStore::create currently checks for the ErrorLevel
of ERROR_DIR_NOT_ROOT, and it properly calls the path expansion API, however it
doesn't check for ERROR_INVALID_PARAMETER which might happen if a path with
virtual drive letter is used.
We can follow the steps below to reproduce the issue:
- Have a writeable directory on Windows, e.g. C:\Temp
- Run "subst T: C:\Temp" on the command line to create the virtual drive T for
C:\Temp
- Check with "cacls T:" and "cacls C:\Temp" that you have the exact same access
control permissions
- Run "FileSystems.getDefault().provider().checkAccess(Path.of("T:\\"),
java.nio.file.AccessMode.WRITE)" in jshell and you'll see an Exception
java.nio.file.FileSystemException: T:\: The parameter is incorrect. Running the
same command on C:\\Temp will return without an exception.
I've attached at the bottom of this email a simple patch that address the
virtual drive issue. There might be a better way to fix this issue so any
feedback is appreciated.
The second issue reported is using a virtual drive with the ImDisk utility to
create a Virtual RAM Disk on Windows (Z: drive in the bug report). As mentioned
in the bug report the failure is slightly different, in this case
GetFinalPathNameByHandleW is called and the API returns ERROR_INVALID_FUNCTION.
This error is caused by the third-party utility design/implementation. With
ImDisk virtual disks, applications that rely on Windows Volume Mount Manager
APIs, like GetFinalPathNameByHandleW, will fail because ImDisk does not
interact with Windows Volume Mount Manager at all, it effectively bypasses it.
Essentially, GetFinalPathNameByHandle and few other APIs will never work
properly with ImDisk virtual drives.
Cheers,
Nikola Grcevski
Microsoft
diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileStore.java
b/src/java.base/windows/classes/sun/nio/fs/WindowsFileStore.java
index acbb2c15f2a..9b4b4117b24 100644
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileStore.java
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileStore.java
@@ -79,10 +79,12 @@ class WindowsFileStore
// volume that the link is on so we need to call it with the
// final target
String target = WindowsLinkSupport.getFinalPath(file, true);
+
try {
return createFromPath(target);
} catch (WindowsException e) {
- if (e.lastError() != ERROR_DIR_NOT_ROOT)
+ if (e.lastError() != ERROR_DIR_NOT_ROOT &&
+ e.lastError() != ERROR_INVALID_PARAMETER)
throw e;
target = WindowsLinkSupport.getFinalPath(file);
if (target == null)