classification
Title: Add non-elevated symlink support for dev mode Windows 10
Type: enhancement Stage: resolved
Components: Library (Lib), Windows Versions: Python 3.8
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: eryksun, izbyshev, paul.moore, steve.dower, tim.golden, vidartf, zach.ware
Priority: normal Keywords: patch

Created on 2017-09-18 19:16 by vidartf, last changed 2019-04-09 18:20 by steve.dower. This issue is now closed.

Files
File name Uploaded Description Edit
devsymlink.patch vidartf, 2017-09-18 19:16 Proof of concept patch
Pull Requests
URL Status Linked Edit
PR 3652 merged vidartf, 2017-09-19 11:01
Messages (9)
msg302482 - (view) Author: Vidar Fauske (vidartf) * Date: 2017-09-18 19:16
As explained in this Microsoft blogpost (https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/), it is possible on newer versions of Windows 10 for non-privileged users to create symlinks when the machine is in developer mode. However, to ensure backwards compatibility, this behavior requires a flag to be passed to the CreateSymbolicLink function.

I think this is something that Python can benefit from having. It would go from "symlinks on Windows rarely work" to "symlinks on Windows work in developer mode (and rarely otherwise)".

I've attached a proof of concept patch to enable this behavior (a Windows 10 machine with the 'Creators Update' is required to test it). In summary, it enables the flag by default, and updates enable_symlink to prevent lacking privilege from disabling symlinks on machines in developer mode.
msg302494 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2017-09-19 00:35
Py_CreateSymbolicLinkW can be removed in 3.5+ because Windows XP is no longer supported and calling enable_symlink() is pointless. 

The Windows API uses some privileges simply to determine which security principals can access a capability. Whether the privilege is currently enabled or disabled in the current access token doesn't matter because functions automatically enable it for the current thread (in an impersonation token). 

In this case, CreateSymbolicLink calls RtlAcquirePrivilege to enable SeCreateSymbolicLinkPrivilege for the current thread; sets the symlink reparse point; and then reverts the current thread via RtlReleasePrivilege. It goes through these same steps whether or not the privilege is already enabled in the process, so there's no chance of a race condition between competing threads.

Also, as a side note, the linked blog makes the following claim, which paints an incomplete picture:

> However, for Windows users, due to Windows Vista’s security 
> requirements, users needed local admin rights and, importantly, 
> had to run mklink in a command-line console elevated as 
> administrator to create/modify symlinks. 

SeCreateSymbolicLinkPrivilege can be added to a standard user account, and it doesn't get filtered out from the user's token. So in general you do not need administrator access. However, the above is describing the case for most developers, who use a administrator account that's subject to UAC restrictions.
msg302673 - (view) Author: Vidar Fauske (vidartf) * Date: 2017-09-21 09:01
Thanks for the informative comments. I opened a PR based on this feedback. Would you mind checking if it conforms to what you had in mind?
msg330307 - (view) Author: Vidar Fauske (vidartf) * Date: 2018-11-23 11:44
The PR has been sitting for a while now with all previous concerns addressed. There has been a few pings on the PR without anything new happening, so I thought I would ping this issue as well: are there any other concerns about this PR, or anything else that is preventing it from being merged?
msg330349 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2018-11-23 18:01
Thanks for the ping (I don't see GitHub notifications - I get 1000s per day and it's not feasible to read them).

I left one more comment on the PR, but then it's good to go!
msg330538 - (view) Author: Vidar Fauske (vidartf) * Date: 2018-11-27 16:55
Thanks! I addressed the comment, so hopefully this should be OK now.
msg339696 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2019-04-09 03:09
:ping: It seems this was ready to be merged a while ago.
msg339800 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2019-04-09 18:19
New changeset 0e10766574f4e287cd6b5e5860a1ca75488f4119 by Steve Dower (Vidar Tonaas Fauske) in branch 'master':
bpo-31512: Add non-elevated symlink support for Windows (GH-3652)
https://github.com/python/cpython/commit/0e10766574f4e287cd6b5e5860a1ca75488f4119
msg339801 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2019-04-09 18:20
Done
History
Date User Action Args
2019-04-09 18:20:25steve.dowersetstatus: open -> closed
resolution: fixed
messages: + msg339801

stage: patch review -> resolved
2019-04-09 18:19:51steve.dowersetmessages: + msg339800
2019-04-09 03:09:34eryksunsetmessages: + msg339696
2018-11-27 16:55:58vidartfsetmessages: + msg330538
2018-11-23 18:01:41steve.dowersetmessages: + msg330349
2018-11-23 11:44:49vidartfsetmessages: + msg330307
2018-09-04 19:24:26terry.reedysetversions: + Python 3.8, - Python 3.6, Python 3.7
2018-06-23 16:18:06eryksunlinkissue33946 superseder
2018-02-27 23:20:32izbyshevsetnosy: + izbyshev
2017-09-21 09:01:00vidartfsetmessages: + msg302673
2017-09-19 11:01:45vidartfsetstage: patch review
pull_requests: + pull_request3645
2017-09-19 00:35:32eryksunsetnosy: + eryksun
messages: + msg302494
2017-09-18 19:16:30vidartfcreate