Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog66
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/fhandler.h13
-rw-r--r--winsup/cygwin/fhandler_termios.cc7
-rw-r--r--winsup/cygwin/fhandler_tty.cc576
-rw-r--r--winsup/cygwin/security.cc112
-rw-r--r--winsup/cygwin/security.h9
-rw-r--r--winsup/cygwin/tty.cc49
-rw-r--r--winsup/cygwin/tty.h18
9 files changed, 702 insertions, 149 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 68334b318..f1e3b7bb7 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,71 @@
2010-04-19 Corinna Vinschen <corinna@vinschen.de>
+ * autoload.cc (GetNamedPipeClientProcessId): Define.
+ * fhandler.h (fhandler_tty_slave::fch_open_handles): Declare private.
+ (fhandler_tty_slave::fch_close_handles): Ditto.
+ (fhandler_tty_slave::cygserver_attach_tty): Drop declaration.
+ (fhandler_tty_slave::fstat): Declare public.
+ (fhandler_tty_slave::fchmod): Declare public.
+ (fhandler_tty_slave::fchown): Declare public.
+ (class fhandler_pty_master): Add master_ctl handle.
+ (fhandler_pty_master::pty_master_thread): Declare public.
+ * fhandler_termios.cc (fhandler_termios::tcinit): If the process
+ is started from a non-Cygwin process, make it tty process group
+ leader.
+ * fhandler_tty.cc: Throughout accommodate additional security related
+ arguments in calls to functions creating or opening objects.
+ (close_maybe): Move to start of file to reuse it
+ in other methods.
+ (struct pipe_request): Define.
+ (struct pipe_reply): Define.
+ (fhandler_tty_slave::open): Throughout, try to open synchronization
+ objects with MAXIMUM_ALLOWED permissions. Drop call to cygserver.
+ Try to duplicate pipe handles via master_ctl pipe if duplicating
+ directly doesn't work.
+ (fhandler_tty_slave::cygserver_attach_tty): Remove.
+ (fhandler_tty_slave::init): Close unused incoming pipe handle.
+ (fhandler_pty_master::close): Send exit message to master control
+ thread and close master_ctl handle.
+ (fhandler_pty_master::pty_master_thread): New method, implementing the
+ master control thread.
+ (pty_master_thread): Static helper to start master control thread.
+ (fhandler_pty_master::setup): Simplify creating pipe inheritance.
+ Make sure we're the one creating the input_available_event. Add
+ comment to explain why. Create master_ctl pipe and start master
+ control thread. Close master_ctl handle in case of error.
+ * security.cc (alloc_sd): Add code to handle tty objects. Add comments
+ to explain what exactly is required.
+ (get_object_sd): New function.
+ (get_object_attribute): New function.
+ (create_object_sd_from_attribute): New function.
+ (set_object_sd): New function.
+ (set_object_attribute): New function.
+ (set_file_attribute): Change attribute type to mode_t.
+ * security.h (set_file_attribute): Change attribute type to mode_t.
+ (get_object_sd): Declare.
+ (get_object_attribute): Declare.
+ (create_object_sd_from_attribute): Declare.
+ (set_object_sd): Declare.
+ (set_object_attribute): Declare.
+ * tty.cc (tty::slave_alive): Implement directly instead of via alive.
+ (tty::exists): Open mutex handle with READ_CONTROL access.
+ (tty::alive): Remove.
+ (tty::open_output_mutex): Convert to inline method.
+ (tty::open_input_mutex): Ditto.
+ (tty::open_mutex): Take additional ACCESS_MASK parameter for the
+ mutex open access mask.
+ (tty::open_inuse): New method.
+ (tty::create_inuse): Take PSECURITY_ATTRIBUTES parameter. Drop fmt
+ name parameter. Always create TTY_SLAVE_ALIVE event.
+ (tty::get_event): Take additional PSECURITY_ATTRIBUTES parameter for
+ CreateEvent.
+ * tty.h (class tty): Change declarations according to aforementioned
+ changes.
+ (tty::open_output_mutex): Implement as inline method.
+ (tty::open_input_mutex): Ditto.
+
+2010-04-19 Corinna Vinschen <corinna@vinschen.de>
+
* dtable.cc (dtable::init_std_file_from_handle): Set dev to
valid content for ptys. Remove setting FILE_CREATE_PIPE_INSTANCE
in access flags since it's not needed. Set the access mask for
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index f5bdadeee..67a93f921 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -419,6 +419,7 @@ LoadDLLfuncEx (FindFirstVolumeA, 8, kernel32, 1)
LoadDLLfuncEx (FindNextVolumeA, 12, kernel32, 1)
LoadDLLfuncEx (FindVolumeClose, 4, kernel32, 1)
LoadDLLfuncEx (GetConsoleWindow, 0, kernel32, 1)
+LoadDLLfuncEx (GetNamedPipeClientProcessId, 8, kernel32, 1)
LoadDLLfuncEx (GetSystemWindowsDirectoryW, 8, kernel32, 1)
LoadDLLfuncEx (GetVolumeNameForVolumeMountPointA, 12, kernel32, 1)
LoadDLLfuncEx (GetSystemDEPPolicy, 0, kernel32, 1)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index cf9d7b9ae..1255a3fb9 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1089,6 +1089,12 @@ class fhandler_tty_common: public fhandler_termios
class fhandler_tty_slave: public fhandler_tty_common
{
HANDLE inuse; // used to indicate that a tty is in use
+
+ /* Helper functions for fchmod and fchown. */
+ bool fch_open_handles ();
+ int fch_set_sd (security_descriptor &sd, bool chown);
+ void fch_close_handles ();
+
public:
/* Constructor */
fhandler_tty_slave ();
@@ -1108,14 +1114,18 @@ class fhandler_tty_slave: public fhandler_tty_common
void fixup_after_exec ();
select_record *select_read (select_stuff *);
- int cygserver_attach_tty (HANDLE*, HANDLE*);
int get_unit ();
virtual char const *ttyname () { return pc.dev.name; }
+ int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
+ int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
+ int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
};
class fhandler_pty_master: public fhandler_tty_common
{
int pktmode; // non-zero if pty in a packet mode.
+ HANDLE master_ctl; // Control socket for handle duplication
+
public:
int need_nl; // Next read should start with \n
DWORD dwProcessId; // Owner of master handles
@@ -1123,6 +1133,7 @@ public:
/* Constructor */
fhandler_pty_master ();
+ DWORD pty_master_thread ();
int process_slave_output (char *buf, size_t len, int pktmode_on);
void doecho (const void *str, DWORD len);
int accept_input ();
diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc
index b5d9f2ef3..b7f7860c5 100644
--- a/winsup/cygwin/fhandler_termios.cc
+++ b/winsup/cygwin/fhandler_termios.cc
@@ -58,6 +58,13 @@ fhandler_termios::tcinit (tty_min *this_tc, bool force)
tc->pgid = myself->pgid;
tc->initialized (true);
}
+ else if (myself->ppid == 1 && myself->pid == myself->pgid
+ && myself->pgid == myself->sid)
+ /* We have been started from a non-Cygwin process. So we just become
+ tty process group leader.
+ TODO: Investigate how SIGTTIN should be handled with pure-windows
+ programs. */
+ tc->pgid = myself->pgid;
}
int
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 30b6dda09..b95bd5f3e 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -19,12 +19,29 @@ details. */
#include "dtable.h"
#include "sigproc.h"
#include "pinfo.h"
+#include "ntdll.h"
#include "cygheap.h"
#include "shared_info.h"
-#include "cygserver.h"
#include "cygthread.h"
#include "child_info.h"
+#define close_maybe(h) \
+ do { \
+ if (h && h != INVALID_HANDLE_VALUE) \
+ CloseHandle (h); \
+ } while (0)
+
+/* pty master control pipe messages */
+struct pipe_request {
+ DWORD pid;
+};
+
+struct pipe_reply {
+ HANDLE from_master;
+ HANDLE to_master;
+ DWORD error;
+};
+
/* tty master stuff */
fhandler_tty_master NO_COPY *tty_master;
@@ -490,20 +507,20 @@ fhandler_tty_slave::open (int flags, mode_t)
pty opened by fhandler_pty_master::open. In the former case, tty
output is handled by a separate thread which controls output. */
shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
- output_done_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
+ output_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
- if (!(output_mutex = get_ttyp ()->open_output_mutex ()))
+ if (!(output_mutex = get_ttyp ()->open_output_mutex (MAXIMUM_ALLOWED)))
{
errmsg = "open output mutex failed, %E";
goto err;
}
- if (!(input_mutex = get_ttyp ()->open_input_mutex ()))
+ if (!(input_mutex = get_ttyp ()->open_input_mutex (MAXIMUM_ALLOWED)))
{
errmsg = "open input mutex failed, %E";
goto err;
}
shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
- if (!(input_available_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf)))
+ if (!(input_available_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
{
errmsg = "open input event failed, %E";
goto err;
@@ -512,14 +529,23 @@ fhandler_tty_slave::open (int flags, mode_t)
/* The ioctl events may or may not exist. See output_done_event,
above. */
shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
- ioctl_request_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
+ ioctl_request_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
- ioctl_done_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
+ ioctl_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
/* FIXME: Needs a method to eliminate tty races */
{
+ /* Create security attribute. Default permissions are 0620. */
+ security_descriptor sd;
+ sd.malloc (sizeof (SECURITY_DESCRIPTOR));
+ InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
+ SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
+ if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
+ sd))
+ sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
acquire_output_mutex (500);
- inuse = get_ttyp ()->create_inuse (TTY_SLAVE_ALIVE);
+ inuse = get_ttyp ()->create_inuse (&sa);
get_ttyp ()->was_opened = true;
release_output_mutex ();
}
@@ -531,43 +557,40 @@ fhandler_tty_slave::open (int flags, mode_t)
goto err_no_errno;
}
- if (myself->pid == get_ttyp ()->master_pid
- || cygserver_running == CYGSERVER_UNAVAIL
- || !cygserver_attach_tty (&from_master_local, &to_master_local))
+ if (get_ttyp ()->master_pid < 0)
+ {
+ errmsg = "*** master is closed";
+ set_errno (EAGAIN);
+ goto err_no_errno;
+ }
+ /* Three case for duplicating the pipe handles:
+ - Either we're the master. In this case, just duplicate the handles.
+ - Or, we have the right to open the master process for handle duplication.
+ In this case, just duplicate the handles.
+ - Or, we have to ask the master process itself. In this case, send our
+ pid to the master process and check the reply. The reply contains
+ either the handles, or an error code which tells us why we didn't
+ get the handles. */
+ if (myself->pid == get_ttyp ()->master_pid)
+ {
+ /* This is the most common case, just calling openpty. */
+ termios_printf ("dup handles within myself.");
+ tty_owner = GetCurrentProcess ();
+ }
+ else
{
- if (get_ttyp ()->master_pid < 0)
- {
- errmsg = "*** master is closed";
- set_errno (EAGAIN);
- goto err_no_errno;
- }
pinfo p (get_ttyp ()->master_pid);
if (!p)
- {
- errmsg = "*** couldn't find tty master";
- set_errno (EAGAIN);
- goto err_no_errno;
- }
- HANDLE tty_owner;
- if (myself->pid == get_ttyp ()->master_pid)
- {
- /* This is the most common case, just calling openpty. */
- termios_printf ("dup handles within myself.");
- tty_owner = GetCurrentProcess ();
- }
+ termios_printf ("*** couldn't find tty master");
else
{
- termios_printf ("cannot dup handles via server. using old method.");
tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
- if (tty_owner == NULL)
- {
- termios_printf ("can't open tty (%d) handle process %d",
- get_unit (), get_ttyp ()->master_pid);
- __seterrno ();
- goto err_no_msg;
- }
+ if (tty_owner)
+ termios_printf ("dup handles directly since I'm allmighty.");
}
-
+ }
+ if (tty_owner)
+ {
if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master,
GetCurrentProcess (), &from_master_local, 0, TRUE,
DUPLICATE_SAME_ACCESS))
@@ -577,8 +600,6 @@ fhandler_tty_slave::open (int flags, mode_t)
__seterrno ();
goto err_no_msg;
}
-
- VerifyHandle (from_master_local);
if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master,
GetCurrentProcess (), &to_master_local, 0, TRUE,
DUPLICATE_SAME_ACCESS))
@@ -586,10 +607,35 @@ fhandler_tty_slave::open (int flags, mode_t)
errmsg = "can't duplicate output, %E";
goto err;
}
- VerifyHandle (to_master_local);
if (tty_owner != GetCurrentProcess ())
CloseHandle (tty_owner);
}
+ else
+ {
+ pipe_request req = { GetCurrentProcessId () };
+ pipe_reply repl;
+ DWORD len;
+
+ __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
+ &installation_key, get_unit ());
+ termios_printf ("dup handles via master control pipe %s", buf);
+ if (!CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl,
+ &len, 500))
+ {
+ errmsg = "can't call master, %E";
+ goto err;
+ }
+ from_master_local = repl.from_master;
+ to_master_local = repl.to_master;
+ if (!from_master_local || !to_master_local)
+ {
+ SetLastError (repl.error);
+ errmsg = "error duplicating pipes, %E";
+ goto err;
+ }
+ }
+ VerifyHandle (from_master_local);
+ VerifyHandle (to_master_local);
termios_printf ("duplicated from_master %p->%p from tty_owner",
get_ttyp ()->from_master, from_master_local);
@@ -660,31 +706,7 @@ fhandler_tty_slave::close ()
}
int
-fhandler_tty_slave::cygserver_attach_tty (LPHANDLE from_master_ptr,
- LPHANDLE to_master_ptr)
-{
- if (!from_master_ptr || !to_master_ptr)
- return 0;
-
- pinfo p (get_ttyp ()->master_pid);
- if (!p)
- return 0;
-
- client_request_attach_tty req (p->dwProcessId,
- (HANDLE) get_ttyp ()->from_master,
- (HANDLE) get_ttyp ()->to_master);
-
- if (req.make_request () == -1 || req.error_code ())
- return 0;
-
- *from_master_ptr = req.from_master ();
- *to_master_ptr = req.to_master ();
-
- return 1;
-}
-
-int
-fhandler_tty_slave::init (HANDLE, DWORD a, mode_t)
+fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t)
{
int flags = 0;
@@ -696,7 +718,12 @@ fhandler_tty_slave::init (HANDLE, DWORD a, mode_t)
if (a == (GENERIC_READ | GENERIC_WRITE))
flags = O_RDWR;
- return open (flags);
+ int ret = open (flags);
+
+ if (f != INVALID_HANDLE_VALUE)
+ CloseHandle (f); /* Reopened by open */
+
+ return ret;
}
ssize_t __stdcall
@@ -1117,6 +1144,177 @@ out:
return retval;
}
+int __stdcall
+fhandler_tty_slave::fstat (struct __stat64 *st)
+{
+ fhandler_base::fstat (st);
+
+ bool to_close = false;
+ if (!input_available_event)
+ {
+ char buf[MAX_PATH];
+ shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
+ input_available_event = OpenEvent (READ_CONTROL, TRUE, buf);
+ if (input_available_event)
+ to_close = true;
+ }
+ if (!input_available_event
+ || get_object_attribute (input_available_event, &st->st_uid, &st->st_gid,
+ &st->st_mode))
+ {
+ /* If we can't access the ACL, or if the tty doesn't actually exist,
+ then fake uid and gid to strict, system-like values. */
+ st->st_mode = S_IFCHR | S_IRUSR | S_IWUSR;
+ st->st_uid = 18;
+ st->st_gid = 544;
+ }
+ if (to_close)
+ CloseHandle (input_available_event);
+ return 0;
+}
+
+/* Helper function for fchmod and fchown, which just opens all handles
+ and signals success via bool return. */
+bool
+fhandler_tty_slave::fch_open_handles ()
+{
+ char buf[MAX_PATH];
+
+ tc = cygwin_shared->tty[get_unit ()];
+ shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
+ input_available_event = OpenEvent (READ_CONTROL | WRITE_DAC | WRITE_OWNER,
+ TRUE, buf);
+ output_mutex = get_ttyp ()->open_output_mutex (WRITE_DAC | WRITE_OWNER);
+ input_mutex = get_ttyp ()->open_input_mutex (WRITE_DAC | WRITE_OWNER);
+ inuse = get_ttyp ()->open_inuse (WRITE_DAC | WRITE_OWNER);
+ if (!input_available_event || !output_mutex || !input_mutex || !inuse)
+ {
+ __seterrno ();
+ return false;
+ }
+ /* These members are optional, no error checking */
+ shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
+ output_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
+ shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
+ ioctl_request_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
+ shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
+ ioctl_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
+ return true;
+}
+
+/* Helper function for fchmod and fchown, which sets the new security
+ descriptor on all objects representing the tty. */
+int
+fhandler_tty_slave::fch_set_sd (security_descriptor &sd, bool chown)
+{
+ security_descriptor sd_old;
+
+ get_object_sd (input_available_event, sd_old);
+ if (/*!set_object_sd (get_io_handle (), sd, chown)
+ && !set_object_sd (get_output_handle (), sd, chown)
+ && */ !set_object_sd (input_available_event, sd, chown)
+ && !set_object_sd (output_mutex, sd, chown)
+ && !set_object_sd (input_mutex, sd, chown)
+ && !set_object_sd (inuse, sd, chown)
+ && (!output_done_event
+ || !set_object_sd (output_done_event, sd, chown))
+ && (!ioctl_request_event
+ || !set_object_sd (ioctl_request_event, sd, chown))
+ && (!ioctl_done_event
+ || !set_object_sd (ioctl_done_event, sd, chown)))
+ return 0;
+ /*set_object_sd (get_io_handle (), sd_old, chown);
+ set_object_sd (get_output_handle (), sd_old, chown);*/
+ set_object_sd (input_available_event, sd_old, chown);
+ set_object_sd (output_mutex, sd_old, chown);
+ set_object_sd (input_mutex, sd_old, chown);
+ set_object_sd (inuse, sd_old, chown);
+ if (!output_done_event)
+ set_object_sd (output_done_event, sd_old, chown);
+ if (!ioctl_request_event)
+ set_object_sd (ioctl_request_event, sd_old, chown);
+ if (!ioctl_done_event)
+ set_object_sd (ioctl_done_event, sd_old, chown);
+ return -1;
+}
+
+/* Helper function for fchmod and fchown, which closes all object handles in
+ the tty. */
+void
+fhandler_tty_slave::fch_close_handles ()
+{
+ close_maybe (get_io_handle ());
+ close_maybe (get_output_handle ());
+ close_maybe (output_done_event);
+ close_maybe (ioctl_done_event);
+ close_maybe (ioctl_request_event);
+ close_maybe (input_available_event);
+ close_maybe (output_mutex);
+ close_maybe (input_mutex);
+ close_maybe (inuse);
+}
+
+int __stdcall
+fhandler_tty_slave::fchmod (mode_t mode)
+{
+ int ret = -1;
+ bool to_close = false;
+ security_descriptor sd;
+ __uid32_t uid;
+ __gid32_t gid;
+
+ if (!input_available_event)
+ {
+ to_close = true;
+ if (!fch_open_handles ())
+ goto errout;
+ }
+ sd.malloc (sizeof (SECURITY_DESCRIPTOR));
+ InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
+ if (!get_object_attribute (input_available_event, &uid, &gid, NULL)
+ && !create_object_sd_from_attribute (NULL, uid, gid, S_IFCHR | mode, sd))
+ ret = fch_set_sd (sd, false);
+errout:
+ if (to_close)
+ fch_close_handles ();
+ return ret;
+}
+
+int __stdcall
+fhandler_tty_slave::fchown (__uid32_t uid, __gid32_t gid)
+{
+ int ret = -1;
+ bool to_close = false;
+ mode_t mode;
+ __uid32_t o_uid;
+ __gid32_t o_gid;
+ security_descriptor sd;
+
+ if (uid == ILLEGAL_UID && gid == ILLEGAL_GID)
+ return 0;
+ if (!input_available_event)
+ {
+ to_close = true;
+ if (!fch_open_handles ())
+ goto errout;
+ }
+ sd.malloc (sizeof (SECURITY_DESCRIPTOR));
+ InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
+ if (!get_object_attribute (input_available_event, &o_uid, &o_gid, &mode))
+ {
+ if ((uid == ILLEGAL_UID || uid == o_uid)
+ && (gid == ILLEGAL_GID || gid == o_gid))
+ ret = 0;
+ else if (!create_object_sd_from_attribute (input_available_event,
+ uid, gid, S_IFCHR | mode, sd))
+ ret = fch_set_sd (sd, true);
+ }
+errout:
+ if (to_close)
+ fch_close_handles ();
+ return ret;
+}
+
/*******************************************************
fhandler_pty_master
*/
@@ -1215,6 +1413,18 @@ fhandler_pty_master::close ()
arch->from_master, arch->to_master, arch->dwProcessId);
if (cygwin_finished_initializing)
{
+ if (arch->master_ctl && get_ttyp ()->master_pid == myself->pid)
+ {
+ char buf[MAX_PATH];
+ pipe_request req = { (DWORD) -1 };
+ pipe_reply repl;
+ DWORD len;
+
+ __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
+ &installation_key, get_unit ());
+ CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500);
+ CloseHandle (arch->master_ctl);
+ }
if (!ForceCloseHandle (arch->from_master))
termios_printf ("error closing from_master %p, %E", arch->from_master);
if (!ForceCloseHandle (arch->to_master))
@@ -1361,16 +1571,154 @@ fhandler_tty_master::init_console ()
return 0;
}
-#define close_maybe(h) \
- do { \
- if (h && h != INVALID_HANDLE_VALUE) \
- CloseHandle (h); \
- } while (0)
+extern "C" BOOL WINAPI GetNamedPipeClientProcessId (HANDLE, PULONG);
+
+/* This thread function handles the master control pipe. It waits for a
+ client to connect. Then it checks if the client process has permissions
+ to access the tty handles. If so, it opens the client process and
+ duplicates the handles into that process. If that fails, it sends a reply
+ with at least one handle set to NULL and an error code. Last but not
+ least, the client is disconnected and the thread waits for the next client.
+
+ A special case is when the master side of the tty is about to be closed.
+ The client side is the fhandler_pty_master::close function and it sends
+ a PID -1 in that case. On Vista and later a check is performed that the
+ request to leave really comes from the master process itself. On earlier
+ OSes there's no function to check for the PID of the client process so
+ we have to trust the client side.
+
+ Since there's
+ always only one pipe instance, there's a chance that clients have to
+ wait to connect to the master control pipe. Therefore the client calls
+ to CallNamedPipe should have a big enough timeout value. For now this
+ is 500ms. Hope that's enough. */
+
+DWORD
+fhandler_pty_master::pty_master_thread ()
+{
+ bool exit = false;
+ GENERIC_MAPPING map = { EVENT_QUERY_STATE, EVENT_MODIFY_STATE, 0,
+ EVENT_QUERY_STATE | EVENT_MODIFY_STATE };
+ pipe_request req;
+ DWORD len;
+ security_descriptor sd;
+ HANDLE token;
+ PRIVILEGE_SET ps;
+ BOOL ret;
+ DWORD pid;
+
+ termios_printf ("Entered");
+ while (!exit && ConnectNamedPipe (master_ctl, NULL))
+ {
+ pipe_reply repl = { NULL, NULL, 0 };
+ bool deimp = false;
+ BOOL allow = FALSE;
+ ACCESS_MASK access = EVENT_MODIFY_STATE;
+ HANDLE client = NULL;
+
+ if (!ReadFile (master_ctl, &req, sizeof req, &len, NULL))
+ {
+ termios_printf ("ReadFile, %E");
+ goto reply;
+ }
+ /* This function is only available since Vista, unfortunately.
+ In earlier OSes we simply have to believe that the client
+ has no malicious intent (== sends arbitrary PIDs). */
+ if (!GetNamedPipeClientProcessId (master_ctl, &pid))
+ pid = req.pid;
+ if (get_object_sd (input_available_event, sd))
+ {
+ termios_printf ("get_object_sd, %E");
+ goto reply;
+ }
+ cygheap->user.deimpersonate ();
+ deimp = true;
+ if (!ImpersonateNamedPipeClient (master_ctl))
+ {
+ termios_printf ("ImpersonateNamedPipeClient, %E");
+ goto reply;
+ }
+ if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE, &token))
+ {
+ termios_printf ("OpenThreadToken, %E");
+ goto reply;
+ }
+ len = sizeof ps;
+ ret = AccessCheck (sd, token, access, &map, &ps, &len, &access, &allow);
+ CloseHandle (token);
+ if (!ret)
+ {
+ termios_printf ("AccessCheck, %E");
+ goto reply;
+ }
+ if (!RevertToSelf ())
+ {
+ termios_printf ("RevertToSelf, %E");
+ goto reply;
+ }
+ if (req.pid == (DWORD) -1) /* Request to finish thread. */
+ {
+ /* Pre-Vista: Just believe in the good of the client process.
+ Post-Vista: Check if the requesting process is the master
+ process itself. */
+ if (pid == (DWORD) -1 || pid == GetCurrentProcessId ())
+ exit = true;
+ goto reply;
+ }
+ if (allow)
+ {
+ client = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
+ if (!client)
+ {
+ termios_printf ("OpenProcess, %E");
+ goto reply;
+ }
+ if (!DuplicateHandle (GetCurrentProcess (), from_master,
+ client, &repl.from_master,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("DuplicateHandle (from_master), %E");
+ goto reply;
+ }
+ if (!DuplicateHandle (GetCurrentProcess (), to_master,
+ client, &repl.to_master,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("DuplicateHandle (to_master), %E");
+ goto reply;
+ }
+ }
+reply:
+ repl.error = GetLastError ();
+ if (client)
+ CloseHandle (client);
+ if (deimp)
+ cygheap->user.reimpersonate ();
+ sd.free ();
+ termios_printf ("Reply: from %p, to %p, error %lu",
+ repl.from_master, repl.to_master, repl.error );
+ if (!WriteFile (master_ctl, &repl, sizeof repl, &len, NULL))
+ termios_printf ("WriteFile, %E");
+ if (!DisconnectNamedPipe (master_ctl))
+ termios_printf ("DisconnectNamedPipe, %E");
+ }
+ termios_printf ("Leaving");
+ return 0;
+}
+
+static DWORD WINAPI
+pty_master_thread (VOID *arg)
+{
+ return ((fhandler_pty_master *) arg)->pty_master_thread ();
+}
bool
fhandler_pty_master::setup (bool ispty)
{
int res;
+ security_descriptor sd;
+ SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
+
tty& t = *cygwin_shared->tty[get_unit ()];
tcinit (&t, true); /* Set termios information. Force initialization. */
@@ -1379,78 +1727,97 @@ fhandler_pty_master::setup (bool ispty)
DWORD pipe_mode = PIPE_NOWAIT;
/* Create communication pipes */
-
char pipename[sizeof("ttyNNNN-from-master")];
__small_sprintf (pipename, "tty%d-from-master", get_unit ());
- res = fhandler_pipe::create_selectable (&sec_none_nih, from_master,
- get_output_handle (), 128 * 1024,
- pipename);
+ res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
+ from_master, get_output_handle (),
+ 128 * 1024, pipename);
if (res)
{
errstr = "input pipe";
goto err;
}
- /* Only ptys should create inheritable handles by default. ttys are
- parcelled out on an as-needed basis and handle inheritance differently. */
- if (ispty && !SetHandleInformation (get_output_handle (), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
- {
- errstr = "inheritable get_output_handle ()";
- goto err;
- }
if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL))
termios_printf ("can't set output_handle(%p) to non-blocking mode",
get_output_handle ());
__small_sprintf (pipename, "tty%d-to-master", get_unit ());
- res = fhandler_pipe::create_selectable (&sec_none_nih, get_io_handle (),
- to_master, 128 * 1024, pipename);
+ res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
+ get_io_handle (), to_master,
+ 128 * 1024, pipename);
if (res)
{
errstr = "output pipe";
goto err;
}
- /* Only ptys should create inheritable handles by default. ttys are
- parcelled out on an as-needed basis and handle inheritance differently. */
- if (ispty && !SetHandleInformation (get_io_handle (), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
- {
- errstr = "inheritable get_io_handle ()";
- goto err;
- }
need_nl = 0;
- /* We do not allow others to open us (for handle duplication)
- but rely on cygheap->inherited_ctty for descendant processes.
- In the future the cygserver may allow access by others. */
-
- if (cygserver_running == CYGSERVER_UNKNOWN)
- cygserver_init ();
+ /* Create security attribute. Default permissions are 0620. */
+ sd.malloc (sizeof (SECURITY_DESCRIPTOR));
+ InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
+ if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
+ sd))
+ sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
/* Create synchronisation events */
if (!ispty)
{
- if (!(output_done_event = t.get_event (errstr = OUTPUT_DONE_EVENT)))
+ if (!(output_done_event = t.get_event (errstr = OUTPUT_DONE_EVENT, &sa)))
goto err;
- if (!(ioctl_done_event = t.get_event (errstr = IOCTL_DONE_EVENT)))
+ if (!(ioctl_done_event = t.get_event (errstr = IOCTL_DONE_EVENT, &sa)))
goto err;
- if (!(ioctl_request_event = t.get_event (errstr = IOCTL_REQUEST_EVENT)))
+ if (!(ioctl_request_event = t.get_event (errstr = IOCTL_REQUEST_EVENT,
+ &sa)))
goto err;
}
- if (!(input_available_event = t.get_event (errstr = INPUT_AVAILABLE_EVENT, TRUE)))
+ /* Carefully check that the input_available_event didn't already exist.
+ This is a measure to make sure that the event security descriptor
+ isn't occupied by a malicious process. We must make sure that the
+ event's security descriptor is what we expect it to be. */
+ if (!(input_available_event = t.get_event (errstr = INPUT_AVAILABLE_EVENT,
+ &sa, TRUE))
+ || GetLastError () == ERROR_ALREADY_EXISTS)
goto err;
char buf[MAX_PATH];
errstr = shared_name (buf, OUTPUT_MUTEX, t.ntty);
- if (!(output_mutex = CreateMutex (&sec_all, FALSE, buf)))
+ if (!(output_mutex = CreateMutex (&sa, FALSE, buf)))
goto err;
errstr = shared_name (buf, INPUT_MUTEX, t.ntty);
- if (!(input_mutex = CreateMutex (&sec_all, FALSE, buf)))
+ if (!(input_mutex = CreateMutex (&sa, FALSE, buf)))
goto err;
+ if (ispty)
+ {
+ /* Create master control pipe which allows the master to duplicate
+ the pty pipe handles to processes which deserve it. */
+ cygthread *h;
+ __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
+ &installation_key, get_unit ());
+ master_ctl = CreateNamedPipe (buf, PIPE_ACCESS_DUPLEX,
+ PIPE_WAIT | PIPE_TYPE_MESSAGE
+ | PIPE_READMODE_MESSAGE, 1, 4096, 4096,
+ 0, &sec_all_nih);
+ if (master_ctl == INVALID_HANDLE_VALUE)
+ {
+ errstr = "pty master control pipe";
+ goto err;
+ }
+ h = new cygthread (::pty_master_thread, 0, this, "pty_master");
+ if (!h)
+ {
+ errstr = "pty master control thread";
+ goto err;
+ }
+ h->zap_h ();
+ }
+
t.from_master = from_master;
t.to_master = to_master;
// /* screws up tty master */ ProtectHandle1INH (output_mutex, output_mutex);
@@ -1475,6 +1842,7 @@ err:
close_maybe (input_mutex);
close_maybe (from_master);
close_maybe (to_master);
+ close_maybe (master_ctl);
termios_printf ("tty%d open failed - failed to create %s", errstr);
return false;
}
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index b09a719f3..c180197e1 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -1,7 +1,7 @@
/* security.cc: NT file access control functions
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009 Red Hat, Inc.
+ 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de
Completely rewritten by Corinna Vinschen <corinna@vinschen.de>
@@ -464,6 +464,10 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
/* From here fill ACL. */
size_t acl_len = sizeof (ACL);
int ace_off = 0;
+ /* Only used for sync objects (for ttys). The admins group should
+ always have the right to manipulate the ACL, so we have to make sure
+ that the ACL gives the admins group STANDARD_RIGHTS_ALL access. */
+ bool saw_admins = false;
/* Construct allow attribute for owner.
Don't set FILE_READ/WRITE_ATTRIBUTES unconditionally on Samba, otherwise
@@ -480,9 +484,12 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
if (S_ISDIR (attribute)
&& (attribute & (S_IWUSR | S_IXUSR)) == (S_IWUSR | S_IXUSR))
owner_allow |= FILE_DELETE_CHILD;
+ /* For sync objects note that the owner is admin. */
+ if (S_ISCHR (attribute) && owner_sid == well_known_admins_sid)
+ saw_admins = true;
/* Construct allow attribute for group. */
- DWORD group_allow = STANDARD_RIGHTS_READ
+ DWORD group_allow = STANDARD_RIGHTS_READ | SYNCHRONIZE
| (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
if (attribute & S_IRGRP)
group_allow |= FILE_GENERIC_READ;
@@ -494,9 +501,15 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
&& (attribute & (S_IWGRP | S_IXGRP)) == (S_IWGRP | S_IXGRP)
&& !(attribute & S_ISVTX))
group_allow |= FILE_DELETE_CHILD;
+ /* For sync objects, add STANDARD_RIGHTS_ALL for admins group. */
+ if (S_ISCHR (attribute) && group_sid == well_known_admins_sid)
+ {
+ group_allow |= STANDARD_RIGHTS_ALL;
+ saw_admins = true;
+ }
/* Construct allow attribute for everyone. */
- DWORD other_allow = STANDARD_RIGHTS_READ
+ DWORD other_allow = STANDARD_RIGHTS_READ | SYNCHRONIZE
| (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
if (attribute & S_IROTH)
other_allow |= FILE_GENERIC_READ;
@@ -560,6 +573,17 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
group_sid, acl_len, NO_INHERITANCE))
return NULL;
+ /* For sync objects, if we didn't see the admins group so far, add entry
+ with STANDARD_RIGHTS_ALL access. */
+ if (S_ISCHR (attribute) && !saw_admins)
+ {
+ if (!add_access_allowed_ace (acl, ace_off++, STANDARD_RIGHTS_ALL,
+ well_known_admins_sid, acl_len,
+ NO_INHERITANCE))
+ return NULL;
+ saw_admins = true;
+ }
+
/* Set allow ACE for everyone. */
if (!add_access_allowed_ace (acl, ace_off++, other_allow,
well_known_world_sid, acl_len, NO_INHERITANCE))
@@ -582,7 +606,8 @@ alloc_sd (path_conv &pc, __uid32_t uid, __gid32_t gid, int attribute,
cygpsid ace_sid ((PSID) &ace->SidStart);
/* Check for related ACEs. */
- if (ace_sid == well_known_null_sid)
+ if (ace_sid == well_known_null_sid
+ || (S_ISCHR (attribute) && ace_sid == well_known_admins_sid))
continue;
if ((ace_sid == cur_owner_sid)
|| (ace_sid == owner_sid)
@@ -717,8 +742,85 @@ set_security_attribute (path_conv &pc, int attribute, PSECURITY_ATTRIBUTES psa,
}
int
+get_object_sd (HANDLE handle, security_descriptor &sd)
+{
+ ULONG len = 0;
+ NTSTATUS status;
+
+ status = NtQuerySecurityObject (handle, ALL_SECURITY_INFORMATION,
+ sd, len, &len);
+ if (status != STATUS_BUFFER_TOO_SMALL)
+ {
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ if (!sd.malloc (len))
+ {
+ set_errno (ENOMEM);
+ return -1;
+ }
+ status = NtQuerySecurityObject (handle, ALL_SECURITY_INFORMATION,
+ sd, len, &len);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ return 0;
+}
+
+int
+get_object_attribute (HANDLE handle, __uid32_t *uidret, __gid32_t *gidret,
+ mode_t *attribute)
+{
+ security_descriptor sd;
+
+ if (get_object_sd (handle, sd))
+ return -1;
+ get_info_from_sd (sd, attribute, uidret, gidret);
+ return 0;
+}
+
+int
+create_object_sd_from_attribute (HANDLE handle, __uid32_t uid, __gid32_t gid,
+ mode_t attribute, security_descriptor &sd)
+{
+ path_conv pc;
+ if ((handle && get_object_sd (handle, sd))
+ || !alloc_sd (pc, uid, gid, attribute, sd))
+ return -1;
+ return 0;
+}
+
+int
+set_object_sd (HANDLE handle, security_descriptor &sd, bool chown)
+{
+ NTSTATUS status;
+ status = NtSetSecurityObject (handle, chown ? ALL_SECURITY_INFORMATION
+ : DACL_SECURITY_INFORMATION, sd);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ return 0;
+}
+
+int
+set_object_attribute (HANDLE handle, __uid32_t uid, __gid32_t gid,
+ mode_t attribute)
+{
+ security_descriptor sd;
+
+ if (create_object_sd_from_attribute (handle, uid, gid, attribute, sd)
+ || set_object_sd (handle, sd, uid != ILLEGAL_UID || gid != ILLEGAL_GID))
+ return -1;
+ return 0;
+}
+
+int
set_file_attribute (HANDLE handle, path_conv &pc,
- __uid32_t uid, __gid32_t gid, int attribute)
+ __uid32_t uid, __gid32_t gid, mode_t attribute)
{
int ret = -1;
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index dcc080f2f..dde4d214e 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -350,7 +350,14 @@ class path_conv;
int __stdcall get_file_attribute (HANDLE, path_conv &, mode_t *,
__uid32_t *, __gid32_t *);
int __stdcall set_file_attribute (HANDLE, path_conv &,
- __uid32_t, __gid32_t, int);
+ __uid32_t, __gid32_t, mode_t);
+int __stdcall get_object_sd (HANDLE, security_descriptor &);
+int __stdcall get_object_attribute (HANDLE, __uid32_t *, __gid32_t *, mode_t *);
+int __stdcall set_object_attribute (HANDLE, __uid32_t, __gid32_t, mode_t);
+int __stdcall create_object_sd_from_attribute (HANDLE, __uid32_t, __gid32_t,
+ mode_t, security_descriptor &);
+int __stdcall set_object_sd (HANDLE, security_descriptor &, bool);
+
int __stdcall get_reg_attribute (HKEY hkey, mode_t *, __uid32_t *, __gid32_t *);
LONG __stdcall get_file_sd (HANDLE fh, path_conv &, security_descriptor &sd);
LONG __stdcall set_file_sd (HANDLE fh, path_conv &, security_descriptor &sd,
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index e7018106d..0991cd66d 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -1,7 +1,7 @@
/* tty.cc
- Copyright 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009
- Red Hat, Inc.
+ Copyright 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009,
+ 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -287,12 +287,6 @@ out:
}
bool
-tty::slave_alive ()
-{
- return alive (TTY_SLAVE_ALIVE);
-}
-
-bool
tty::exists ()
{
/* Attempt to open the from-master side of the tty. If it is accessible
@@ -307,7 +301,7 @@ tty::exists ()
CloseHandle (r);
CloseHandle (w);
- HANDLE h = open_output_mutex ();
+ HANDLE h = open_output_mutex (READ_CONTROL);
if (h)
{
CloseHandle (h);
@@ -317,45 +311,38 @@ tty::exists ()
}
bool
-tty::alive (const char *fmt)
+tty::slave_alive ()
{
HANDLE ev;
- char buf[MAX_PATH];
-
- shared_name (buf, fmt, ntty);
- if ((ev = OpenEvent (EVENT_ALL_ACCESS, FALSE, buf)))
+ if ((ev = open_inuse (READ_CONTROL)))
CloseHandle (ev);
return ev != NULL;
}
HANDLE
-tty::open_output_mutex ()
+tty::open_mutex (const char *mutex, ACCESS_MASK access)
{
- return open_mutex (OUTPUT_MUTEX);
-}
-
-HANDLE
-tty::open_input_mutex ()
-{
- return open_mutex (INPUT_MUTEX);
+ char buf[MAX_PATH];
+ shared_name (buf, mutex, ntty);
+ return OpenMutex (access, TRUE, buf);
}
HANDLE
-tty::open_mutex (const char *mutex)
+tty::open_inuse (ACCESS_MASK access)
{
char buf[MAX_PATH];
- shared_name (buf, mutex, ntty);
- return OpenMutex (MUTEX_ALL_ACCESS, TRUE, buf);
+ shared_name (buf, TTY_SLAVE_ALIVE, ntty);
+ return OpenEvent (access, FALSE, buf);
}
HANDLE
-tty::create_inuse (const char *fmt)
+tty::create_inuse (PSECURITY_ATTRIBUTES sa)
{
HANDLE h;
char buf[MAX_PATH];
- shared_name (buf, fmt, ntty);
- h = CreateEvent (&sec_all, TRUE, FALSE, buf);
+ shared_name (buf, TTY_SLAVE_ALIVE, ntty);
+ h = CreateEvent (sa, TRUE, FALSE, buf);
termios_printf ("%s %p", buf, h);
if (!h)
termios_printf ("couldn't open inuse event, %E", buf);
@@ -374,13 +361,15 @@ tty::init ()
}
HANDLE
-tty::get_event (const char *fmt, BOOL manual_reset)
+tty::get_event (const char *fmt, PSECURITY_ATTRIBUTES sa, BOOL manual_reset)
{
HANDLE hev;
char buf[MAX_PATH];
shared_name (buf, fmt, ntty);
- if (!(hev = CreateEvent (&sec_all, manual_reset, FALSE, buf)))
+ if (!sa)
+ sa = &sec_all;
+ if (!(hev = CreateEvent (sa, manual_reset, FALSE, buf)))
{
termios_printf ("couldn't create %s", buf);
set_errno (ENOENT); /* FIXME this can't be the right errno */
diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h
index b4c02a411..630bdb048 100644
--- a/winsup/cygwin/tty.h
+++ b/winsup/cygwin/tty.h
@@ -1,6 +1,6 @@
/* tty.h: shared tty info for cygwin
- Copyright 2000, 2001, 2002, 2003, 2004, 2006 Red Hat, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2006, 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -84,7 +84,8 @@ class fhandler_pty_master;
class tty: public tty_min
{
- HANDLE get_event (const char *fmt, BOOL manual_reset = FALSE)
+ HANDLE get_event (const char *fmt, PSECURITY_ATTRIBUTES sa,
+ BOOL manual_reset = FALSE);
__attribute__ ((regparm (3)));
public:
pid_t master_pid; /* PID of tty master process */
@@ -95,13 +96,14 @@ public:
bool was_opened; /* True if opened at least once. */
void init ();
- HANDLE create_inuse (const char *);
- bool alive (const char *fmt);
+ HANDLE open_inuse (ACCESS_MASK access);
+ HANDLE create_inuse (PSECURITY_ATTRIBUTES);
bool slave_alive ();
- bool master_alive ();
- HANDLE open_mutex (const char *mutex);
- HANDLE open_output_mutex ();
- HANDLE open_input_mutex ();
+ HANDLE open_mutex (const char *mutex, ACCESS_MASK access);
+ inline HANDLE open_output_mutex (ACCESS_MASK access)
+ { return open_mutex (OUTPUT_MUTEX, access); }
+ inline HANDLE open_input_mutex (ACCESS_MASK access)
+ { return open_mutex (INPUT_MUTEX, access); }
bool exists ();
void set_master_closed () {master_pid = -1;}
static void __stdcall create_master (int);