[newlib-cygwin] Cygwin: fix regression in O_TMPFILE | O_EXCL case
Corinna Vinschen
corinna@sourceware.org
Sun Jan 6 21:40:00 GMT 2019
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=9dae73edb8871f017251ddcba959e09457923a8e
commit 9dae73edb8871f017251ddcba959e09457923a8e
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Sun Jan 6 22:39:45 2019 +0100
Cygwin: fix regression in O_TMPFILE | O_EXCL case
The new proc fd code accidentally allowed to linkat an O_TMPFILE
even if the file has been opened with O_EXCL. This patch fixes it.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/fhandler.h | 2 +-
winsup/cygwin/fhandler_process_fd.cc | 18 ++++++++++++------
winsup/cygwin/include/cygwin/signal.h | 5 ++++-
winsup/cygwin/path.h | 5 +++++
winsup/cygwin/pinfo.cc | 11 ++++++++---
winsup/cygwin/pinfo.h | 2 +-
6 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index e32c219..d02b9a9 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2578,7 +2578,7 @@ class fhandler_process: public fhandler_proc
class fhandler_process_fd : public fhandler_process
{
- fhandler_base *fetch_fh (HANDLE &);
+ fhandler_base *fetch_fh (HANDLE &, uint32_t);
public:
fhandler_process_fd () : fhandler_process () {}
diff --git a/winsup/cygwin/fhandler_process_fd.cc b/winsup/cygwin/fhandler_process_fd.cc
index 06d37c0..0c0452a 100644
--- a/winsup/cygwin/fhandler_process_fd.cc
+++ b/winsup/cygwin/fhandler_process_fd.cc
@@ -29,7 +29,7 @@ details. */
fhandler_base *
-fhandler_process_fd::fetch_fh (HANDLE &out_hdl)
+fhandler_process_fd::fetch_fh (HANDLE &out_hdl, uint32_t flags)
{
const char *path;
char *e;
@@ -49,6 +49,12 @@ fhandler_process_fd::fetch_fh (HANDLE &out_hdl)
cygheap_fdget cfd (fd, true);
if (cfd < 0)
return NULL;
+ if ((flags & FFH_LINKAT)
+ && (cfd->get_flags () & (O_TMPFILE | O_EXCL)) == (O_TMPFILE | O_EXCL))
+ {
+ set_errno (ENOENT);
+ return NULL;
+ }
proc = GetCurrentProcess ();
pc << cfd->pc;
hdl = cfd->get_handle ();
@@ -68,10 +74,10 @@ fhandler_process_fd::fetch_fh (HANDLE &out_hdl)
return NULL;
}
size_t size;
- void *buf = p->file_pathconv (fd, size);
+ void *buf = p->file_pathconv (fd, FFH_LINKAT, size);
if (size == 0)
{
- set_errno (EPERM);
+ set_errno (ENOENT);
CloseHandle (proc);
return NULL;
}
@@ -103,7 +109,7 @@ fhandler_process_fd::fd_reopen (int flags)
fhandler_base *fh;
HANDLE hdl;
- fh = fetch_fh (hdl);
+ fh = fetch_fh (hdl, 0);
if (!fh)
return NULL;
fh->set_io_handle (hdl);
@@ -126,7 +132,7 @@ fhandler_process_fd::fstat (struct stat *statbuf)
fhandler_base *fh;
HANDLE hdl;
- fh = fetch_fh (hdl);
+ fh = fetch_fh (hdl, 0);
if (!fh)
return -1;
fh->set_io_handle (hdl);
@@ -142,7 +148,7 @@ fhandler_process_fd::link (const char *newpath)
fhandler_base *fh;
HANDLE hdl;
- fh = fetch_fh (hdl);
+ fh = fetch_fh (hdl, FFH_LINKAT);
if (!fh)
return -1;
fh->set_io_handle (hdl);
diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h
index 9d99727..e659d7a 100644
--- a/winsup/cygwin/include/cygwin/signal.h
+++ b/winsup/cygwin/include/cygwin/signal.h
@@ -187,7 +187,10 @@ struct _sigcommune
void *_si_process_handle;
__extension__ union
{
- int _si_fd;
+ struct {
+ int _si_fd;
+ uint32_t _si_flags;
+ };
int64_t _si_pipe_unique_id;
char *_si_str;
};
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index af10321..2b88504 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -73,6 +73,11 @@ enum path_types
PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */
};
+enum fetch_fh_flags
+{
+ FFH_LINKAT = (1 << 0),
+};
+
NTSTATUS file_get_fai (HANDLE, PFILE_ALL_INFORMATION);
int check_reparse_point_target (HANDLE, bool, PREPARSE_DATA_BUFFER,
PUNICODE_STRING);
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 00b3ed6..90dfd2b 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -660,9 +660,13 @@ commune_process (void *arg)
{
sigproc_printf ("processing PICOM_FILE_PATHCONV");
int fd = si._si_commune._si_fd;
+ uint32_t flags = si._si_commune._si_flags;
unsigned int n = 0;
cygheap_fdget cfd (fd);
- if (cfd >= 0)
+ if (cfd >= 0
+ && (!(flags & FFH_LINKAT)
+ || (cfd->get_flags () & (O_TMPFILE | O_EXCL))
+ != (O_TMPFILE | O_EXCL)))
{
fhandler_base *fh = cfd;
void *ser_buf = fh->pc.serialize (fh->get_handle (), n);
@@ -763,6 +767,7 @@ _pinfo::commune_request (__uint32_t code, ...)
case PICOM_FD:
case PICOM_FILE_PATHCONV:
si._si_commune._si_fd = va_arg (args, int);
+ si._si_commune._si_flags = va_arg (args, uint32_t);
break;
break;
@@ -852,13 +857,13 @@ _pinfo::pipe_fhandler (int64_t unique_id, size_t &n)
}
void *
-_pinfo::file_pathconv (int fd, size_t &n)
+_pinfo::file_pathconv (int fd, uint32_t flags, size_t &n)
{
if (!pid)
return NULL;
if (pid == myself->pid)
return NULL;
- commune_result cr = commune_request (PICOM_FILE_PATHCONV, fd);
+ commune_result cr = commune_request (PICOM_FILE_PATHCONV, fd, flags);
n = cr.n;
return (void *) cr.s;
}
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 8eb3c43..c4881c7 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -103,7 +103,7 @@ public:
commune_result commune_request (__uint32_t, ...);
bool alive ();
fhandler_pipe *pipe_fhandler (int64_t, size_t &);
- void *file_pathconv (int, size_t &);
+ void *file_pathconv (int, uint32_t, size_t &);
char *fd (int fd, size_t &);
char *fds (size_t &);
char *root (size_t &);
More information about the Cygwin-cvs
mailing list