win: support running inside an AppContainer (lowbox token)#5
Open
dylan-conway wants to merge 3 commits into
Open
win: support running inside an AppContainer (lowbox token)#5dylan-conway wants to merge 3 commits into
dylan-conway wants to merge 3 commits into
Conversation
Returns 1 when the process runs with an AppContainer (lowbox) token, 0 otherwise and on non-Windows platforms. Several Windows facilities (the named pipe namespace, the mount manager) are restricted inside an AppContainer; embedders and upcoming libuv code need a cheap way to detect that situation.
An AppContainer (lowbox token) process may only create named pipes under \\?\pipe\LOCAL\. uv__unique_pipe_name generated names outside that prefix, so every CreateNamedPipe call failed with ERROR_ACCESS_DENIED, which uv__pipe_server treated as a name collision and retried with a new name forever, spinning at 100% CPU. Any uv_spawn with piped stdio or uv_pipe() hit this. - Prefix the generated names with LOCAL\. The names are internal and never surfaced (they embed a pointer value and the pid), and outside an AppContainer the prefix is just part of the name, so this is not observable. - Cap ERROR_ACCESS_DENIED retries in uv__pipe_server at one so a process that is denied access to the pipe namespace for other reasons fails instead of looping forever.
When the second GetFinalPathNameByHandleW call failed, the error was overwritten with ERROR_INVALID_HANDLE before being read by the caller, so the caller reported EBADF regardless of the real failure. Preserve the error across the buffer free instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three small commits that let libuv-based programs work inside a Windows AppContainer (lowbox token). Supersedes #4, which carried a
uv_fs_realpathdevice-mapping fallback (~400 lines) that the consumer can implement on its side instead; this PR is just the parts that have to live in libuv.What breaks today (verified on Windows 11 26200)
\\?\pipe\LOCAL\; anywhere elseCreateNamedPipereturnsERROR_ACCESS_DENIED.uv__unique_pipe_namegenerates\\?\pipe\uv\<ptr>-<pid>anduv__pipe_servertreatsERROR_ACCESS_DENIEDas a name collision and retries with a new name forever, so anyuv_spawnwith piped stdio (anduv_pipe()) busy-loops at 100% CPU.GetFinalPathNameByHandleW(VOLUME_NAME_DOS)is denied on every handle (the DOS-name translation opens the mount-manager device, which the sandbox blocks). When the second call infs__realpath_handlefails, the real error is overwritten withERROR_INVALID_HANDLE, so the caller reportsEBADFregardless of the cause.Changes
win: add uv_os_is_app_container()— returns1when the process token is an AppContainer token (GetTokenInformation(TokenIsAppContainer), cached withuv_once);0otherwise and on non-Windows. Declared inuv.h, documented inmisc.rst, exercised intest-platform-output. Internal callers useuv__is_app_container().win,pipe: make internal pipe names usable inside an AppContainer—uv__unique_pipe_namenow generates\\?\pipe\LOCAL\uv\<ptr>-<pid>. The names are internal (never surfaced; embed a pointer and the pid) and outside an AppContainer the prefix is just six literal bytes in the name, so this is not observable.uv__pipe_servernow allows oneERROR_ACCESS_DENIEDretry then fails, so a process denied the pipe namespace for any reason errors instead of looping.win,fs: preserve GetLastError in fs__realpath_handle— keep the real error across the buffer free instead of forcingERROR_INVALID_HANDLE.Not in this PR
uv_fs_realpathstill returnsEPERMinside an AppContainer (correctly now, rather thanEBADF). A working fallback requires building a device→drive-letter map, which is large and has no single-call solution; consumers that need it can implement it on top ofVOLUME_NAME_NTandFileIdInformation. Theuv_pipe_bind2ERROR_ACCESS_DENIED→UV_EADDRINUSEmapping is also left as-is: gating it onuv__is_app_container()would make a genuine name collision on aLOCAL\name inside an AppContainer reportEACCESinstead ofEADDRINUSE.