4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-08 18:19:08 +08:00

Cygwin: AF_UNIX: SCM_RIGHTS: support pty slave descriptors

This is the first case where the fhandler being sent uses an
archetype.  This archetype is of no use to the receiving process, so
we have to make the following changes:

- Modify fhandler_pty_slave::dup so that it duplicates handles when it
  is called on an fhandler that doesn't yet have an archetype.

- Modify dtable::dup_worker so that it creates an archetype for the
  new fhandler after fhandler_pty_slave::dup returns.
This commit is contained in:
Ken Brown 2020-11-30 17:47:25 -05:00
parent 81e265492a
commit c605ea0d6d
3 changed files with 185 additions and 36 deletions

View File

@ -677,35 +677,56 @@ out:
fhandler_base *
dtable::dup_worker (fhandler_base *oldfh, int flags, DWORD src_pid)
{
bool need_new_arch = false;
fhandler_base *newfh = oldfh->clone ();
if (!newfh)
debug_printf ("clone failed");
else
{
if (!oldfh->archetype)
newfh->set_handle (NULL);
newfh->pc.reset_conv_handle ();
if (oldfh->dup (newfh, flags, src_pid))
{
delete newfh;
newfh = NULL;
debug_printf ("oldfh->dup failed");
}
else
{
/* Don't increment refcnt here since we don't know if this is a
allocated fd. So we leave this chore to the caller. */
newfh->usecount = 0;
newfh->archetype_usecount (1);
/* The O_CLOEXEC flag enforces close-on-exec behaviour. */
newfh->set_close_on_exec (!!(flags & O_CLOEXEC));
debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (),
oldfh->get_handle (), newfh->get_handle ());
}
debug_printf ("clone failed");
goto out;
}
/* If we're duplicating an fhandler from a different process and we
use an archetype, the old archetype is useless. */
if (src_pid && oldfh->archetype
&& !(newfh->archetype = find_archetype (oldfh->dev ())))
need_new_arch = true;
if (!oldfh->archetype)
newfh->set_handle (NULL);
newfh->pc.reset_conv_handle ();
if (oldfh->dup (newfh, flags, src_pid))
{
delete newfh;
newfh = NULL;
debug_printf ("oldfh->dup failed");
goto out;
}
if (need_new_arch)
{
newfh->set_name (newfh->dev ().name ());
newfh->archetype = newfh->clone ();
debug_printf ("created an archetype (%p) for %s(%d/%d)",
newfh->archetype, newfh->get_name (),
newfh->dev ().get_major (), newfh->dev ().get_minor ());
newfh->archetype->archetype = NULL;
newfh->archetype->usecount = 0;
*add_archetype () = newfh->archetype;
}
/* Don't increment refcnt here since we don't know if this is a
allocated fd. So we leave this chore to the caller. */
newfh->usecount = 0;
newfh->archetype_usecount (1);
/* The O_CLOEXEC flag enforces close-on-exec behaviour. */
newfh->set_close_on_exec (!!(flags & O_CLOEXEC));
debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (),
oldfh->get_handle (), newfh->get_handle ());
out:
return newfh;
}

View File

@ -2008,6 +2008,7 @@ fhandler_socket_unix::serialize (int fd)
switch (dev.get_major ())
{
case DEV_PTYS_MAJOR:
break;
case DEV_PTYM_MAJOR:
case DEV_FLOPPY_MAJOR:
case DEV_CDROM_MAJOR:
@ -2091,30 +2092,48 @@ fhandler_socket_unix::deserialize (void *bufp)
{
fh_ser *fhs = (fh_ser *) bufp;
fhandler_base *oldfh, *newfh;
DWORD winpid = fhs->winpid;
cygheap_fdnew cfd;
if (cfd < 0)
return -1;
oldfh = (fhandler_base *) &fhs->fhu;
newfh = cygheap->fdtab.dup_worker (oldfh, 0, winpid);
newfh = cygheap->fdtab.dup_worker (oldfh, 0, fhs->winpid);
/* Tell sender it can delete its temporary copy of the fhandler. */
if (!send_scm_fd_ack (fhs->uniq_id))
debug_printf ("can't send ack");
if (!newfh)
return -1;
switch ((dev_t) newfh->dev ())
device dev = newfh->dev ();
switch (dev.get_major ())
{
case FH_FS:
newfh->set_name_from_handle ();
break;
case FH_UNIX:
if (((fhandler_socket_unix *) newfh)->get_pipe_end () == pipe_server)
((fhandler_socket_unix *) newfh)->gen_pipe_name ();
case DEV_PTYS_MAJOR:
break;
case DEV_PTYM_MAJOR:
case DEV_FLOPPY_MAJOR:
case DEV_CDROM_MAJOR:
case DEV_SD_MAJOR:
case DEV_SD1_MAJOR ... DEV_SD7_MAJOR:
case DEV_SD_HIGHPART_START ... DEV_SD_HIGHPART_END:
case DEV_TAPE_MAJOR:
case DEV_SERIAL_MAJOR:
case DEV_CONS_MAJOR:
set_errno (EOPNOTSUPP);
return -1;
default:
break;
switch ((dev_t) dev)
{
case FH_FS:
newfh->set_name_from_handle ();
break;
case FH_UNIX:
if (((fhandler_socket_unix *) newfh)->get_pipe_end () == pipe_server)
((fhandler_socket_unix *) newfh)->gen_pipe_name ();
break;
default:
break;
}
}
cfd = newfh;
return cfd;

View File

@ -1081,8 +1081,11 @@ out:
}
int
fhandler_pty_slave::dup (fhandler_base *child, int flags, DWORD)
fhandler_pty_slave::dup (fhandler_base *child, int flags, DWORD src_pid)
{
if (src_pid && !child->archetype)
goto dup_handles;
/* This code was added in Oct 2001 for some undisclosed reason.
However, setting the controlling tty on a dup causes rxvt to
hang when the parent does a dup since the controlling pgid changes.
@ -1095,6 +1098,112 @@ fhandler_pty_slave::dup (fhandler_base *child, int flags, DWORD)
myself->set_ctty (this, flags);
report_tty_counts (child, "duped slave", "");
return 0;
dup_handles:
/* We're being called from dtable::dup_worker with src_pid != 0, and
we don't have an archetype yet. We need to duplicate handles
from the source process, and the caller will create a new
archetype. The following code is adapted from
fhandler_pty_slave::open. */
fhandler_pty_slave *fhp = (fhandler_pty_slave *) child;
HANDLE src_proc;
HANDLE from_master_local, from_master_cyg_local;
HANDLE to_master_local, to_master_cyg_local;
HANDLE *handles[] =
{
&src_proc,
&from_master_local, &from_master_cyg_local,
&to_master_local, &to_master_cyg_local,
&fhp->output_mutex, &fhp->input_mutex, &fhp->inuse,
&fhp->input_available_event,
NULL
};
for (HANDLE **h = handles; *h; h++)
**h = NULL;
src_proc = OpenProcess (PROCESS_DUP_HANDLE, FALSE, src_pid);
if (!src_proc)
{
termios_printf ("can't open source process, %E");
goto err;
}
if (!DuplicateHandle (src_proc, output_mutex, GetCurrentProcess (),
&fhp->output_mutex, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate output_mutex from %u/%p, %E",
src_pid, output_mutex);
goto err;
}
if (!DuplicateHandle (src_proc, input_mutex, GetCurrentProcess (),
&fhp->input_mutex, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate input_mutex from %u/%p, %E",
src_pid, input_mutex);
goto err;
}
if (!DuplicateHandle (src_proc, input_available_event, GetCurrentProcess (),
&fhp->input_available_event, 0, TRUE,
DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate input_available_event from %u/%p, %E",
src_pid, input_available_event);
goto err;
}
if (!DuplicateHandle (src_proc, inuse, GetCurrentProcess (),
&fhp->inuse, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate inuse from %u/%p, %E",
src_pid, inuse);
goto err;
}
if (!DuplicateHandle (src_proc, get_ttyp ()->from_master (),
GetCurrentProcess (), &from_master_local,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate input from %u/%p, %E",
src_pid, get_ttyp ()->from_master ());
goto err;
}
if (!DuplicateHandle (src_proc, get_ttyp ()->from_master_cyg (),
GetCurrentProcess (), &from_master_cyg_local,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate input from %u/%p, %E",
src_pid, get_ttyp ()->from_master_cyg ());
goto err;
}
if (!DuplicateHandle (src_proc, get_ttyp ()->to_master (),
GetCurrentProcess (), &to_master_local,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate to_master_local from %u/%p, %E",
src_pid, get_ttyp ()->to_master ());
goto err;
}
if (!DuplicateHandle (src_proc, get_ttyp ()->to_master_cyg (),
GetCurrentProcess (), &to_master_cyg_local,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
termios_printf ("can't duplicate to_master_cyg_local from %u/%p, %E",
src_pid, get_ttyp ()->to_master_cyg ());
goto err;
}
CloseHandle (src_proc);
fhp->set_handle (from_master_local);
fhp->set_handle_cyg (from_master_cyg_local);
fhp->set_output_handle (to_master_local);
fhp->set_output_handle_cyg (to_master_cyg_local);
return 0;
err:
__seterrno ();
for (HANDLE **h = handles; *h; h++)
if (**h)
CloseHandle (**h);
return -1;
}
int