diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 442569799..49093a524 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +2005-02-28 Corinna Vinschen + + * fhandler.h (class fhandler_socket): Declare new method + set_socketpair_eids. + * fhandler_socket.cc (fhandler_socket::set_socketpair_eids): New method. + (fhandler_socket::dup): Duplicate sec_pipe if necessary. + (fhandler_socket::listen): Only create sec_pipe if named pipes are + available. Initialized sec_peer_pid to 0 as on Linux. + (fhandler_socket::connect): Only run eid credential transaction if + named pipes are available. Fake otherwise. Initialized sec_peer_pid + to 0 as on Linux. + (fhandler_socket::accept): Ditto. + (fhandler_socket::close): Move closing sec_pipe handle from here... + (fhandler_socket::~fhandler_socket): ... to here. + * net.cc (socketpair): Set eid credentials by calling + fhandler_socket::set_socketpair_eids() on both socket ends. + * wincap.h (wincaps::has_named_pipes): New element. + * wincap.cc: Implement above element throughout. + 2005-02-26 Christopher Faylor * sigproc.cc (_pinfo::set_ctty): Move function diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 2d9aa5f7f..bdc8d3b8a 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -365,7 +365,10 @@ class fhandler_socket: public fhandler_base __uid32_t sec_peer_uid; __gid32_t sec_peer_gid; char *eid_pipe_name (char *buf); + public: + void set_socketpair_eids (void); + private: struct _WSAPROTOCOL_INFOA *prot_info_ptr; char *sun_path; struct status_flags diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index b5b4847ec..ee93ff517 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -60,6 +60,14 @@ fhandler_socket::eid_pipe_name (char *buf) return buf; } +void +fhandler_socket::set_socketpair_eids (void) +{ + sec_pid = sec_peer_pid = getpid (); + sec_uid = sec_peer_uid = geteuid32 (); + sec_gid = sec_peer_gid = getegid32 (); +} + /* cygwin internal: map sockaddr into internet domain address */ static int get_inet_addr (const struct sockaddr *in, int inlen, @@ -154,6 +162,9 @@ fhandler_socket::~fhandler_socket () cfree (prot_info_ptr); if (sun_path) cfree (sun_path); + /* Close eid credentials pipe handle. */ + if (sec_pipe != INVALID_HANDLE_VALUE) + CloseHandle (sec_pipe); } char *fhandler_socket::get_proc_fd_name (char *buf) @@ -341,12 +352,37 @@ fhandler_socket::fixup_after_exec () int fhandler_socket::dup (fhandler_base *child) { + HANDLE nh; + debug_printf ("here"); fhandler_socket *fhs = (fhandler_socket *) child; fhs->addr_family = addr_family; - if (get_addr_family () == AF_LOCAL) - fhs->set_sun_path (get_sun_path ()); fhs->set_socket_type (get_socket_type ()); + if (get_addr_family () == AF_LOCAL) + { + fhs->set_sun_path (get_sun_path ()); + if (get_socket_type () == SOCK_STREAM) + { + fhs->sec_pid = sec_pid; + fhs->sec_uid = sec_uid; + fhs->sec_gid = sec_gid; + fhs->sec_peer_pid = sec_peer_pid; + fhs->sec_peer_uid = sec_peer_uid; + fhs->sec_peer_gid = sec_peer_gid; + if (sec_pipe != INVALID_HANDLE_VALUE) + { + if (!DuplicateHandle (hMainProc, sec_pipe, hMainProc, &nh, 0, + TRUE, DUPLICATE_SAME_ACCESS)) + { + system_printf ("!DuplicateHandle(%x) failed, %E", sec_pipe); + __seterrno (); + return -1; + } + else + fhs->sec_pipe = nh; + } + } + } fhs->connect_state (connect_state ()); if (winsock2_active) @@ -378,12 +414,13 @@ fhandler_socket::dup (fhandler_base *child) having winsock called from fhandler_base and it creates only inheritable sockets which is wrong for winsock2. */ - HANDLE nh; if (!DuplicateHandle (hMainProc, get_io_handle (), hMainProc, &nh, 0, !winsock2_active, DUPLICATE_SAME_ACCESS)) { system_printf ("!DuplicateHandle(%x) failed, %E", get_io_handle ()); __seterrno (); + if (fhs->sec_pipe != INVALID_HANDLE_VALUE) + CloseHandle (fhs->sec_pipe); return -1; } VerifyHandle (nh); @@ -630,20 +667,30 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) } /* eid credential transaction. */ - struct ucred in = { getpid (), geteuid32 (), getegid32 () }; - struct ucred out = { (pid_t) -1, (__uid32_t) -1, (__gid32_t) -1 }; - DWORD bytes = 0; - if (CallNamedPipe(eid_pipe_name ((char *) alloca (CYG_MAX_PATH + 1)), - &in, sizeof in, &out, sizeof out, &bytes, 1000)) - { - debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d", - out.pid, out.uid, out.gid); - sec_peer_pid = out.pid; - sec_peer_uid = out.uid; - sec_peer_gid = out.gid; - } - else - debug_printf ("Receiving eid credentials failed: %E"); + if (wincap.has_named_pipes ()) + { + struct ucred in = { getpid (), geteuid32 (), getegid32 () }; + struct ucred out = { (pid_t) 0, (__uid32_t) -1, (__gid32_t) -1 }; + DWORD bytes = 0; + if (CallNamedPipe(eid_pipe_name ((char *) alloca (CYG_MAX_PATH + 1)), + &in, sizeof in, &out, sizeof out, &bytes, 1000)) + { + debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d", + out.pid, out.uid, out.gid); + sec_peer_pid = out.pid; + sec_peer_uid = out.uid; + sec_peer_gid = out.gid; + } + else + debug_printf ("Receiving eid credentials failed: %E"); + } + else /* 9x */ + { + /* Incorrect but wrong pid at least doesn't break getpeereid. */ + sec_peer_pid = getpid (); + sec_peer_uid = geteuid32 (); + sec_peer_gid = getegid32 (); + } } err = WSAGetLastError (); @@ -669,10 +716,13 @@ fhandler_socket::listen (int backlog) sec_pid = getpid (); sec_uid = geteuid32 (); sec_gid = getegid32 (); - sec_peer_pid = (pid_t) -1; + sec_peer_pid = (pid_t) 0; sec_peer_uid = (__uid32_t) -1; sec_peer_gid = (__gid32_t) -1; - sec_pipe = + /* A listening socket can call listen again, but that shouldn't + result in trying to create another pipe. */ + if (wincap.has_named_pipes () && sec_pipe == INVALID_HANDLE_VALUE) + sec_pipe = CreateNamedPipe (eid_pipe_name ((char *) alloca (CYG_MAX_PATH + 1)), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, @@ -692,7 +742,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len) bool secret_check_failed = false; bool in_progress = false; struct ucred in = { sec_pid, sec_uid, sec_gid }; - struct ucred out = { (pid_t) -1, (__uid32_t) -1, (__gid32_t) -1 }; + struct ucred out = { (pid_t) 0, (__uid32_t) -1, (__gid32_t) -1 }; /* Allows NULL peer and len parameters. */ struct sockaddr_in peer_dummy; @@ -747,21 +797,31 @@ fhandler_socket::accept (struct sockaddr *peer, int *len) } /* eid credential transaction. */ - DWORD bytes = 0; - bool ret = ConnectNamedPipe (sec_pipe, NULL); - if (ret || GetLastError () == ERROR_PIPE_CONNECTED) + if (wincap.has_named_pipes ()) { - if (!ReadFile (sec_pipe, &out, sizeof out, &bytes, NULL)) - debug_printf ("Receiving eid credentials failed: %E"); + DWORD bytes = 0; + bool ret = ConnectNamedPipe (sec_pipe, NULL); + if (ret || GetLastError () == ERROR_PIPE_CONNECTED) + { + if (!ReadFile (sec_pipe, &out, sizeof out, &bytes, NULL)) + debug_printf ("Receiving eid credentials failed: %E"); + else + debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d", + out.pid, out.uid, out.gid); + if (!WriteFile (sec_pipe, &in, sizeof in, &bytes, NULL)) + debug_printf ("Sending eid credentials failed: %E"); + DisconnectNamedPipe (sec_pipe); + } else - debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d", - out.pid, out.uid, out.gid); - if (!WriteFile (sec_pipe, &in, sizeof in, &bytes, NULL)) - debug_printf ("Sending eid credentials failed: %E"); - DisconnectNamedPipe (sec_pipe); + debug_printf ("Connecting the eid credential pipe failed: %E"); + } + else /* 9x */ + { + /* Incorrect but wrong pid at least doesn't break getpeereid. */ + out.pid = sec_pid; + out.uid = sec_uid; + out.gid = sec_gid; } - else - debug_printf ("Connecting the eid credential pipe failed: %E"); } if ((SOCKET) res == INVALID_SOCKET) @@ -1392,10 +1452,6 @@ fhandler_socket::close () setsockopt (get_socket (), SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof linger); - /* Close eid credentials pipe handle. */ - if (sec_pipe != INVALID_HANDLE_VALUE) - CloseHandle (sec_pipe); - while ((res = closesocket (get_socket ())) != 0) { if (WSAGetLastError () != WSAEWOULDBLOCK) diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 98e121c5a..472e97c3e 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -2198,6 +2198,8 @@ socketpair (int family, int type, int protocol, int *sb) ((fhandler_socket *) sb0)->set_addr_family (family); ((fhandler_socket *) sb0)->set_socket_type (type); ((fhandler_socket *) sb0)->connect_state (connected); + if (family == AF_LOCAL && type == SOCK_STREAM) + ((fhandler_socket *) sb0)->set_socketpair_eids (); cygheap_fdnew sb1 (sb0, false); @@ -2207,6 +2209,8 @@ socketpair (int family, int type, int protocol, int *sb) ((fhandler_socket *) sb1)->set_addr_family (family); ((fhandler_socket *) sb1)->set_socket_type (type); ((fhandler_socket *) sb1)->connect_state (connected); + if (family == AF_LOCAL && type == SOCK_STREAM) + ((fhandler_socket *) sb1)->set_socketpair_eids (); sb[0] = sb0; sb[1] = sb1; diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 4011b5dec..9a790b087 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -42,6 +42,7 @@ static NO_COPY wincaps wincap_unknown = { has_move_file_ex:false, has_negative_pids:false, has_unreliable_pipes:false, + has_named_pipes:false, has_try_enter_critical_section:false, has_raw_devices:false, has_valid_processorlevel:false, @@ -90,6 +91,7 @@ static NO_COPY wincaps wincap_95 = { has_move_file_ex:false, has_negative_pids:true, has_unreliable_pipes:true, + has_named_pipes:false, has_try_enter_critical_section:false, has_raw_devices:false, has_valid_processorlevel:false, @@ -138,6 +140,7 @@ static NO_COPY wincaps wincap_95osr2 = { has_move_file_ex:false, has_negative_pids:true, has_unreliable_pipes:true, + has_named_pipes:false, has_try_enter_critical_section:false, has_raw_devices:false, has_valid_processorlevel:false, @@ -186,6 +189,7 @@ static NO_COPY wincaps wincap_98 = { has_move_file_ex:false, has_negative_pids:true, has_unreliable_pipes:true, + has_named_pipes:false, has_try_enter_critical_section:false, has_raw_devices:false, has_valid_processorlevel:true, @@ -234,6 +238,7 @@ static NO_COPY wincaps wincap_98se = { has_move_file_ex:false, has_negative_pids:true, has_unreliable_pipes:true, + has_named_pipes:false, has_try_enter_critical_section:false, has_raw_devices:false, has_valid_processorlevel:true, @@ -282,6 +287,7 @@ static NO_COPY wincaps wincap_me = { has_move_file_ex:false, has_negative_pids:true, has_unreliable_pipes:true, + has_named_pipes:false, has_try_enter_critical_section:false, has_raw_devices:false, has_valid_processorlevel:true, @@ -330,6 +336,7 @@ static NO_COPY wincaps wincap_nt3 = { has_move_file_ex:true, has_negative_pids:false, has_unreliable_pipes:false, + has_named_pipes:true, has_try_enter_critical_section:false, has_raw_devices:true, has_valid_processorlevel:true, @@ -378,6 +385,7 @@ static NO_COPY wincaps wincap_nt4 = { has_move_file_ex:true, has_negative_pids:false, has_unreliable_pipes:false, + has_named_pipes:true, has_try_enter_critical_section:true, has_raw_devices:true, has_valid_processorlevel:true, @@ -426,6 +434,7 @@ static NO_COPY wincaps wincap_nt4sp4 = { has_move_file_ex:true, has_negative_pids:false, has_unreliable_pipes:false, + has_named_pipes:true, has_try_enter_critical_section:true, has_raw_devices:true, has_valid_processorlevel:true, @@ -474,6 +483,7 @@ static NO_COPY wincaps wincap_2000 = { has_move_file_ex:true, has_negative_pids:false, has_unreliable_pipes:false, + has_named_pipes:true, has_try_enter_critical_section:true, has_raw_devices:true, has_valid_processorlevel:true, @@ -522,6 +532,7 @@ static NO_COPY wincaps wincap_xp = { has_move_file_ex:true, has_negative_pids:false, has_unreliable_pipes:false, + has_named_pipes:true, has_try_enter_critical_section:true, has_raw_devices:true, has_valid_processorlevel:true, @@ -570,6 +581,7 @@ static NO_COPY wincaps wincap_2003 = { has_move_file_ex:true, has_negative_pids:false, has_unreliable_pipes:false, + has_named_pipes:true, has_try_enter_critical_section:true, has_raw_devices:true, has_valid_processorlevel:true, diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index c6c54b0c1..6d7d63ec9 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -43,6 +43,7 @@ struct wincaps unsigned has_move_file_ex : 1; unsigned has_negative_pids : 1; unsigned has_unreliable_pipes : 1; + unsigned has_named_pipes : 1; unsigned has_try_enter_critical_section : 1; unsigned has_raw_devices : 1; unsigned has_valid_processorlevel : 1; @@ -105,6 +106,7 @@ public: bool IMPLEMENT (has_move_file_ex) bool IMPLEMENT (has_negative_pids) bool IMPLEMENT (has_unreliable_pipes) + bool IMPLEMENT (has_named_pipes) bool IMPLEMENT (has_try_enter_critical_section) bool IMPLEMENT (has_raw_devices) bool IMPLEMENT (has_valid_processorlevel)