https://bugs.winehq.org/show_bug.cgi?id=56647
Bug ID: 56647 Summary: ntdll-Junction_Points prevent rustup from correctly installing a toolchain Product: Wine-staging Version: 9.8 Hardware: x86-64 URL: https://rustup.rs/ OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: lorenzofer@live.it CC: leslie_alistair@hotmail.com, z.figura12@gmail.com Distribution: ArchLinux
Created attachment 76423 --> https://bugs.winehq.org/attachment.cgi?id=76423 return STATUS_NOT_A_REPARSE_POINT instead of STATUS_INVALID_PARAMETER
Hi. With the recent rustup 1.27.0 using wine-staging with the ntdll-Junction_Points patches, the toolchain installation doesn't complete properly, failing to write to the settings.toml under the prefix home .rustup directory info.
A bug with the same root cause is also present on rustup 1.26.0 where while the installation was completing properly, it was failing to remove the .rustup/tmp/* directories, causing issues with subsequent installations.
Both bugs express the same behavioral pattern with few differences. I investigated the directory bug firstly, so I will detail this, and confirmed that the problem and the expected solution are the same.
Rustup (or one of it's dependency managing files) get the handle of the temporary directory using CreateFileW and then checking if it's a reparse point using DeviceIoControl with FSCTL_GET_REPARSE_POINT. The directories (and the file) aren't reparse points at all, so the readlink fails returining EINVAL. This EINVAL is then mapped to an NT_STATUS using errno_to_status that map EINVAL to STATUS_INVALID_PARAMETER. However this mapping is incorrect for FSCTL_GET_REPARSE_POINT as in this case applications that handle this case like rustup try to handle this case by epxecting STATUS_NOT_A_REPARSE_POINT.
Returning STATUS_NOT_A_REPARSE_POINT in this case allow rustup to work (both versions )
Attaching a patch to show the change in the file.c code (and restored also the out_buffer check)
https://bugs.winehq.org/show_bug.cgi?id=56647
Lorenzo Ferrillo lorenzofer@live.it changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |erich.e.hoover@gmail.com
https://bugs.winehq.org/show_bug.cgi?id=56647
--- Comment #1 from Lorenzo Ferrillo lorenzofer@live.it --- CCing Erich E. Hoover as the maker of the patchset
https://bugs.winehq.org/show_bug.cgi?id=56647
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, source
https://bugs.winehq.org/show_bug.cgi?id=56647
--- Comment #2 from Lorenzo Ferrillo lorenzofer@live.it --- I have another issue related to this patchset and Rust, in particular the tool cargo from Nightlies after 05 May 2024, when the code you are compiling is on a directory with part of the path on a different drive (in my case was in a subdir of Z:\home)
This particualr issue start from the 0005 patch of the patchset: Subject: [PATCH] server: Implement FILE_OPEN_REPARSE_POINT option.
In particular adding the FILE_OPEN_REPARSE_POINT to kernelbase, this cause this path to be considered a reparse point and assigned the FILE_ATTRIBUTE_REPARSE_POINT flag.
This cause cargo to ask for a NtQueryInformationFile with FileAttributeTagInformation (in addition to FileStatInformation) If this return IO_REPARSE_TAG_MOUNT_POINT, as it's in this case, it try to get the Reparse Point info with FSCTL_GET_REPARSE_POINT where the flow is failing on readlink (as linux mountpoints aren't symlinks)
Note that even FileStatInformation have a ReparseTag that can contain IO_REPARSE_TAG_MOUNT_POINT, but that it's used at all, preferring FileAttributeTagInformation.
If I avoid returning IO_REPARSE_TAG_MOUNT_POINT from FileAttributeTagInformation, cargo start to work again If I globally avoid FILE_OPEN_REPARSE_POINT in get_nt_file_options, it works and avoid the call for FileAttributeTagInformation If I avoid setting FILE_ATTRIBUTE_REPARSE_POINT in fd_get_file_info beheaviour is like the previous one.
I see different mode to proceed: The first would be to avoid setting IO_REPARSE_TAG_MOUNT_POINT, either in the specific sections or stubbing fd_is_mount_point, both situation would effectively return to the previous situation without FILE_OPEN_REPARSE_POINT implemented (the code to set IO_REPARSE_TAG_MOUNT_POINT was there is various zone but "dead" becouse conditioned on this flag ) or to try to implement this case (with the risk of opening another can of worms)
https://bugs.winehq.org/show_bug.cgi?id=56647
--- Comment #3 from Erich E. Hoover erich.e.hoover@gmail.com --- (In reply to Lorenzo Ferrillo from comment #2)
... This cause cargo to ask for a NtQueryInformationFile with FileAttributeTagInformation (in addition to FileStatInformation) If this return IO_REPARSE_TAG_MOUNT_POINT, as it's in this case, it try to get the Reparse Point info with FSCTL_GET_REPARSE_POINT where the flow is failing on readlink (as linux mountpoints aren't symlinks) ...
It's been a while since I've looked at this, but I thought I had it set up to return an IO_REPARSE_TAG_LX_SYMLINK (WSL Linux Symlink)... I'll try to take a look at these issues this weekend, but if it's failing to "convert" unix symlinks (or I forgot to add that patch) then that could explain the issue here.
https://bugs.winehq.org/show_bug.cgi?id=56647
--- Comment #4 from Lorenzo Ferrillo lorenzofer@live.it --- Eric the issue here is that these folders aren't symlinks, they are unix mountpoints, and readlink doesn't work for them. IO_REPARSE_TAG_MOUNT_POINT is setted only if S_ISDIR is true and the folder device is different then the parent device, or their inode are the same. The function for that is fd_is_mount_point and pre-exist the ntdll_Junction-Points patchset however they weren't actually setted without implementing FILE_OPEN_REPARSE_POINT usage.
https://bugs.winehq.org/show_bug.cgi?id=56647
--- Comment #5 from Erich E. Hoover erich.e.hoover@gmail.com --- (In reply to Lorenzo Ferrillo from comment #4)
Eric the issue here is that these folders aren't symlinks, they are unix mountpoints, and readlink doesn't work for them. IO_REPARSE_TAG_MOUNT_POINT is setted only if S_ISDIR is true and the folder device is different then the parent device, or their inode are the same. The function for that is fd_is_mount_point and pre-exist the ntdll_Junction-Points patchset however they weren't actually setted without implementing FILE_OPEN_REPARSE_POINT usage.
Oh, I thought you were talking about a symlink to a different drive. I'll have to think about how a real mount point should behave here...