https://bugs.winehq.org/show_bug.cgi?id=43036
Bug ID: 43036 Summary: SetNamedPipeHandleState returns ERROR_ACCESS_DENIED when setting PIPE_NOWAIT Product: Wine Version: 2.7 Hardware: x86 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: dan-wine@berrange.com Distribution: ---
In GNULIB, there is code which tries to create an implementation of the POSIX pipe() method for Windows, using the methods _pipe, _get_osfhandle and SetNamedPipeHandleState. This code works when run on real windows systems (i've tried Win2k8 myself), but fails when run under Wine (I've tested versions 2.5 and 2.7 in Fedora), with ERROR_ACCESS_DENIED from the SetNamedPipeHandleState method
Since GNULIB code is fairly complex to follow I created this short demo program:
$ cat > demo.c <<EOF #include <sys/unistd.h> #include <stdio.h> #include <windows.h>
int nonblock(int fd) { HANDLE h = (HANDLE)_get_osfhandle(fd); char errbuf[1024]; DWORD state;
if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0) == 0) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errbuf, 1024, NULL);
fprintf(stderr, "Failed GetNamedPipeHandleState (%lu) %s", GetLastError(), errbuf); return -1; }
if ((state & PIPE_NOWAIT) != 0) { return 0; }
state |= PIPE_NOWAIT;
if (SetNamedPipeHandleState (h, &state, NULL, NULL) == 0) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errbuf, 1024, NULL);
fprintf(stderr, "Failed SetNamedPipeHandleState (%lu) %s", GetLastError(), errbuf); return -1; } return 0; }
int main(int argc, char **argv) { int fd[2];
if (_pipe(fd, 4096, 0) < 0) { fprintf(stderr, "Failed to create pipe\n"); return -1; }
if (nonblock(fd[0]) < 0){ fprintf(stderr, "Could not set non-blocking on fd[0]\n"); return -1; } if (nonblock(fd[1]) < 0){ fprintf(stderr, "Could not set non-blocking on fd[1]\n"); return -1; }
fprintf(stderr, "Created non-blocking pipe pair\n"); }
EOF
$ i686-w64-mingw32-gcc -Wall -mconsole -o pipe.exe pipe.c
$ ./pipe.exe fixme:winediag:start_process Wine Staging 2.7 is a testing version containing experimental patches. fixme:winediag:start_process Please mention your exact version when filing bug reports on winehq.org. fixme:sync:GetNamedPipeHandleStateW 0x2c 0x61f8f8 (nil) (nil) (nil) (nil) 0: semi-stub Failed SetNamedPipeHandleState (5) Access denied. Could not set non-blocking on fd[0]
Strangely, this only seems to fail on fd[0] - if I let it run on fd[1] it will work.
The original GNULIB code I hit the problem on is here:
http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/pipe2.c http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/nonblocking.c
The Fedora Wine 2.7 package I tested on was built with these sources:
SHA512 (wine-2.7.tar.xz) = 1e61b9a4aa1f5f42fb27d11d5254a9ba90f348ad9c4d1ddd4b5da47cd7de638290a20accf7447db9c0e4ced4c2144497cdf5fc906a5eac60e923dabb61f65d3a SHA512 (wine-2.7.tar.xz.sign) = b03f4376b10bd8ea66e5e6fc0862a4f948e009862a374677c326744b31c9d9fdcf1efd3b789149fcb6fe617f9c75b1b47d61f884e06e8c0fe16633a99911b667 SHA512 (wine-staging-2.7.tar.gz) = 0abc89af701ae1b95c0eb08e72894c7bc40bdfe792e05b8af9282eab8407bb90b7dfcd4eb3a193a88759ce5d6ea6c2aa9696cac2d744f543c92529bb0d2636ee
https://bugs.winehq.org/show_bug.cgi?id=43036
--- Comment #1 from dan-wine@berrange.com --- Investigating the code I've learnt that the '_pipe' function calls "CreatePipe". This method then uses NtCreateNamedPipeFile() to create the HANDLE for the read end of the pipe, passing GENERIC_READ for the access control bits, while using NtOpenFile() to create the HANDLE for the write end of the pipe, passing GENERIC_WRITE for the access control bits.
Next, the SetNamedPipeHandleState() method ultimately ends up calling set_named_pipe_info() in the wineserver. This method calls get_pipe_server_obj() passing FILE_WRITE_ATTRIBUTES for the required access control bits.
Since the read end of the pipe was opened with GENERIC_READ, get_pipe_server_obj() fails with ERROR_ACCESS_DENIED. So the read end of the pipe created by CreatePipe() will never be able to have attributes set.
Interestingly, when we call SetNamedPipeHandleState() with the write end of the pipe, the get_pipe_server_obj() fails because the handle is not actually a pipe, causing set_named_pipe_info() to fall back to get_handle_obj() passing 0 as the required access control check. Thus, even though the write end of the pipe has GENERIC_WRITE permissions (which include FILE_WRITE_ATTRIBUTES), this never gets checked !
I'm unclear on what the best way to fix all this is, but as a test I modified CreatePipe to set FILE_WRITE_ATTRIBUTES for the read pipe and that was sufficient to fix GNULIB (and libvirt) when running under Wine.
https://bugs.winehq.org/show_bug.cgi?id=43036
--- Comment #2 from dan-wine@berrange.com --- Created attachment 58190 --> https://bugs.winehq.org/attachment.cgi?id=58190 Pach that sets FILE_WRITE_ATTRIBUTES on the read handle in CreatePipe
This is the quick hack patch I used to try to fix the permissions check problem.
https://bugs.winehq.org/show_bug.cgi?id=43036
Michael Stefaniuc mstefani@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |patch CC| |mstefani@winehq.org
https://bugs.winehq.org/show_bug.cgi?id=43036
Jacek Caban jacek@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |8712db6f554349728663bff0ff2 | |b03334aa905b3 Resolution|--- |FIXED CC| |jacek@codeweavers.com Status|UNCONFIRMED |RESOLVED
--- Comment #3 from Jacek Caban jacek@codeweavers.com --- This commit should fix the problem: https://source.winehq.org/git/wine.git/commitdiff/8712db6f554349728663bff0ff...
Note that proper PIPE_NOWAIT is still not implemented, bug SetNamedPipeHandleState call should be fine.
https://bugs.winehq.org/show_bug.cgi?id=43036
Nikolay Sivov bunglehead@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|-unknown |kernel32
https://bugs.winehq.org/show_bug.cgi?id=43036
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #4 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 3.15.
https://bugs.winehq.org/show_bug.cgi?id=43036
Michael Stefaniuc mstefani@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Target Milestone|--- |3.0.x
https://bugs.winehq.org/show_bug.cgi?id=43036
Michael Stefaniuc mstefani@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Target Milestone|3.0.x |---
--- Comment #5 from Michael Stefaniuc mstefani@winehq.org --- Removing the 3.0.x milestone from bug fixes included in 3.0.4.