-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
os: Symlink creation should work on Windows without elevation #22874
Comments
For the record, this does in fact make the call succeed on my systems; diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index 93b6c135c7..8baf7d2c60 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -391,6 +391,7 @@ func Symlink(oldname, newname string) error {
if isdir {
flags |= syscall.SYMBOLIC_LINK_FLAG_DIRECTORY
}
+ flags |= 0x02 // SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
err = syscall.CreateSymbolicLink(n, o, flags)
if err != nil {
return &LinkError{"symlink", oldname, newname, err} |
If they transparently allowed users to create symlinks without client side code changes, that means existing broken code would suddenly start working. Instead, the Windows 10 Creators Update introduces honor system privilege escalation. FWIW the change works on my Windows 10 system after the patch too |
Thanks for the info! We can look into this for Go 1.11, including writing a test which will make sure we don't accidentally break Windows XP etc by including this flag. Hopefully we don't need to conditionally set the flag after detecting the OS version at runtime. But we might. /cc @alexbrainman |
@calmh do you propose to just add SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE flag to syscall.CreateSymbolicLink call? I am bit concerned about doing this by default (what @as said) - your program fails at this moment, but it will succeed after your change. And given that this functionality is a "security concern" according to Microsoft, that makes me even more worried. Reading https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/ does not make it clear in my mind what Microsoft recommends - new functionality will only work in "developer" mode, so they are still concerned about security - why do they leave final decision on us developers (SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE flag)? Alex |
Go tries to take the cross platform approach, erring to the side of Unixness. Compare for example os.Remove which takes care to remove read only files on Windows too, because that's how it works on most other Go support systems - as opposed to the Windows native API. On other systems regular users can create symlinks, so I don't think most Go programs will be surprised if this also succeeds on Windows (with the appropriate mode enabled, etc.). The developer mode in Windows 10 is one thing, it's not clear to me that symlinks for regular users will not be enabled by default in Windows 11 or whatever. So yes, I think we should set the flag and make os.Symlink succeed when it can, even on Windows. Especially since there is no other way to do it on Windows (using the standard library without hacks). |
My concern is that we are changing existing behavior. And a security related behavior at that. I am not security expert myself, so I would not know what the implication of this change is.
That does not bother me, because it is out of our control.
Yes, I don't see a way to allow new functionality in Go standard library. Maybe we should just wait for Windows 11 :-) Alex |
I don't know how to argue against an unspecified security straw man, but whatever Go program depends on this behavior seems broken to me. I can see Microsoft having to retain 100% API compatibility forever (that's their thing for good and bad), but we do not to the same extent and there is prior art - for example in #9606. The impact of this change would be insignificant in comparison to that change, imho. |
Symbolic links are UNIX like Sockets and X11 are UNIX: regrettably so. There is probably a reason MS used an opt-in for this feature, whether they want free quality assurance through their developer program or otherwise aren't sure of what this change will do across different Windows versions: it's odd. |
Fair enough. @calmh if you send a fix for this, I will be happy to test it on Windows XP. But this would have to wait until after go1.10 is released. Thank you. Alex |
…g as SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE is not yet implemented in Go's implementation for Window's symlinks as of 1.9.2 - golang/go#22874 Signed-off-by: Nicholas Rishel <PrototypeNM1@users.noreply.github.com>
…g as SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE is not yet implemented in Go's implementation for Window's symlinks as of 1.9.2 - golang/go#22874 Signed-off-by: Nicholas Rishel <PrototypeNM1@users.noreply.github.com>
…g as SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE is not yet implemented in Go's implementation for Window's symlinks as of 1.9.2 - golang/go#22874 Signed-off-by: Nicholas Rishel <PrototypeNM1@users.noreply.github.com>
Change https://golang.org/cl/99337 mentions this issue: |
@calmh err := os.Symlink("old", "new")
if err != nil {
fmt.Printf("%s\n", err)
}
err = os.Symlink("old", "new")
if err != nil {
fmt.Printf("%s\n", err)
} Unfortunately, I beleive the fault seems to be in the WINAPI itself, |
On Windows 10 Creators Update, with Developer Mode enabled, symlinks can be created by regular users without elevation. This can be tested by opening a command prompt and running
mklink a b
for example. However, creating links usingos.Symlink
in Go 1.9.2 windows/amd64 fails withA required privilege is not held by the client.
The cause seems to be that the application needs to pass the
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
flag toCreateSymbolicLink
in order to be able to create symbolic links without elevation. I can't exactly follow the reasoning behind introducing and requiring this flag, but it seems like we should probably set it in theos.Symlink
implementation for Windows.https://msdn.microsoft.com/en-us/library/windows/desktop/aa363866(v=vs.85).aspx
Given that this flag exists at all we should probably expect further bizarre stuff like the call failing if we are privileged and passing that flag, or if we are privileged and on a Windows version where the flag doesn't exist yet, or whatever. So it probably requires more careful testing than just slapping on the flag and seeing it succeed...
The text was updated successfully, but these errors were encountered: