[PATCH 0/3] Some AF_UNIX fixes

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/3] Some AF_UNIX fixes

cygwin-patches mailing list
I'll push these in a few days if no one sees anything wrong.  Corinna,
please check them when you return.

Ken Brown (3):
  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

 winsup/cygwin/fhandler.cc             | 11 +++++++++--
 winsup/cygwin/fhandler_socket_unix.cc | 19 ++++++++++---------
 winsup/cygwin/path.cc                 | 27 ++++++++++++++++++---------
 winsup/cygwin/security.cc             |  4 +++-
 4 files changed, 40 insertions(+), 21 deletions(-)

--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 1/3] Cygwin: AF_UNIX: use FILE_OPEN_REPARSE_POINT when needed

cygwin-patches mailing list
There are two Windows system calls that currently fail with
STATUS_IO_REPARSE_TAG_NOT_HANDLED when called on an AF_UNIX socket: a
call to NtOpenFile in get_file_sd and a call to 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 |  4 +++-
 2 files changed, 12 insertions(+), 3 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..91fdc1e42 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -65,7 +65,9 @@ get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd,
    fh ? pc.init_reopen_attr (attr, fh)
       : pc.get_object_attr (attr, sec_none_nih),
    &io, 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 ();
--
2.28.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/3] Cygwin: fix handling of known reparse points that are not symlinks

cygwin-patches mailing list
In reply to this post by cygwin-patches mailing list
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

Reply | Threaded
Open this post in threaded view
|

[PATCH 3/3] Cygwin: always recognize AF_UNIX sockets as reparse points

cygwin-patches mailing list
In reply to this post by cygwin-patches mailing list
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 <w32api/winioctl.h>
 #include <asm/byteorder.h>
 #include <unistd.h>
@@ -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, &rgp->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