Re: [PATCH 0/2] Fix a bad case of absolute path handling

2021-11-10 Thread Ken Brown

On 11/10/2021 3:32 PM, corinna-cyg...@cygwin.com wrote:

From: Corinna Vinschen 

As I told Takashi in PM, I will try to more often send patches to the
cygwin-patches ML before pushing them, so there's a chance to chime in.


LGTM.


This patch series is supposed to address the `rm -rf' problem reported
in https://cygwin.com/pipermail/cygwin/2021-November/249837.html

It was always frustrating, having to allow DOS drive letter paths for
backward compatibility.  This here is another case of ambiguity,
triggered by the `isabspath' macro handling "X:" as absolute path, even
without the trailing slash or backslash.

Check out the 2nd patch for a more detailed description.

While at it, I wonder if we might have a chance to fix these ambiguities
in a better way.  For instance, consider this:

   $ mkdir -p test/c:
   $ cd test

As non-admin:

   $ touch c:/foo
   touch: cannot touch 'c:/foo': Permission denied

As admin, even worse:

   $ touch c:/foo
   $ ls /cygdrive/c/foo
   foo

As long as we support DOS paths as input, I have a hard time to see how
to fix this, but maybe we can at least minimize the ambiguity somehow.


I can't immediately think of anything.  But is it really impossible to phase out 
DOS path support over a period of time?  We could start with a HEADS-UP, asking 
for comments, then a deprecation announcement, then something like the old 
dosfilewarning option, then a more forceful warning that can't be turned off, 
and finally removal of support.  This could be done over a period of several 
years (not sure how many).


We could also put lines like

  # C:/ on /c type ntfs (binary,posix=0)

into the default /etc/fstab.

Ken


[PATCH 2/2] Cygwin: introduce isabspath_strict macro

2021-11-10 Thread corinna-cygwin
From: Corinna Vinschen 

isabspath handles a path "X:", without trailing slas or backslash,
as absolute path.  This breaks some scenarios with relative paths
starting with "X:".  For instance, fstatat will mishandle a call
with valid dirfd and "c:" as path.

The reason is that gen_full_path_at() will check for isabspath("C:")
which returns true.  So the path will be used verbatim in fstatat,
rather than being converted to a path "/c:".

So, introduce isabspath_strict, which returns true for paths starting
with "X:" only if the next char is actually a slash or backslash.
Use it from gen_full_path_at().

This still fixes only half the problem.  The right thing would have been
to disallow using DOS paths in the first place.  Unfortunately it's much
too late for that.

Addresses: https://cygwin.com/pipermail/cygwin/2021-November/249837.html
Signed-off-by: Corinna Vinschen 
---
 winsup/cygwin/syscalls.cc | 2 +-
 winsup/cygwin/winsup.h| 8 
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 7a48e422e8f4..661c143479e4 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -4714,7 +4714,7 @@ gen_full_path_at (char *path_ret, int dirfd, const char 
*pathname,
  return -1;
}
 }
-  if (pathname && isabspath (pathname))
+  if (pathname && isabspath_strict (pathname))
 stpcpy (path_ret, pathname);
   else
 {
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index f6fea6313d56..1f265ec28934 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -139,9 +139,17 @@ extern int cygserver_running;
 #undef issep
 #define issep(ch) (strchr (" \t\n\r", (ch)) != NULL)
 
+/* Treats "X:" as absolute path.
+   FIXME: We should drop the notion that "X:" is a valid absolute path.
+   Only "X:/" and "X:\\" should be (see isabspath_strict below).  The
+   problem is to find out if we have code depending on this behaviour. */
 #define isabspath(p) \
   (isdirsep (*(p)) || (isalpha (*(p)) && (p)[1] == ':' && (!(p)[2] || isdirsep 
((p)[2]
 
+/* Treats "X:/" and "X:\\" as absolute paths, but not "X:" */
+#define isabspath_strict(p) \
+  (isdirsep (*(p)) || (isalpha (*(p)) && (p)[1] == ':' && isdirsep ((p)[2])))
+
 / Initialization/Termination **/
 
 class per_process;
-- 
2.31.1



[PATCH 0/2] Fix a bad case of absolute path handling

2021-11-10 Thread corinna-cygwin
From: Corinna Vinschen 

As I told Takashi in PM, I will try to more often send patches to the
cygwin-patches ML before pushing them, so there's a chance to chime in.

This patch series is supposed to address the `rm -rf' problem reported
in https://cygwin.com/pipermail/cygwin/2021-November/249837.html

It was always frustrating, having to allow DOS drive letter paths for
backward compatibility.  This here is another case of ambiguity,
triggered by the `isabspath' macro handling "X:" as absolute path, even
without the trailing slash or backslash.

Check out the 2nd patch for a more detailed description.

While at it, I wonder if we might have a chance to fix these ambiguities
in a better way.  For instance, consider this:

  $ mkdir -p test/c:
  $ cd test

As non-admin:

  $ touch c:/foo
  touch: cannot touch 'c:/foo': Permission denied

As admin, even worse:

  $ touch c:/foo
  $ ls /cygdrive/c/foo
  foo

As long as we support DOS paths as input, I have a hard time to see how
to fix this, but maybe we can at least minimize the ambiguity somehow.


Corinna


Corinna Vinschen (2):
  Cygwin: drop unused isabspath_u and iswabspath macros
  Cygwin: introduce isabspath_strict macro

 winsup/cygwin/syscalls.cc |  2 +-
 winsup/cygwin/winsup.h| 20 
 2 files changed, 9 insertions(+), 13 deletions(-)

-- 
2.31.1



[PATCH 1/2] Cygwin: drop unused isabspath_u and iswabspath macros

2021-11-10 Thread corinna-cygwin
From: Corinna Vinschen 

Signed-off-by: Corinna Vinschen 
---
 winsup/cygwin/winsup.h | 12 
 1 file changed, 12 deletions(-)

diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index abdef35261ca..f6fea6313d56 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -139,18 +139,6 @@ extern int cygserver_running;
 #undef issep
 #define issep(ch) (strchr (" \t\n\r", (ch)) != NULL)
 
-/* Every path beginning with / or \, as well as every path being X:
-   or starting with X:/ or X:\ */
-#define isabspath_u(p) \
-  ((p)->Length && \
-   (iswdirsep ((p)->Buffer[0]) || \
-((p)->Length > sizeof (WCHAR) && iswalpha ((p)->Buffer[0]) \
-&& (p)->Buffer[1] == L':' && \
-((p)->Length == 2 * sizeof (WCHAR) || iswdirsep ((p)->Buffer[2])
-
-#define iswabspath(p) \
-  (iswdirsep (*(p)) || (iswalpha (*(p)) && (p)[1] == L':' && (!(p)[2] || 
iswdirsep ((p)[2]
-
 #define isabspath(p) \
   (isdirsep (*(p)) || (isalpha (*(p)) && (p)[1] == ':' && (!(p)[2] || isdirsep 
((p)[2]
 
-- 
2.31.1



Re: [PATCH] Cygwin: pipe: Handle WAIT_CANCELED when waiting read_mtx.

2021-11-10 Thread Corinna Vinschen
On Nov 10 17:23, Takashi Yano wrote:
> - Add missing handling for WAIT_CANCELED in cygwait() for read_mtx
>   in raw_read().
> ---
>  winsup/cygwin/fhandler_pipe.cc | 10 +-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc
> index bc06d157c..13731437e 100644
> --- a/winsup/cygwin/fhandler_pipe.cc
> +++ b/winsup/cygwin/fhandler_pipe.cc
> @@ -302,10 +302,18 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
>set_errno (EAGAIN);
>len = (size_t) -1;
>return;
> -default:
> +case WAIT_SIGNALED:
>set_errno (EINTR);
>len = (size_t) -1;
>return;
> +case WAIT_CANCELED:
> +  pthread::static_cancel_self ();
> +  /* NOTREACHED */
> +default:
> +  /* Should not reach here. */
> +  __seterrno ();
> +  len = (size_t) -1;
> +  return;
>  }
>while (nbytes < len)
>  {
> -- 
> 2.33.0

ACK.  Please push.


Thanks,
Corinna


[PATCH] Cygwin: pipe: Handle WAIT_CANCELED when waiting read_mtx.

2021-11-10 Thread Takashi Yano
- Add missing handling for WAIT_CANCELED in cygwait() for read_mtx
  in raw_read().
---
 winsup/cygwin/fhandler_pipe.cc | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc
index bc06d157c..13731437e 100644
--- a/winsup/cygwin/fhandler_pipe.cc
+++ b/winsup/cygwin/fhandler_pipe.cc
@@ -302,10 +302,18 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
   set_errno (EAGAIN);
   len = (size_t) -1;
   return;
-default:
+case WAIT_SIGNALED:
   set_errno (EINTR);
   len = (size_t) -1;
   return;
+case WAIT_CANCELED:
+  pthread::static_cancel_self ();
+  /* NOTREACHED */
+default:
+  /* Should not reach here. */
+  __seterrno ();
+  len = (size_t) -1;
+  return;
 }
   while (nbytes < len)
 {
-- 
2.33.0