* dtable.cc (dtable::vfork_parent_restore): Add debugging statement.
* exceptions.cc (try_to_debug): Spin only as long as we don't have a debugger attached. * fhandler.h (fhandler_base::set_nohandle): New method. (fhandler_base::get_nohandle): New method. * fhandler.cc (fhandler_base::dup): Avoid duplicating handle if there is no handle. * fhandler_disk_file.cc (fhandler_disk_file::opendir): Set nohandle flag on dummy fd. * Makefile.in: Make intermediate library for eventual inclusion in libcygwin.a * fhandler.h (fhandler_pipe::fhandler_pipe): Remove default argument setting since it is no longer used. * miscfuncs.cc (check_null_str): New function. (+check_null_str_errno): Ditto. * net.cc: Add defensive buffer checking throughout. (cygwin_sendto): Protect against invalid fd. (cygwin_recvfrom): Ditto. (cygwin_getpeername): Ditto. (cygwin_recv): Ditto. (cygwin_send): Ditto. * winsup.h: Declare a new function. * select.cc (set_bits): Fix conditional for setting fd in exceptfds. * dtable.cc (dtable::build_fhandler): Create fhandler_pipe using correct device type. * path.cc (get_devn): Set correct pipe device type from device name.
This commit is contained in:
@ -117,6 +117,17 @@ wsock_event::wait (int socket, LPDWORD flags)
|
||||
|
||||
WSADATA wsadata;
|
||||
|
||||
/* Cygwin internal */
|
||||
static fhandler_socket *
|
||||
get (int fd)
|
||||
{
|
||||
cygheap_fdget cfd (fd);
|
||||
if (cfd < 0)
|
||||
return 0;
|
||||
|
||||
return cfd->is_socket ();
|
||||
}
|
||||
|
||||
/* Cygwin internal */
|
||||
static SOCKET __stdcall
|
||||
set_socket_inheritance (SOCKET sock)
|
||||
@ -205,6 +216,9 @@ cygwin_inet_addr (const char *cp)
|
||||
extern "C" int
|
||||
cygwin_inet_aton (const char *cp, struct in_addr *inp)
|
||||
{
|
||||
if (check_null_str_errno (cp) || check_null_invalid_struct_errno (inp))
|
||||
return 0;
|
||||
|
||||
unsigned long res = inet_addr (cp);
|
||||
if (res == INADDR_NONE && strcmp (cp, "255.255.255.255"))
|
||||
return 0;
|
||||
@ -219,6 +233,8 @@ extern "C" unsigned int WINAPI inet_network (const char *);
|
||||
extern "C" unsigned int
|
||||
cygwin_inet_network (const char *cp)
|
||||
{
|
||||
if (check_null_str_errno (cp))
|
||||
return 0;
|
||||
unsigned int res = inet_network (cp);
|
||||
return res;
|
||||
}
|
||||
@ -232,7 +248,6 @@ inet_netof (struct in_addr in)
|
||||
{
|
||||
unsigned long i, res;
|
||||
|
||||
|
||||
i = ntohl (in.s_addr);
|
||||
if (IN_CLASSA (i))
|
||||
res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
|
||||
@ -253,8 +268,7 @@ extern "C" struct in_addr
|
||||
inet_makeaddr (int net, int lna)
|
||||
{
|
||||
unsigned long i;
|
||||
struct in_addr in;
|
||||
|
||||
static struct in_addr in; /* Note -- not thread safe! */
|
||||
|
||||
if (net < IN_CLASSA_MAX)
|
||||
i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
|
||||
@ -473,6 +487,8 @@ out:
|
||||
extern "C" struct protoent *
|
||||
cygwin_getprotobyname (const char *p)
|
||||
{
|
||||
if (check_null_str_errno (p))
|
||||
return NULL;
|
||||
free_protoent_ptr (protoent_buf);
|
||||
protoent_buf = dup_protoent_ptr (getprotobyname (p));
|
||||
if (!protoent_buf)
|
||||
@ -604,37 +620,45 @@ cygwin_sendto (int fd,
|
||||
int res;
|
||||
wsock_event wsock_evt;
|
||||
LPWSAOVERLAPPED ovr;
|
||||
fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
|
||||
sockaddr_in sin;
|
||||
sigframe thisframe (mainthread);
|
||||
fhandler_socket *h = get (fd);
|
||||
|
||||
if (get_inet_addr (to, tolen, &sin, &tolen) == 0)
|
||||
return -1;
|
||||
|
||||
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
debug_printf ("Fallback to winsock 1 sendto call");
|
||||
if ((res = sendto (h->get_socket (), (const char *) buf, len, flags,
|
||||
(sockaddr *) &sin, tolen)) == SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len))
|
||||
|| __check_null_invalid_struct_errno (to, tolen)
|
||||
|| !h)
|
||||
res = -1;
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
|
||||
(sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
sockaddr_in sin;
|
||||
sigframe thisframe (mainthread);
|
||||
|
||||
if (get_inet_addr (to, tolen, &sin, &tolen) == 0)
|
||||
return -1;
|
||||
|
||||
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
debug_printf ("Fallback to winsock 1 sendto call");
|
||||
if ((res = sendto (h->get_socket (), (const char *) buf, len, flags,
|
||||
(sockaddr *) &sin, tolen)) == SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
|
||||
(sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
|
||||
syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags);
|
||||
@ -654,33 +678,42 @@ cygwin_recvfrom (int fd,
|
||||
int res;
|
||||
wsock_event wsock_evt;
|
||||
LPWSAOVERLAPPED ovr;
|
||||
fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
|
||||
sigframe thisframe (mainthread);
|
||||
fhandler_socket *h = get (fd);
|
||||
|
||||
if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
debug_printf ("Fallback to winsock 1 recvfrom call");
|
||||
if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen))
|
||||
== SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
if (__check_null_invalid_struct_errno (buf, (unsigned) len)
|
||||
|| check_null_invalid_struct_errno (fromlen)
|
||||
|| __check_null_invalid_struct_errno (from, (unsigned) *fromlen)
|
||||
|| !h)
|
||||
res = -1;
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
|
||||
from, fromlen, ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
sigframe thisframe (mainthread);
|
||||
|
||||
if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
debug_printf ("Fallback to winsock 1 recvfrom call");
|
||||
if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen))
|
||||
== SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
|
||||
from, fromlen, ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
|
||||
syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags);
|
||||
@ -688,17 +721,6 @@ cygwin_recvfrom (int fd,
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Cygwin internal */
|
||||
fhandler_socket *
|
||||
get (int fd)
|
||||
{
|
||||
cygheap_fdget cfd (fd);
|
||||
if (cfd < 0)
|
||||
return 0;
|
||||
|
||||
return cfd->is_socket ();
|
||||
}
|
||||
|
||||
/* exported as setsockopt: standards? */
|
||||
extern "C" int
|
||||
cygwin_setsockopt (int fd,
|
||||
@ -711,7 +733,7 @@ cygwin_setsockopt (int fd,
|
||||
int res = -1;
|
||||
const char *name = "error";
|
||||
|
||||
if (h)
|
||||
if (!__check_invalid_read_ptr_errno (optval, optlen) && h)
|
||||
{
|
||||
/* For the following debug_printf */
|
||||
switch (optname)
|
||||
@ -774,7 +796,9 @@ cygwin_getsockopt (int fd,
|
||||
fhandler_socket *h = get (fd);
|
||||
int res = -1;
|
||||
const char *name = "error";
|
||||
if (h)
|
||||
if (!check_null_invalid_struct_errno (optlen)
|
||||
&& !__check_null_invalid_struct_errno (optval, (unsigned) optlen)
|
||||
&& h)
|
||||
{
|
||||
/* For the following debug_printf */
|
||||
switch (optname)
|
||||
@ -843,13 +867,14 @@ cygwin_connect (int fd,
|
||||
int secret [4];
|
||||
sigframe thisframe (mainthread);
|
||||
|
||||
if (__check_invalid_read_ptr_errno (name, namelen))
|
||||
return -1;
|
||||
|
||||
if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0)
|
||||
return -1;
|
||||
|
||||
if (!sock)
|
||||
{
|
||||
res = -1;
|
||||
}
|
||||
res = -1;
|
||||
else
|
||||
{
|
||||
res = connect (sock->get_socket (), (sockaddr *) &sin, namelen);
|
||||
@ -975,6 +1000,10 @@ out:
|
||||
extern "C" struct servent *
|
||||
cygwin_getservbyname (const char *name, const char *proto)
|
||||
{
|
||||
if (check_null_str_errno (name)
|
||||
|| (proto != NULL && check_null_str_errno (proto)))
|
||||
return NULL;
|
||||
|
||||
free_servent_ptr (servent_buf);
|
||||
servent_buf = dup_servent_ptr (getservbyname (name, proto));
|
||||
if (!servent_buf)
|
||||
@ -988,6 +1017,9 @@ cygwin_getservbyname (const char *name, const char *proto)
|
||||
extern "C" struct servent *
|
||||
cygwin_getservbyport (int port, const char *proto)
|
||||
{
|
||||
if (proto != NULL && check_null_str_errno (proto))
|
||||
return NULL;
|
||||
|
||||
free_servent_ptr (servent_buf);
|
||||
servent_buf = dup_servent_ptr (getservbyport (port, proto));
|
||||
if (!servent_buf)
|
||||
@ -1002,6 +1034,9 @@ cygwin_gethostname (char *name, size_t len)
|
||||
{
|
||||
int PASCAL win32_gethostname (char*, int);
|
||||
|
||||
if (__check_null_invalid_struct_errno (name, len))
|
||||
return -1;
|
||||
|
||||
if (wsock32_handle == NULL ||
|
||||
win32_gethostname (name, len) == SOCKET_ERROR)
|
||||
{
|
||||
@ -1080,6 +1115,9 @@ cygwin_gethostbyname (const char *name)
|
||||
static char *tmp_addr_list[2];
|
||||
static int a, b, c, d;
|
||||
|
||||
if (check_null_str_errno (name))
|
||||
return NULL;
|
||||
|
||||
if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
|
||||
{
|
||||
/* In case you don't have DNS, at least x.x.x.x still works */
|
||||
@ -1116,6 +1154,9 @@ cygwin_gethostbyname (const char *name)
|
||||
extern "C" struct hostent *
|
||||
cygwin_gethostbyaddr (const char *addr, int len, int type)
|
||||
{
|
||||
if (__check_null_invalid_struct_errno (addr, len))
|
||||
return NULL;
|
||||
|
||||
free_hostent_ptr (hostent_buf);
|
||||
hostent_buf = dup_hostent_ptr (gethostbyaddr (addr, len, type));
|
||||
if (!hostent_buf)
|
||||
@ -1135,6 +1176,11 @@ cygwin_gethostbyaddr (const char *addr, int len, int type)
|
||||
extern "C" int
|
||||
cygwin_accept (int fd, struct sockaddr *peer, int *len)
|
||||
{
|
||||
if (peer != NULL
|
||||
&& (check_null_invalid_struct_errno (len)
|
||||
|| __check_null_invalid_struct_errno (peer, (unsigned) *len)))
|
||||
return -1;
|
||||
|
||||
int res = -1;
|
||||
BOOL secret_check_failed = FALSE;
|
||||
BOOL in_progress = FALSE;
|
||||
@ -1220,6 +1266,9 @@ cygwin_accept (int fd, struct sockaddr *peer, int *len)
|
||||
extern "C" int
|
||||
cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen)
|
||||
{
|
||||
if (__check_null_invalid_struct_errno (my_addr, addrlen))
|
||||
return -1;
|
||||
|
||||
int res = -1;
|
||||
|
||||
fhandler_socket *sock = get (fd);
|
||||
@ -1306,6 +1355,10 @@ out:
|
||||
extern "C" int
|
||||
cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen)
|
||||
{
|
||||
if (check_null_invalid_struct_errno (namelen)
|
||||
|| __check_null_invalid_struct_errno (addr, (unsigned) *namelen))
|
||||
return -1;
|
||||
|
||||
int res = -1;
|
||||
|
||||
fhandler_socket *sock = get (fd);
|
||||
@ -1419,12 +1472,21 @@ cygwin_herror (const char *s)
|
||||
extern "C" int
|
||||
cygwin_getpeername (int fd, struct sockaddr *name, int *len)
|
||||
{
|
||||
fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
|
||||
int res;
|
||||
if (check_null_invalid_struct_errno (len)
|
||||
|| __check_null_invalid_struct_errno (name, (unsigned) *len))
|
||||
return -1;
|
||||
|
||||
debug_printf ("getpeername %d", h->get_socket ());
|
||||
int res = getpeername (h->get_socket (), name, len);
|
||||
if (res)
|
||||
set_winsock_errno ();
|
||||
fhandler_socket *h = get (fd);
|
||||
|
||||
if (!h)
|
||||
res = -1;
|
||||
else
|
||||
{
|
||||
res = getpeername (h->get_socket (), name, len);
|
||||
if (res)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
|
||||
debug_printf ("%d = getpeername %d", res, h->get_socket ());
|
||||
return res;
|
||||
@ -1437,33 +1499,39 @@ cygwin_recv (int fd, void *buf, int len, unsigned int flags)
|
||||
int res;
|
||||
wsock_event wsock_evt;
|
||||
LPWSAOVERLAPPED ovr;
|
||||
fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
|
||||
sigframe thisframe (mainthread);
|
||||
fhandler_socket *h = get (fd);
|
||||
|
||||
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
debug_printf ("Fallback to winsock 1 recv call");
|
||||
if ((res = recv (h->get_socket (), (char *) buf, len, flags))
|
||||
== SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
if (__check_null_invalid_struct_errno (buf, len) || !h)
|
||||
res = -1;
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSARecv (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
|
||||
ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
sigframe thisframe (mainthread);
|
||||
|
||||
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
debug_printf ("Fallback to winsock 1 recv call");
|
||||
if ((res = recv (h->get_socket (), (char *) buf, len, flags))
|
||||
== SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSARecv (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
|
||||
ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
|
||||
syscall_printf ("%d = recv (%d, %x, %x, %x)", res, fd, buf, len, flags);
|
||||
@ -1478,33 +1546,39 @@ cygwin_send (int fd, const void *buf, int len, unsigned int flags)
|
||||
int res;
|
||||
wsock_event wsock_evt;
|
||||
LPWSAOVERLAPPED ovr;
|
||||
fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd];
|
||||
sigframe thisframe (mainthread);
|
||||
fhandler_socket *h = get (fd);
|
||||
|
||||
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
debug_printf ("Fallback to winsock 1 send call");
|
||||
if ((res = send (h->get_socket (), (const char *) buf, len, flags))
|
||||
== SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
if (__check_invalid_read_ptr_errno (buf, len) || !h)
|
||||
res = -1;
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSASend (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
|
||||
ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
sigframe thisframe (mainthread);
|
||||
|
||||
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
debug_printf ("Fallback to winsock 1 send call");
|
||||
if ((res = send (h->get_socket (), (const char *) buf, len, flags))
|
||||
== SOCKET_ERROR)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSABUF wsabuf = { len, (char *) buf };
|
||||
DWORD ret = 0;
|
||||
if (WSASend (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
|
||||
ovr, NULL) != SOCKET_ERROR)
|
||||
res = ret;
|
||||
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
|
||||
{
|
||||
set_winsock_errno ();
|
||||
res = -1;
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
|
||||
set_winsock_errno ();
|
||||
}
|
||||
|
||||
syscall_printf ("%d = send (%d, %x, %d, %x)", res, fd, buf, len, flags);
|
||||
@ -1523,6 +1597,9 @@ getdomainname (char *domain, int len)
|
||||
* in use and include paths for the Domain name in each ?
|
||||
* Punt for now and assume MS-TCP on Win95.
|
||||
*/
|
||||
if (__check_null_invalid_struct_errno (domain, len))
|
||||
return -1;
|
||||
|
||||
reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
|
||||
(!wincap.is_winnt ()) ? "System" : "SYSTEM",
|
||||
"CurrentControlSet", "Services",
|
||||
@ -2039,6 +2116,9 @@ get_ifconf (struct ifconf *ifc, int what)
|
||||
unsigned long lip, lnp;
|
||||
struct sockaddr_in *sa;
|
||||
|
||||
if (check_null_invalid_struct_errno (ifc))
|
||||
return -1;
|
||||
|
||||
/* Union maps buffer to correct struct */
|
||||
struct ifreq *ifr = ifc->ifc_req;
|
||||
|
||||
|
Reference in New Issue
Block a user