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>
This commit is contained in:
Corinna Vinschen 2019-01-06 22:39:45 +01:00
parent 8a17b1b2bf
commit 9dae73edb8
6 changed files with 31 additions and 12 deletions

View File

@ -2578,7 +2578,7 @@ class fhandler_process: public fhandler_proc
class fhandler_process_fd : public fhandler_process class fhandler_process_fd : public fhandler_process
{ {
fhandler_base *fetch_fh (HANDLE &); fhandler_base *fetch_fh (HANDLE &, uint32_t);
public: public:
fhandler_process_fd () : fhandler_process () {} fhandler_process_fd () : fhandler_process () {}

View File

@ -29,7 +29,7 @@ details. */
fhandler_base * fhandler_base *
fhandler_process_fd::fetch_fh (HANDLE &out_hdl) fhandler_process_fd::fetch_fh (HANDLE &out_hdl, uint32_t flags)
{ {
const char *path; const char *path;
char *e; char *e;
@ -49,6 +49,12 @@ fhandler_process_fd::fetch_fh (HANDLE &out_hdl)
cygheap_fdget cfd (fd, true); cygheap_fdget cfd (fd, true);
if (cfd < 0) if (cfd < 0)
return NULL; return NULL;
if ((flags & FFH_LINKAT)
&& (cfd->get_flags () & (O_TMPFILE | O_EXCL)) == (O_TMPFILE | O_EXCL))
{
set_errno (ENOENT);
return NULL;
}
proc = GetCurrentProcess (); proc = GetCurrentProcess ();
pc << cfd->pc; pc << cfd->pc;
hdl = cfd->get_handle (); hdl = cfd->get_handle ();
@ -68,10 +74,10 @@ fhandler_process_fd::fetch_fh (HANDLE &out_hdl)
return NULL; return NULL;
} }
size_t size; size_t size;
void *buf = p->file_pathconv (fd, size); void *buf = p->file_pathconv (fd, FFH_LINKAT, size);
if (size == 0) if (size == 0)
{ {
set_errno (EPERM); set_errno (ENOENT);
CloseHandle (proc); CloseHandle (proc);
return NULL; return NULL;
} }
@ -103,7 +109,7 @@ fhandler_process_fd::fd_reopen (int flags)
fhandler_base *fh; fhandler_base *fh;
HANDLE hdl; HANDLE hdl;
fh = fetch_fh (hdl); fh = fetch_fh (hdl, 0);
if (!fh) if (!fh)
return NULL; return NULL;
fh->set_io_handle (hdl); fh->set_io_handle (hdl);
@ -126,7 +132,7 @@ fhandler_process_fd::fstat (struct stat *statbuf)
fhandler_base *fh; fhandler_base *fh;
HANDLE hdl; HANDLE hdl;
fh = fetch_fh (hdl); fh = fetch_fh (hdl, 0);
if (!fh) if (!fh)
return -1; return -1;
fh->set_io_handle (hdl); fh->set_io_handle (hdl);
@ -142,7 +148,7 @@ fhandler_process_fd::link (const char *newpath)
fhandler_base *fh; fhandler_base *fh;
HANDLE hdl; HANDLE hdl;
fh = fetch_fh (hdl); fh = fetch_fh (hdl, FFH_LINKAT);
if (!fh) if (!fh)
return -1; return -1;
fh->set_io_handle (hdl); fh->set_io_handle (hdl);

View File

@ -187,7 +187,10 @@ struct _sigcommune
void *_si_process_handle; void *_si_process_handle;
__extension__ union __extension__ union
{ {
struct {
int _si_fd; int _si_fd;
uint32_t _si_flags;
};
int64_t _si_pipe_unique_id; int64_t _si_pipe_unique_id;
char *_si_str; char *_si_str;
}; };

View File

@ -73,6 +73,11 @@ enum path_types
PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */ 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); NTSTATUS file_get_fai (HANDLE, PFILE_ALL_INFORMATION);
int check_reparse_point_target (HANDLE, bool, PREPARSE_DATA_BUFFER, int check_reparse_point_target (HANDLE, bool, PREPARSE_DATA_BUFFER,
PUNICODE_STRING); PUNICODE_STRING);

View File

@ -660,9 +660,13 @@ commune_process (void *arg)
{ {
sigproc_printf ("processing PICOM_FILE_PATHCONV"); sigproc_printf ("processing PICOM_FILE_PATHCONV");
int fd = si._si_commune._si_fd; int fd = si._si_commune._si_fd;
uint32_t flags = si._si_commune._si_flags;
unsigned int n = 0; unsigned int n = 0;
cygheap_fdget cfd (fd); 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; fhandler_base *fh = cfd;
void *ser_buf = fh->pc.serialize (fh->get_handle (), n); 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_FD:
case PICOM_FILE_PATHCONV: case PICOM_FILE_PATHCONV:
si._si_commune._si_fd = va_arg (args, int); si._si_commune._si_fd = va_arg (args, int);
si._si_commune._si_flags = va_arg (args, uint32_t);
break; break;
break; break;
@ -852,13 +857,13 @@ _pinfo::pipe_fhandler (int64_t unique_id, size_t &n)
} }
void * void *
_pinfo::file_pathconv (int fd, size_t &n) _pinfo::file_pathconv (int fd, uint32_t flags, size_t &n)
{ {
if (!pid) if (!pid)
return NULL; return NULL;
if (pid == myself->pid) if (pid == myself->pid)
return NULL; return NULL;
commune_result cr = commune_request (PICOM_FILE_PATHCONV, fd); commune_result cr = commune_request (PICOM_FILE_PATHCONV, fd, flags);
n = cr.n; n = cr.n;
return (void *) cr.s; return (void *) cr.s;
} }

View File

@ -103,7 +103,7 @@ public:
commune_result commune_request (__uint32_t, ...); commune_result commune_request (__uint32_t, ...);
bool alive (); bool alive ();
fhandler_pipe *pipe_fhandler (int64_t, size_t &); 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 *fd (int fd, size_t &);
char *fds (size_t &); char *fds (size_t &);
char *root (size_t &); char *root (size_t &);