[newlib-cygwin] Cygwin: POSIX msg queues: move handling of memory map into fhandler

Corinna Vinschen corinna@sourceware.org
Fri May 21 13:34:32 GMT 2021


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=723f38b10af6d465ccdd41af408e8c3d84331033

commit 723f38b10af6d465ccdd41af408e8c3d84331033
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Fri May 21 15:25:37 2021 +0200

    Cygwin: POSIX msg queues: move handling of memory map into fhandler
    
    This encapsulated creation, duplication, and closing of all
    Windows objects connected to the message queue in the fhandler.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler.h         | 11 +++++-
 winsup/cygwin/fhandler_mqueue.cc | 40 ++++++++++++++++++----
 winsup/cygwin/posix_ipc.cc       | 72 +++++-----------------------------------
 3 files changed, 52 insertions(+), 71 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index b0618963d..0ffc5a697 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -3107,6 +3107,8 @@ class fhandler_mqueue: public fhandler_base
 {
   struct mq_info mqi;
 
+  struct mq_info *_mqinfo (HANDLE, SIZE_T, mode_t, int, bool);
+
 public:
   fhandler_mqueue ();
   fhandler_mqueue (void *) {}
@@ -3116,7 +3118,14 @@ public:
 
   char *get_proc_fd_name (char *);
 
-  struct mq_info *mqinfo (int8_t *, HANDLE, size_t, mode_t, int);
+  struct mq_info *mqinfo_create (HANDLE _h, SIZE_T _s, mode_t _m, int _f)
+  {
+    return _mqinfo (_h, _s, _m, _f, false);
+  }
+  struct mq_info *mqinfo_open (HANDLE _h, SIZE_T _s, mode_t _m, int _f)
+  {
+    return _mqinfo (_h, _s, _m, _f, true);
+  }
   struct mq_info *mqinfo () { return &mqi; }
 
   void fixup_after_fork (HANDLE);
diff --git a/winsup/cygwin/fhandler_mqueue.cc b/winsup/cygwin/fhandler_mqueue.cc
index d068d2ad5..06ccf2f1e 100644
--- a/winsup/cygwin/fhandler_mqueue.cc
+++ b/winsup/cygwin/fhandler_mqueue.cc
@@ -20,17 +20,19 @@ fhandler_mqueue::fhandler_mqueue () :
 }
 
 struct mq_info *
-fhandler_mqueue::mqinfo (int8_t *mptr, HANDLE sect, size_t size, mode_t mode,
-			 int flags)
+fhandler_mqueue::_mqinfo (HANDLE fh, SIZE_T filesize, mode_t mode, int flags,
+			  bool just_open)
 {
-  WCHAR buf[MAX_PATH];
+  WCHAR buf[NAME_MAX + sizeof ("mqueue/XXX")];
   UNICODE_STRING uname;
   OBJECT_ATTRIBUTES attr;
   NTSTATUS status;
+  LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize };
+  PVOID mptr = NULL;
 
-  mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr;
-  mqinfo ()->mqi_sect = sect;
-  mqinfo ()->mqi_sectsize = size;
+  /* Set sectsize prior to using filesize in NtMapViewOfSection.  It will
+     get pagesize aligned, which breaks the next NtMapViewOfSection in fork. */
+  mqinfo ()->mqi_sectsize = filesize;
   mqinfo ()->mqi_mode = mode;
   mqinfo ()->mqi_flags = flags;
 
@@ -60,10 +62,36 @@ fhandler_mqueue::mqinfo (int8_t *mptr, HANDLE sect, size_t size, mode_t mode,
   if (!NT_SUCCESS (status))
     goto err;
 
+  InitializeObjectAttributes (&attr, NULL, 0, NULL, NULL);
+  status = NtCreateSection (&mqinfo ()->mqi_sect, SECTION_ALL_ACCESS, &attr,
+			    &fsiz, PAGE_READWRITE, SEC_COMMIT, fh);
+  if (!NT_SUCCESS (status))
+    goto err;
+
+  status = NtMapViewOfSection (mqinfo ()->mqi_sect, NtCurrentProcess (),
+			       &mptr, 0, filesize, NULL, &filesize,
+			       ViewShare, 0, PAGE_READWRITE);
+  if (!NT_SUCCESS (status))
+    goto err;
+
+  mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr;
+
+  /* Special problem on Cygwin.  /dev/mqueue is just a simple dir,
+     so there's a chance normal files are created in there. */
+  if (just_open && mqinfo ()->mqi_hdr->mqh_magic != MQI_MAGIC)
+    {
+      status = STATUS_ACCESS_DENIED;
+      goto err;
+    }
+
   mqinfo ()->mqi_magic = MQI_MAGIC;
   return mqinfo ();
 
 err:
+  if (mqinfo ()->mqi_sect)
+    NtClose (mqinfo ()->mqi_sect);
+  if (mqinfo ()->mqi_waitrecv)
+    NtClose (mqinfo ()->mqi_waitrecv);
   if (mqinfo ()->mqi_waitsend)
     NtClose (mqinfo ()->mqi_waitsend);
   if (mqinfo ()->mqi_lock)
diff --git a/winsup/cygwin/posix_ipc.cc b/winsup/cygwin/posix_ipc.cc
index 7038d1146..fc483bdc8 100644
--- a/winsup/cygwin/posix_ipc.cc
+++ b/winsup/cygwin/posix_ipc.cc
@@ -318,35 +318,6 @@ struct mq_attr defattr = { 0, 10, 8192, 0 };	/* Linux defaults. */
 extern "C" off_t lseek64 (int, off_t, int);
 extern "C" void *mmap64 (void *, size_t, int, int, int, off_t);
 
-static int8_t *
-_map_file (int fd, SIZE_T filesize, HANDLE &secth)
-{
-  OBJECT_ATTRIBUTES oa;
-  LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize };
-  NTSTATUS status;
-  PVOID addr = NULL;
-
-  secth = NULL;
-  InitializeObjectAttributes (&oa, NULL, 0, NULL, NULL);
-  status = NtCreateSection (&secth, SECTION_ALL_ACCESS, &oa, &fsiz,
-			    PAGE_READWRITE, SEC_COMMIT,
-			    (HANDLE) _get_osfhandle (fd));
-  if (NT_SUCCESS (status))
-    {
-      status = NtMapViewOfSection (secth, NtCurrentProcess (), &addr, 0,
-				   filesize, NULL, &filesize,
-				   ViewShare, 0, PAGE_READWRITE);
-      if (!NT_SUCCESS (status))
-	{
-	  NtClose (secth);
-	  secth = NULL;
-	}
-    }
-  if (!NT_SUCCESS (status))
-    __seterrno_from_nt_status (status);
-  return (int8_t *) addr;
-}
-
 extern "C" mqd_t
 mq_open (const char *name, int oflag, ...)
 {
@@ -355,10 +326,9 @@ mq_open (const char *name, int oflag, ...)
   off_t filesize = 0;
   va_list ap;
   mode_t mode;
-  HANDLE secth;
-  int8_t *mptr = NULL;
-  fhandler_mqueue *fh;
+  fhandler_mqueue *fh = NULL;
   struct stat statbuff;
+  int8_t *mptr = NULL;
   struct mq_hdr *mqhdr;
   struct msg_hdr *msghdr;
   struct mq_attr *attr;
@@ -414,11 +384,6 @@ mq_open (const char *name, int oflag, ...)
 	  if (ftruncate64 (fd, filesize) == -1)
 	    __leave;
 
-	  /* Memory map the file */
-	  mptr = _map_file (fd, filesize, secth);
-	  if (!mptr)
-	    __leave;
-
 	  /* Create file descriptor for mqueue */
 	  cygheap_fdnew fdm;
 
@@ -429,12 +394,14 @@ mq_open (const char *name, int oflag, ...)
 	    __leave;
 	  fdm = fh;
 
-	  mqinfo = fh->mqinfo (mptr, secth, filesize, mode, nonblock);
+	  mqinfo = fh->mqinfo_create ((HANDLE) _get_osfhandle (fd), filesize,
+				      mode, nonblock);
 	  if (!mqinfo)
 	    __leave;
 
 	  /* Initialize header at beginning of file */
 	  /* Create free list with all messages on it */
+	  mptr = (int8_t *) mqinfo->mqi_hdr;
 	  mqhdr = mqinfo->mqi_hdr;
 	  mqhdr->mqh_attr.mq_flags = 0;
 	  mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
@@ -493,25 +460,6 @@ mq_open (const char *name, int oflag, ...)
 	  __leave;
 	}
 
-      filesize = statbuff.st_size;
-      mptr = _map_file (fd, filesize, secth);
-      if (!mptr)
-	__leave;
-
-      close (fd);
-      fd = -1;
-
-      mqhdr = (struct mq_hdr *) mptr;
-      if (mqhdr->mqh_magic != MQI_MAGIC)
-	{
-	  system_printf (
-    "Old message queue \"%s\" detected!\n"
-    "This file is not usable as message queue anymore due to changes in the "
-    "internal file layout.  Please remove the file and try again.", mqname);
-	  set_errno (EACCES);
-	  __leave;
-	}
-
       /* Create file descriptor for mqueue */
       cygheap_fdnew fdm;
 
@@ -522,11 +470,12 @@ mq_open (const char *name, int oflag, ...)
 	__leave;
       fdm = fh;
 
-      mqinfo = fh->mqinfo (mptr, secth, filesize, statbuff.st_mode,
-			   nonblock);
+      mqinfo = fh->mqinfo_open ((HANDLE) _get_osfhandle (fd), statbuff.st_size,
+				statbuff.st_mode, nonblock);
       if (!mqinfo)
 	__leave;
 
+      close (fd);
       return (mqd_t) fdm;
     }
   __except (EFAULT) {}
@@ -535,11 +484,6 @@ mq_open (const char *name, int oflag, ...)
   save_errno save;
   if (created)
     unlink (mqname);
-  if (mptr)
-    {
-      NtUnmapViewOfSection (NtCurrentProcess (), mptr);
-      NtClose (secth);
-    }
   if (fd >= 0)
     close (fd);
   return (mqd_t) -1;


More information about the Cygwin-cvs mailing list