Skip to content

std.os.windows: add error.UnrecognizedVolume #18952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 16, 2024

Conversation

andrewrk
Copy link
Member

@andrewrk andrewrk commented Feb 15, 2024

Thanks to @matklad for finding this additional NTSTATUS possibility when calling GetFinalPathNameByHandle.

Follow-up issue:

@andrewrk andrewrk added breaking Implementing this issue could cause existing code to no longer compile or have different behavior. standard library This issue involves writing Zig code for the standard library. os-windows labels Feb 15, 2024
Comment on lines +2240 to +2252
// This mapping is not correct; it is actually expected
// that calling GetFinalPathNameByHandle might return
// error.UnrecognizedVolume, and in fact has been observed
// in the wild. The problem is that wToPrefixedFileW was
// never intended to make *any* OS syscall APIs. It's only
// supposed to convert a string to one that is eligible to
// be used in the ntdll syscalls.
//
// To solve this, this function needs to no longer call
// GetFinalPathNameByHandle under any conditions, or the
// calling function needs to get reworked to not need to
// call this function.
//
// This may involve making breaking API changes.
Copy link
Collaborator

@squeek502 squeek502 Feb 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, the dilemma is:

  • ntdll syscalls cannot handle relative paths with .. components
  • In the best case, we can remove .. components trivially (this is what normalizePath/removeDotDirsSanitized does)
  • However, to be able to make a syscall when given a path like ../../foo, it needs to be resolved into an absolute path and given the NT namespace prefix (\??\)
  • RtlGetFullPathName_U can handle the case when resolving a path like ../../foo against the cwd, but not against an arbitrary directory handle
  • Therefore, we use our own GetFinalPathNameByHandle implementation in the case where we (1) can't trivially remove .. components and (2) need to resolve the path against a non-CWD dir

EDIT: So one possibility here is that there's some way to handle a path like ../../foo without needing to resolve it into an absolute path. The other is that this is a bug in our GetFinalPathNameByHandle implementation rather than wToPrefixedFileW (that is, we're not able to get a path of a handle that we should be able to get a path for).

EDIT#2: Here's where the GetFinalPathNameByHandle call was introduced: #16783 and the bug it fixed: #16779

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, to be able to make a syscall when given a path like ../../foo, it needs to be resolved into an absolute path and given the NT namespace prefix (??)

Zig file system API should make this fail for all operating systems. You shouldn't be able to open a parent directory from an open directory handle.

The only exception is the current working directory, which is already an exception for other use cases.

This hack should have never been made, and by not making the hack it would have helped us reach that conclusion earlier.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fwiw, I believe it was me who reported ".. doesn’t work on windows” (#16779), and, for my use-case, it is indeed enough if that only works for cwd

Copy link
Collaborator

@squeek502 squeek502 Feb 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zig file system API should make this fail for all operating systems. You shouldn't be able to open a parent directory from an open directory handle.

This might be a bit complicated due to things like #18452 and #7751. That is, resolving .. before symlinks (the Windows way) would be a break from normal non-Windows behavior, and resolving symlinks before .. would require syscalls. Symlinks in general complicate things, too.

There is a potentially relevant RESOLVE_BENEATH flag on Linux (and O_RESOLVE_BENEATH on FreeBSD), though: https://man7.org/linux/man-pages/man2/openat2.2.html

Thanks to @matklad for finding this additional NTSTATUS possibility when
calling GetFinalPathNameByHandle.
@andrewrk andrewrk force-pushed the windows-unrecognized-volume branch from 003aa82 to f4620d4 Compare February 16, 2024 01:40
@andrewrk andrewrk merged commit 0183b44 into master Feb 16, 2024
@andrewrk andrewrk deleted the windows-unrecognized-volume branch February 16, 2024 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. os-windows standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants