This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients bstorm, eryksun, ned.deily, paul.moore, steve.dower, tim.golden, vinay.sajip, vstinner, zach.ware
Date 2019-06-27.22:09:40
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1561673381.23.0.280194327043.issue37369@roundup.psfhosted.org>
In-reply-to
Content
> you should go through your current user's apps directory 
> (C:\Users\name\AppData\Local\Microsoft\WindowsApps\<package family>,
> which contains only symlinks to the actual executables).

"%LocalAppData%\Microsoft\WindowsApps" contains IO_REPARSE_TAG_APPEXECLINK reparse points. An application-execution link is not like a regular symlink, i.e. it does not have the name-surrogate bit set in the tag value. In addition to the real application path, an app-exec link also contains the package information that the system uses to create the special access token that's required in order to execute the application.

I stepped through CreateProcessW in 10.0.18362.175 (slow ring), which has the old behavior. The first NtCreateUserProcess system call (the call that actually creates the Process object) fails with STATUS_IO_REPARSE_TAG_NOT_HANDLED. CreateProcessW handles this by getting the package information from the reparse point and creating a new token that contains 3 additional security attributes (WIN://SYSAPPID, WIN://PKG, and WIN://PKGHOSTID). For the subsequent NtCreateUserProcess system call, it uses the real path under "%ProgramFiles%\WindowsApps" and impersonates the new access token. 

The real executable has two ACEs for standard users. There's a basic access-allowed ACE that grants read access, but does not grant execute access. There's also an access-allowed callback ACE that grants read and execute access. Normally the kernel security routines ignore callback ACEs in an access check, since they're intended for an application-defined callback in the user-mode AuthZ API. Apparently something is special-casing the access check in this case, to conditionally check the security attributes in the token in order to apply this callback ACE. If I remove the callback ACE, users can no longer execute python.exe, so I know this is the ACE that's granting execute access.

Back to CreateProcessW. If I try to directly execute the real executable in "%ProgramFiles%\WindowsApps", the NtCreateUserProcess system call fails with STATUS_ACCESS_DENIED, as expected. But then CreateProcessW does something that I didn't expect. It parses out the base filename "python.exe" and joins it to "%LocalAppData%\Microsoft\WindowsApps". If it finds the app-exec link, then it reads it to create the special package access token, as if we had run the app-exec link directly. If I had to guess, I would assume this behavior has been disabled in newer versions of Windows 10. I'm using the slow ring for now, so I don't have a way to test this guess.
History
Date User Action Args
2019-06-27 22:09:41eryksunsetrecipients: + eryksun, paul.moore, vinay.sajip, vstinner, tim.golden, ned.deily, zach.ware, steve.dower, bstorm
2019-06-27 22:09:41eryksunsetmessageid: <1561673381.23.0.280194327043.issue37369@roundup.psfhosted.org>
2019-06-27 22:09:41eryksunlinkissue37369 messages
2019-06-27 22:09:40eryksuncreate