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

commit 782b3385309d20cc60f6a41806091ca8430748f2
Author: Corinna Vinschen <[email protected]>
Date:   Tue May 25 22:03:36 2021 +0200

    Cygwin: path_conv: fix mqueue path check
    
    The check for a file or dir within /dev/mqueue is accidentally using
    the incoming path, which could be a relative path.  Make sure to
    restore the absolute POSIX path in path_copy and only then test the
    path.
    
    Also, move the actual check for a valid path below /dev/mqueue into
    the fhandler_mqueue class.
    
    Signed-off-by: Corinna Vinschen <[email protected]>

Diff:
---
 winsup/cygwin/fhandler.h         |  2 ++
 winsup/cygwin/fhandler_mqueue.cc | 15 +++++++++++++++
 winsup/cygwin/mqueue_types.h     |  3 +++
 winsup/cygwin/path.cc            | 22 +++++++---------------
 4 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 5e298a82f..bd63933c2 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -3111,6 +3111,8 @@ class fhandler_mqueue: public fhandler_disk_file
   off_t filesize;
   off_t position;
 
+  bool valid_path ();
+
   struct mq_info *_mqinfo (SIZE_T, mode_t, int, bool);
 
   struct mq_info *mqinfo_create (struct mq_attr *, mode_t, int);
diff --git a/winsup/cygwin/fhandler_mqueue.cc b/winsup/cygwin/fhandler_mqueue.cc
index 04a6c3611..f074474d7 100644
--- a/winsup/cygwin/fhandler_mqueue.cc
+++ b/winsup/cygwin/fhandler_mqueue.cc
@@ -34,9 +34,24 @@ fhandler_mqueue::~fhandler_mqueue ()
   cfree (filebuf);
 }
 
+bool
+fhandler_mqueue::valid_path ()
+{
+  const char *posix_basename = get_name () + MQ_LEN;
+  size_t len = strlen (posix_basename);
+  if (len > 0 && len <= NAME_MAX && !strpbrk (posix_basename, "/\\"))
+    return true;
+  return false;
+}
+
 int
 fhandler_mqueue::open (int flags, mode_t mode)
 {
+  if (!valid_path ())
+    {
+      set_errno (EINVAL);
+      return 0;
+    }
   /* FIXME: reopen by handle semantics missing yet */
   flags &= ~(O_NOCTTY | O_PATH | O_BINARY | O_TEXT);
   return mq_open (flags, mode, NULL);
diff --git a/winsup/cygwin/mqueue_types.h b/winsup/cygwin/mqueue_types.h
index 4d0d910e4..1e4fe127e 100644
--- a/winsup/cygwin/mqueue_types.h
+++ b/winsup/cygwin/mqueue_types.h
@@ -10,6 +10,9 @@ details. */
 
 #define MQI_MAGIC      0x98765432UL
 
+#define MQ_PATH "/dev/mqueue/"
+#define MQ_LEN  (sizeof (MQ_PATH) - 1)
+
 /* The mq_attr structure is defined using long datatypes per POSIX.
    The mq_fattr is the in-file representation of the mq_attr struct.
    Originally created this way for 32/64 bit interoperability, this
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 53cdc282d..6a07f0d06 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1188,6 +1188,10 @@ path_conv::check (const char *src, unsigned opt,
          return;
        }
 
+      /* Restore last path component */
+      if (tail < path_end && tail > path_copy + 1)
+       *tail = '/';
+
       if (dev.isfs ())
        {
          /* If FS hasn't been checked already in symlink_info::check,
@@ -1227,16 +1231,8 @@ path_conv::check (const char *src, unsigned opt,
            set_exec (0);
 
          /* FIXME: bad hack alert!!!  We need a better solution */
-
-#define MQ_PATH "/dev/mqueue/"
-#define MQ_LEN  (sizeof (MQ_PATH) - 1)
-
-         if (!strncmp (src, MQ_PATH, MQ_LEN))
-           {
-             size_t len = strlen (src + MQ_LEN);
-             if (len > 0 && len <= NAME_MAX && !strpbrk (src + MQ_LEN, "/\\"))
-               dev.parse (FH_MQUEUE);
-           }
+         if (!strncmp (path_copy, MQ_PATH, MQ_LEN) && path_copy[MQ_LEN])
+           dev.parse (FH_MQUEUE);
        }
 
       if (opt & PC_NOFULL)
@@ -1270,11 +1266,7 @@ path_conv::check (const char *src, unsigned opt,
        path_flags |= PATH_CTTY;
 
       if (opt & PC_POSIX)
-       {
-         if (tail < path_end && tail > path_copy + 1)
-           *tail = '/';
-         set_posix (path_copy);
-       }
+       set_posix (path_copy);
 
 #if 0
       if (!error)

Reply via email to