[PATCH v2 5/6] Cygwin: AF_UNIX: listen_pipe: check for STATUS_SUCCESS
A successful connection can be indicated by STATUS_SUCCESS or STATUS_PIPE_CONNECTED. Previously we were checking only for the latter. --- winsup/cygwin/fhandler_socket_unix.cc | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 0ae7fe125..1a9532fe5 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -1064,6 +1064,7 @@ fhandler_socket_unix::listen_pipe () IO_STATUS_BLOCK io; HANDLE evt = NULL; DWORD waitret = WAIT_OBJECT_0; + int ret = -1; io.Status = STATUS_PENDING; if (!is_nonblocking () && !(evt = create_event ())) @@ -1085,9 +1086,11 @@ fhandler_socket_unix::listen_pipe () set_errno (EINTR); else if (status == STATUS_PIPE_LISTENING) set_errno (EAGAIN); - else if (status != STATUS_PIPE_CONNECTED) + else if (status == STATUS_SUCCESS || status == STATUS_PIPE_CONNECTED) +ret = 0; + else __seterrno_from_nt_status (status); - return (status == STATUS_PIPE_CONNECTED) ? 0 : -1; + return ret; } ULONG -- 2.28.0
[PATCH v2 4/6] Cygwin: AF_UNIX: socket: set the O_RDWR flag
--- winsup/cygwin/fhandler_socket_unix.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 429aa8a90..0ae7fe125 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -1366,6 +1366,7 @@ fhandler_socket_unix::socket (int af, int type, int protocol, int flags) wmem (262144); set_addr_family (AF_UNIX); set_socket_type (type); + set_flags (O_RDWR | O_BINARY); if (flags & SOCK_NONBLOCK) set_nonblocking (true); if (flags & SOCK_CLOEXEC) -- 2.28.0
[PATCH v2 6/6] Cygwin: AF_UNIX: open_pipe: call recv_peer_info
If open_pipe is called with xchg_sock_info true, call recv_peer_info in addition to send_sock_info. --- winsup/cygwin/fhandler_socket_unix.cc | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index 1a9532fe5..9f7f86c47 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -941,7 +941,11 @@ fhandler_socket_unix::open_pipe (PUNICODE_STRING pipe_name, bool xchg_sock_info) { set_handle (ph); if (xchg_sock_info) - send_sock_info (false); + { + /* FIXME: Should we check for errors? */ + send_sock_info (false); + recv_peer_info (); + } } return status; } -- 2.28.0
[PATCH v2 0/6] Some AF_UNIX fixes
I'm about to push these. Corinna, please check them when you return. The only difference between v2 and v1 is that there are a few more fixes. I'm trying to help get the AF_UNIX development going again. I'm mostly working on the topic/af_unix branch. But when I find bugs that exist on master, I'll push those to master and then merge master to topic/af_unix. So far what I have on that branch locally (to be pushed shortly) is an implementation of fhandler_socket_unix::read, which I've tested by running the srver/client programs from Section 57.2 of Kerrisk's book, "The Linux Programming Interface". Ken Brown (6): Cygwin: AF_UNIX: use FILE_OPEN_REPARSE_POINT when needed Cygwin: fix handling of known reparse points that are not symlinks Cygwin: always recognize AF_UNIX sockets as reparse points Cygwin: AF_UNIX: socket: set the O_RDWR flag Cygwin: AF_UNIX: listen_pipe: check for STATUS_SUCCESS Cygwin: AF_UNIX: open_pipe: call recv_peer_info winsup/cygwin/fhandler.cc | 11 -- winsup/cygwin/fhandler_socket_unix.cc | 31 +-- winsup/cygwin/path.cc | 27 +++ winsup/cygwin/security.cc | 8 +-- 4 files changed, 53 insertions(+), 24 deletions(-) -- 2.28.0
[PATCH v2 3/6] Cygwin: always recognize AF_UNIX sockets as reparse points
If __WITH_AF_UNIX is defined when Cygwin is built, then a named AF_UNIX socket is represented by a reparse point with a Cygwin-specific tag and GUID. Make such files recognizable as reparse points (but not as sockets) even if __WITH_AF_UNIX is not defined. That way utilities such as 'ls' and 'rm' still behave reasonably. This requires two changes: - Define the GUID __cygwin_socket_guid unconditionally. - Make check_reparse_point_target return PATH_REP on a reparse point of this type if __WITH_AF_UNIX is not defined. --- winsup/cygwin/fhandler_socket_unix.cc | 17 + winsup/cygwin/path.cc | 10 ++ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/winsup/cygwin/fhandler_socket_unix.cc b/winsup/cygwin/fhandler_socket_unix.cc index d7bb1090e..429aa8a90 100644 --- a/winsup/cygwin/fhandler_socket_unix.cc +++ b/winsup/cygwin/fhandler_socket_unix.cc @@ -8,9 +8,17 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +#include "winsup.h" + +GUID __cygwin_socket_guid = { + .Data1 = 0xefc1714d, + .Data2 = 0x7b19, + .Data3 = 0x4407, + .Data4 = { 0xba, 0xb3, 0xc5, 0xb1, 0xf9, 0x2c, 0xb8, 0x8c } +}; + #ifdef __WITH_AF_UNIX -#include "winsup.h" #include #include #include @@ -124,13 +132,6 @@ class af_unix_pkt_hdr_t (void *)(((PBYTE)(_p)) + AF_UNIX_PKT_OFFSETOF_DATA (_p)); \ }) -GUID __cygwin_socket_guid = { - .Data1 = 0xefc1714d, - .Data2 = 0x7b19, - .Data3 = 0x4407, - .Data4 = { 0xba, 0xb3, 0xc5, 0xb1, 0xf9, 0x2c, 0xb8, 0x8c } -}; - /* Some error conditions on pipes have multiple status codes, unfortunately. */ #define STATUS_PIPE_NO_INSTANCE_AVAILABLE(status) \ ({ NTSTATUS _s = (status); \ diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 2e3208d2d..4f5f03a76 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2476,8 +2476,7 @@ check_reparse_point_string (PUNICODE_STRING subst) /* Return values: <0: Negative errno. 0: Not a reparse point recognized by us. ->0: PATH_SYMLINK | PATH_REP for symlink or directory mount point, -PATH_SOCKET | PATH_REP for AF_UNIX socket. +>0: Path flags for a recognized reparse point, always including PATH_REP. */ int check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp, @@ -2618,15 +2617,18 @@ check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp, } return -EIO; } -#ifdef __WITH_AF_UNIX else if (rp->ReparseTag == IO_REPARSE_TAG_CYGUNIX) { PREPARSE_GUID_DATA_BUFFER rgp = (PREPARSE_GUID_DATA_BUFFER) rp; if (memcmp (CYGWIN_SOCKET_GUID, >ReparseGuid, sizeof (GUID)) == 0) +#ifdef __WITH_AF_UNIX return PATH_SOCKET | PATH_REP; +#else +/* Recognize this as a reparse point but not as a socket. */ +return PATH_REP; +#endif } -#endif /* __WITH_AF_UNIX */ return 0; } -- 2.28.0
[PATCH v2 2/6] Cygwin: fix handling of known reparse points that are not symlinks
Commit aa467e6e, "Cygwin: add AF_UNIX reparse points to path handling", changed check_reparse_point_target so that it could return a positive value on a known reparse point that is not a symlink. But some of the code in check_reparse_point that handles this positive return value was executed unconditionally, when it should have been executed only for symlinks. As a result, posixify could be called on a buffer containing garbage, and check_reparse_point could erroneously return a positive value on a non-symlink. This is now fixed so that posixify is only called if the reparse point is a symlink, and check_reparse_point returns 0 if the reparse point is not a symlink. Also fix symlink_info::check to handle this last case, in which check_reparse_point returns 0 on a known reparse point. --- winsup/cygwin/path.cc | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 638f1adce..2e3208d2d 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2655,11 +2655,15 @@ symlink_info::check_reparse_point (HANDLE h, bool remote) /* ret is > 0, so it's a known reparse point, path in symbuf. */ path_flags |= ret; if (ret & PATH_SYMLINK) -sys_wcstombs (srcbuf, SYMLINK_MAX + 7, symbuf.Buffer, - symbuf.Length / sizeof (WCHAR)); - /* A symlink is never a directory. */ - fileattr &= ~FILE_ATTRIBUTE_DIRECTORY; - return posixify (srcbuf); +{ + sys_wcstombs (srcbuf, SYMLINK_MAX + 7, symbuf.Buffer, + symbuf.Length / sizeof (WCHAR)); + /* A symlink is never a directory. */ + fileattr &= ~FILE_ATTRIBUTE_DIRECTORY; + return posixify (srcbuf); +} + else +return 0; } int @@ -3274,6 +3278,9 @@ restart: &= ~FILE_ATTRIBUTE_DIRECTORY; break; } + else if (res == 0 && (path_flags & PATH_REP)) + /* Known reparse point but not a symlink. */ + goto file_not_symlink; else { /* Volume moint point or unrecognized reparse point type. -- 2.28.0
[PATCH v2 1/6] Cygwin: AF_UNIX: use FILE_OPEN_REPARSE_POINT when needed
The following Windows system calls currently fail with STATUS_IO_REPARSE_TAG_NOT_HANDLED when called on an AF_UNIX socket: - NtOpenFile in get_file_sd - NtOpenFile in set_file_sd - NtCreateFile in fhandler_base::open Fix this by adding the FILE_OPEN_REPARSE_POINT flag to those calls when the file is a known reparse point. --- winsup/cygwin/fhandler.cc | 11 +-- winsup/cygwin/security.cc | 8 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 82b21aff4..5dbbd4068 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -620,13 +620,20 @@ fhandler_base::open (int flags, mode_t mode) else create_disposition = (flags & O_CREAT) ? FILE_OPEN_IF : FILE_OPEN; - if (get_device () == FH_FS) + if (get_device () == FH_FS +#ifdef __WITH_AF_UNIX + || get_device () == FH_UNIX +#endif + ) { - /* Add the reparse point flag to known repares points, otherwise we + /* Add the reparse point flag to known reparse points, otherwise we open the target, not the reparse point. This would break lstat. */ if (pc.is_known_reparse_point ()) options |= FILE_OPEN_REPARSE_POINT; +} + if (get_device () == FH_FS) +{ /* O_TMPFILE files are created with delete-on-close semantics, as well as with FILE_ATTRIBUTE_TEMPORARY. The latter speeds up file access, because the OS tries to keep the file in memory as much as possible. diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 468b05164..d48526619 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -65,7 +65,9 @@ get_file_sd (HANDLE fh, path_conv , security_descriptor , fh ? pc.init_reopen_attr (attr, fh) : pc.get_object_attr (attr, sec_none_nih), , FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT); + FILE_OPEN_FOR_BACKUP_INTENT + | pc.is_known_reparse_point () + ? FILE_OPEN_REPARSE_POINT : 0); if (!NT_SUCCESS (status)) { sd.free (); @@ -232,7 +234,9 @@ set_file_sd (HANDLE fh, path_conv , security_descriptor , bool is_chown) : pc.get_object_attr (attr, sec_none_nih), , FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT); + FILE_OPEN_FOR_BACKUP_INTENT + | pc.is_known_reparse_point () + ? FILE_OPEN_REPARSE_POINT : 0); if (!NT_SUCCESS (status)) { fh = NULL; -- 2.28.0