public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
* [PATCH 0/3] Fix fstat on FIFOs, part 2
@ 2021-02-18 17:13 Ken Brown
  2021-02-18 17:13 ` [PATCH 1/3] Cygwin: define fhandler_fifo::fstat Ken Brown
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ken Brown @ 2021-02-18 17:13 UTC (permalink / raw)
  To: cygwin-patches

The first patch fixes a bug, in which fstat on FIFOs sometimes used
pipe handles instead of file handles.

The second and third patches should improve the efficiency of fstat
and open on FIFOs.

Ken Brown (3):
  Cygwin: define fhandler_fifo::fstat
  Cygwin: fstat_helper: always use handle in call to get_file_attribute
  Cygwin: FIFO: temporarily keep a conv_handle in syscalls.cc:open

 winsup/cygwin/fhandler.h            |  1 +
 winsup/cygwin/fhandler_disk_file.cc |  3 +--
 winsup/cygwin/fhandler_fifo.cc      | 23 +++++++++++++++++++++++
 winsup/cygwin/syscalls.cc           | 22 +++++++++++++++++++---
 4 files changed, 44 insertions(+), 5 deletions(-)

-- 
2.30.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] Cygwin: define fhandler_fifo::fstat
  2021-02-18 17:13 [PATCH 0/3] Fix fstat on FIFOs, part 2 Ken Brown
@ 2021-02-18 17:13 ` Ken Brown
  2021-02-18 17:13 ` [PATCH 2/3] Cygwin: fstat_helper: always use handle in call to get_file_attribute Ken Brown
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ken Brown @ 2021-02-18 17:13 UTC (permalink / raw)
  To: cygwin-patches

Previously fstat on a FIFO would call fhandler_base::fstat.

The latter is not appropriate if fhandler_fifo::open has already been
called (and O_PATH is not set), for the following reason.  If a FIFO
has been opened as a writer or duplexer, then it has an io_handle that
is a pipe handle rather than a file handle.  fhandler_base::fstat will
use this handle and potentially return incorrect results.  If the FIFO
has been opened as a reader, then it has no io_handle, and a call to
fhandler_base::fstat will lead to a call to fhandler_base::open.
Opening the fhandler a second time can change it in undesired ways;
for example, it can modify the flags and status_flags.

The new fhandler_fifo::fstat avoids these problems by creating an
fhandler_disk_file and calling its fstat method in case
fhandler_fifo::open has already been called and O_PATH is not set.
---
 winsup/cygwin/fhandler.h       |  1 +
 winsup/cygwin/fhandler_fifo.cc | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index e457e2785..78d9c7984 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1510,6 +1510,7 @@ public:
   ssize_t __reg3 raw_write (const void *ptr, size_t ulen);
   void fixup_after_fork (HANDLE);
   void fixup_after_exec ();
+  int __reg2 fstat (struct stat *buf);
   int __reg2 fstatvfs (struct statvfs *buf);
   select_record *select_read (select_stuff *);
   select_record *select_write (select_stuff *);
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index 8b67037cb..365f14053 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -1494,6 +1494,29 @@ errout:
   len = (size_t) -1;
 }
 
+int __reg2
+fhandler_fifo::fstat (struct stat *buf)
+{
+  if (reader || writer || duplexer)
+    {
+      /* fhandler_fifo::open has been called, and O_PATH is not set.
+	 We don't want to call fhandler_base::fstat.  In the writer
+	 and duplexer cases we have a handle, but it's a pipe handle
+	 rather than a file handle, so it's not suitable for stat.  In
+	 the reader case we don't have a handle, but
+	 fhandler_base::fstat would call fhandler_base::open, which
+	 would modify the flags and status_flags. */
+      fhandler_disk_file fh (pc);
+      fh.get_device () = FH_FS;
+      int res = fh.fstat (buf);
+      buf->st_dev = buf->st_rdev = dev ();
+      buf->st_mode = dev ().mode ();
+      buf->st_size = 0;
+      return res;
+    }
+  return fhandler_base::fstat (buf);
+}
+
 int __reg2
 fhandler_fifo::fstatvfs (struct statvfs *sfs)
 {
-- 
2.30.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/3] Cygwin: fstat_helper: always use handle in call to get_file_attribute
  2021-02-18 17:13 [PATCH 0/3] Fix fstat on FIFOs, part 2 Ken Brown
  2021-02-18 17:13 ` [PATCH 1/3] Cygwin: define fhandler_fifo::fstat Ken Brown
@ 2021-02-18 17:13 ` Ken Brown
  2021-02-18 17:13 ` [PATCH 3/3] Cygwin: FIFO: temporarily keep a conv_handle in syscalls.cc:open Ken Brown
  2021-02-19 17:07 ` [PATCH 0/3] Fix fstat on FIFOs, part 2 Corinna Vinschen
  3 siblings, 0 replies; 5+ messages in thread
From: Ken Brown @ 2021-02-18 17:13 UTC (permalink / raw)
  To: cygwin-patches

Previously, the call to get_file_attribute for FIFOs set the first
argument to NULL instead of the handle h returned by get_stat_handle,
thereby forcing the file to be opened for fetching the security
descriptor in get_file_sd().  This was done because h might have been
a pipe handle rather than a file handle, and its permissions would not
necessarily reflect those of the file.

That situation can no longer occur with the new fhandler_fifo::fstat
introduced in the previous commit.
---
 winsup/cygwin/fhandler_disk_file.cc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index ef9171bbf..6170427b0 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -475,8 +475,7 @@ fhandler_base::fstat_helper (struct stat *buf)
   else if (pc.issocket ())
     buf->st_mode = S_IFSOCK;
 
-  if (!get_file_attribute (is_fs_special () && !pc.issocket () ? NULL : h, pc,
-			   &buf->st_mode, &buf->st_uid, &buf->st_gid))
+  if (!get_file_attribute (h, pc, &buf->st_mode, &buf->st_uid, &buf->st_gid))
     {
       /* If read-only attribute is set, modify ntsec return value */
       if (::has_attribute (attributes, FILE_ATTRIBUTE_READONLY)
-- 
2.30.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/3] Cygwin: FIFO: temporarily keep a conv_handle in syscalls.cc:open
  2021-02-18 17:13 [PATCH 0/3] Fix fstat on FIFOs, part 2 Ken Brown
  2021-02-18 17:13 ` [PATCH 1/3] Cygwin: define fhandler_fifo::fstat Ken Brown
  2021-02-18 17:13 ` [PATCH 2/3] Cygwin: fstat_helper: always use handle in call to get_file_attribute Ken Brown
@ 2021-02-18 17:13 ` Ken Brown
  2021-02-19 17:07 ` [PATCH 0/3] Fix fstat on FIFOs, part 2 Corinna Vinschen
  3 siblings, 0 replies; 5+ messages in thread
From: Ken Brown @ 2021-02-18 17:13 UTC (permalink / raw)
  To: cygwin-patches

When a FIFO is opened, syscalls.cc:open always calls fstat on the
newly-created fhandler_fifo.  This results from a call to
device_access_denied.

To speed-up this fstat call, and therefore the open(2) call, use
PC_KEEP_HANDLE when the fhandler is created.  The resulting
conv_handle is retained until after the fstat call if the fhandler is
a FIFO; otherwise, it is closed immediately.
---
 winsup/cygwin/syscalls.cc | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 32a155a1c..460fe6801 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1487,8 +1487,15 @@ open (const char *unix_path, int flags, ...)
 	  opt |= PC_CTTY;
 	}
 
+      /* If we're opening a FIFO, we will call device_access_denied
+	 below.  This leads to a call to fstat, which can use the
+	 path_conv handle. */
+      opt |= PC_KEEP_HANDLE;
       if (!(fh = build_fh_name (unix_path, opt, stat_suffixes)))
 	__leave;		/* errno already set */
+      opt &= ~PC_KEEP_HANDLE;
+      if (!fh->isfifo ())
+	fh->pc.close_conv_handle ();
       if ((flags & O_NOFOLLOW) && fh->issymlink () && !(flags & O_PATH))
 	{
 	  set_errno (ELOOP);
@@ -1555,9 +1562,18 @@ open (const char *unix_path, int flags, ...)
 	  delete fh;
 	  fh = fh_file;
 	}
-      else if ((fh->is_fs_special () && fh->device_access_denied (flags))
-	       || !fh->open_with_arch (flags, mode & 07777))
-	__leave;		/* errno already set */
+      else
+	{
+	  if (fh->is_fs_special ())
+	    {
+	      if (fh->device_access_denied (flags))
+		__leave;	/* errno already set */
+	      else if (fh->isfifo ())
+		fh->pc.close_conv_handle ();
+	    }
+	  if (!fh->open_with_arch (flags, mode & 07777))
+	    __leave;		/* errno already set */
+	}
       /* Move O_TMPFILEs to the bin to avoid blocking the parent dir. */
       if ((flags & O_TMPFILE) && !fh->pc.isremote ())
 	try_to_bin (fh->pc, fh->get_handle (), DELETE,
-- 
2.30.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] Fix fstat on FIFOs, part 2
  2021-02-18 17:13 [PATCH 0/3] Fix fstat on FIFOs, part 2 Ken Brown
                   ` (2 preceding siblings ...)
  2021-02-18 17:13 ` [PATCH 3/3] Cygwin: FIFO: temporarily keep a conv_handle in syscalls.cc:open Ken Brown
@ 2021-02-19 17:07 ` Corinna Vinschen
  3 siblings, 0 replies; 5+ messages in thread
From: Corinna Vinschen @ 2021-02-19 17:07 UTC (permalink / raw)
  To: cygwin-patches

On Feb 18 12:13, Ken Brown via Cygwin-patches wrote:
> The first patch fixes a bug, in which fstat on FIFOs sometimes used
> pipe handles instead of file handles.
> 
> The second and third patches should improve the efficiency of fstat
> and open on FIFOs.
> 
> Ken Brown (3):
>   Cygwin: define fhandler_fifo::fstat
>   Cygwin: fstat_helper: always use handle in call to get_file_attribute
>   Cygwin: FIFO: temporarily keep a conv_handle in syscalls.cc:open
> 
>  winsup/cygwin/fhandler.h            |  1 +
>  winsup/cygwin/fhandler_disk_file.cc |  3 +--
>  winsup/cygwin/fhandler_fifo.cc      | 23 +++++++++++++++++++++++
>  winsup/cygwin/syscalls.cc           | 22 +++++++++++++++++++---
>  4 files changed, 44 insertions(+), 5 deletions(-)
> 
> -- 
> 2.30.0

LGTM, please push.


Thanks,
Corinna

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-02-19 17:07 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-18 17:13 [PATCH 0/3] Fix fstat on FIFOs, part 2 Ken Brown
2021-02-18 17:13 ` [PATCH 1/3] Cygwin: define fhandler_fifo::fstat Ken Brown
2021-02-18 17:13 ` [PATCH 2/3] Cygwin: fstat_helper: always use handle in call to get_file_attribute Ken Brown
2021-02-18 17:13 ` [PATCH 3/3] Cygwin: FIFO: temporarily keep a conv_handle in syscalls.cc:open Ken Brown
2021-02-19 17:07 ` [PATCH 0/3] Fix fstat on FIFOs, part 2 Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).