From 5a64d8694176dbe7bd0c61c33d6e6cecd54d7a71 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sat, 24 Nov 2001 03:11:39 +0000 Subject: * 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. --- winsup/cygwin/ChangeLog | 39 +++++ winsup/cygwin/Makefile.in | 4 +- winsup/cygwin/dtable.cc | 4 +- winsup/cygwin/exceptions.cc | 12 +- winsup/cygwin/fhandler.cc | 6 +- winsup/cygwin/fhandler.h | 46 +++--- winsup/cygwin/fhandler_disk_file.cc | 1 + winsup/cygwin/miscfuncs.cc | 18 +++ winsup/cygwin/net.cc | 304 +++++++++++++++++++++++------------- winsup/cygwin/path.cc | 6 +- winsup/cygwin/select.cc | 2 +- winsup/cygwin/winsup.h | 1 + 12 files changed, 297 insertions(+), 146 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 935020e28..e3877a00d 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,42 @@ +2001-11-23 Christopher Faylor + + * 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. + +2001-11-23 Christopher Faylor + + * 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. + +2001-11-23 Corinna Vinschen + + * 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. + 2001-11-22 Christopher Faylor * path.cc (conv_path_list): Fix wild indexing into path due to diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 3d9633a4f..243e54ebc 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -191,14 +191,14 @@ new-$(LIB_NAME): $(LIB_NAME) # Rule to build cygwin.dll new-$(DLL_NAME): $(LDSCRIPT) $(DLL_OFILES) $(DEF_FILE) $(DLL_IMPORTS) $(LIBC) $(LIBM) Makefile winver_stamp - $(CXX) $(CXXFLAGS) -nostdlib -Wl,-T$(firstword $^) -Wl,--out-implib,$(LIB_NAME) -shared -o $@ \ + $(CXX) $(CXXFLAGS) -nostdlib -Wl,-T$(firstword $^) -Wl,--out-implib,cygdll.a -shared -o $@ \ -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o winver.o \ $(DLL_IMPORTS) $(MALLOC_OBJ) $(LIBM) $(LIBC) \ -lstdc++ -lgcc -lshell32 -luuid @rm -f stamp-cygwin-lib $(LIB_NAME): new-$(DLL_NAME) $(LIBCOS) stamp-cygwin-lib - $(AR) rcv $(LIB_NAME) $(LIBCOS) + $(AR) rcv $(LIB_NAME) $(LIBCOS) cygdll.a stamp-cygwin-lib: @touch stamp-cygwin-lib diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 48bc1fca0..664b2c92d 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -18,6 +18,7 @@ details. */ #include #include #include +#include #define USE_SYS_TYPES_FD_SET #include @@ -292,7 +293,7 @@ dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit) case FH_PIPE: case FH_PIPER: case FH_PIPEW: - fh = cnew (fhandler_pipe) (); + fh = cnew (fhandler_pipe) (dev); break; case FH_SOCKET: if ((fh = cnew (fhandler_socket) ())) @@ -591,6 +592,7 @@ dtable::vfork_parent_restore () close_all_files (); fhandler_base **deleteme = fds; + assert (fds_on_hold != NULL); fds = fds_on_hold; fds_on_hold = NULL; cfree (deleteme); diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 41a1319db..a9481167b 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -383,19 +383,19 @@ try_to_debug (bool waitloop) &si, &pi); - static int NO_COPY keep_looping = 0; - - if (dbg) + if (!dbg) + system_printf ("Failed to start debugger: %E"); + else { if (!waitloop) return 1; SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE); - while (keep_looping) + while (!IsDebuggerPresent ()) /* spin */; + Sleep (4000); + small_printf ("*** continuing from debugger call\n"); } - - system_printf ("Failed to start debugger: %E"); /* FIXME: need to know handles of all running threads to resume_all_threads_except (current_thread_id); */ diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index e61b90ee9..21f4fb39c 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -916,7 +916,9 @@ fhandler_base::dup (fhandler_base *child) debug_printf ("in fhandler_base dup"); HANDLE nh; - if (!DuplicateHandle (hMainProc, get_handle(), hMainProc, &nh, 0, TRUE, + if (get_nohandle ()) + nh = NULL; + else if (!DuplicateHandle (hMainProc, get_handle(), hMainProc, &nh, 0, TRUE, DUPLICATE_SAME_ACCESS)) { system_printf ("dup(%s) failed, handle %x, %E", @@ -1151,7 +1153,7 @@ fhandler_base::fixup_after_fork (HANDLE parent) fork_fixup (parent, io_handle, "io_handle"); } -int +bool fhandler_base::is_nonblocking () { return (openflags & O_NONBLOCK_MASK) != 0; diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 07864fca1..3e89a3bba 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -30,7 +30,7 @@ enum FH_W95LSBUG = 0x00400000, /* set when lseek is called as a flag that * _write should check if we've moved beyond * EOF, zero filling if so. */ - FH_UNUSED = 0x00800000, /* currently unused. */ + FH_NOHANDLE = 0x00800000, /* No handle associated with fhandler. */ FH_NOEINTR = 0x01000000, /* Set if I/O should be uninterruptible. */ FH_FFIXUP = 0x02000000, /* Set if need to fixup after fork. */ FH_LOCAL = 0x04000000, /* File is unix domain socket */ @@ -167,25 +167,29 @@ class fhandler_base int get_access () { return access; } void set_access (int x) { access = x; } - int get_async () { return FHISSETF (ASYNC); } + bool get_async () { return FHISSETF (ASYNC); } void set_async (int x) { FHCONDSETF (x, ASYNC); } int get_flags () { return openflags; } void set_flags (int x) { openflags = x; } - int is_nonblocking (); + bool is_nonblocking (); void set_nonblocking (int yes); - int get_w_binary () { return FHISSETF (WBINARY); } - int get_r_binary () { return FHISSETF (RBINARY); } + bool get_w_binary () { return FHISSETF (WBINARY); } + bool get_r_binary () { return FHISSETF (RBINARY); } - int get_w_binset () { return FHISSETF (WBINSET); } - int get_r_binset () { return FHISSETF (RBINSET); } + bool get_w_binset () { return FHISSETF (WBINSET); } + bool get_r_binset () { return FHISSETF (RBINSET); } void set_w_binary (int b) { FHCONDSETF (b, WBINARY); FHSETF (WBINSET); } void set_r_binary (int b) { FHCONDSETF (b, RBINARY); FHSETF (RBINSET); } void clear_w_binary () {FHCLEARF (WBINARY); FHCLEARF (WBINSET); } void clear_r_binary () {FHCLEARF (RBINARY); FHCLEARF (RBINSET); } + + bool get_nohandle () { return FHISSETF (NOHANDLE); } + void set_nohandle (int x) { FHCONDSETF (x, NOHANDLE); } + void set_open_status () {open_status = status;} DWORD get_open_status () {return open_status;} void reset_to_open_binmode () @@ -197,10 +201,10 @@ class fhandler_base int get_default_fmode (int flags); - int get_r_no_interrupt () { return FHISSETF (NOEINTR); } + bool get_r_no_interrupt () { return FHISSETF (NOEINTR); } void set_r_no_interrupt (int b) { FHCONDSETF (b, NOEINTR); } - int get_close_on_exec () { return FHISSETF (CLOEXEC); } + bool get_close_on_exec () { return FHISSETF (CLOEXEC); } int set_close_on_exec_flag (int b) { return FHCONDSETF (b, CLOEXEC); } LPSECURITY_ATTRIBUTES get_inheritance (bool all = 0) @@ -212,9 +216,9 @@ class fhandler_base } void set_check_win95_lseek_bug (int b = 1) { FHCONDSETF (b, W95LSBUG); } - int get_check_win95_lseek_bug () { return FHISSETF (W95LSBUG); } + bool get_check_win95_lseek_bug () { return FHISSETF (W95LSBUG); } - int get_need_fork_fixup () { return FHISSETF (FFIXUP); } + bool get_need_fork_fixup () { return FHISSETF (FFIXUP); } void set_need_fork_fixup () { FHSETF (FFIXUP); } virtual void set_close_on_exec (int val); @@ -223,31 +227,31 @@ class fhandler_base virtual void fixup_after_fork (HANDLE); virtual void fixup_after_exec (HANDLE) {} - int get_symlink_p () { return FHISSETF (SYMLINK); } + bool get_symlink_p () { return FHISSETF (SYMLINK); } void set_symlink_p (int val) { FHCONDSETF (val, SYMLINK); } void set_symlink_p () { FHSETF (SYMLINK); } - int get_socket_p () { return FHISSETF (LOCAL); } + bool get_socket_p () { return FHISSETF (LOCAL); } void set_socket_p (int val) { FHCONDSETF (val, LOCAL); } void set_socket_p () { FHSETF (LOCAL); } - int get_execable_p () { return FHISSETF (EXECABL); } + bool get_execable_p () { return FHISSETF (EXECABL); } void set_execable_p (executable_states val) { FHCONDSETF (val == is_executable, EXECABL); FHCONDSETF (val == dont_care_if_executable, DCEXEC); } void set_execable_p () { FHSETF (EXECABL); } - int dont_care_if_execable () { return FHISSETF (DCEXEC); } + bool dont_care_if_execable () { return FHISSETF (DCEXEC); } - int get_append_p () { return FHISSETF (APPEND); } + bool get_append_p () { return FHISSETF (APPEND); } void set_append_p (int val) { FHCONDSETF (val, APPEND); } void set_append_p () { FHSETF (APPEND); } - int get_query_open () { return FHISSETF (QUERYOPEN); } + bool get_query_open () { return FHISSETF (QUERYOPEN); } void set_query_open (int val) { FHCONDSETF (val, QUERYOPEN); } - int get_readahead_valid () { return raixget < ralen; } + bool get_readahead_valid () { return raixget < ralen; } int puts_readahead (const char *s, size_t len = (size_t) -1); int put_readahead (char value); @@ -260,10 +264,10 @@ class fhandler_base int get_readahead_into_buffer (char *buf, size_t buflen); - int has_acls () { return FHISSETF (HASACLS); } + bool has_acls () { return FHISSETF (HASACLS); } void set_has_acls (int val) { FHCONDSETF (val, HASACLS); } - int isremote () { return FHISSETF (ISREMOTE); } + bool isremote () { return FHISSETF (ISREMOTE); } void set_isremote (int val) { FHCONDSETF (val, ISREMOTE); } const char *get_name () { return unix_path_name; } @@ -405,7 +409,7 @@ class fhandler_pipe: public fhandler_base DWORD orig_pid; unsigned id; public: - fhandler_pipe (DWORD devtype = FH_PIPE); + fhandler_pipe (DWORD devtype); off_t lseek (off_t offset, int whence); select_record *select_read (select_record *s); select_record *select_write (select_record *s); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 0585555c4..7a596b88b 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -599,6 +599,7 @@ fhandler_disk_file::opendir (path_conv& real_name) dir->__d_dirent->d_version = __DIRENT_VERSION; cygheap_fdnew fd; fd = this; + fd->set_nohandle (true); dir->__d_dirent->d_fd = fd; dir->__d_u.__d_data.__fh = this; /* FindFirstFile doesn't seem to like duplicate /'s. */ diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 4d72339cb..6cc03a669 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -115,6 +115,15 @@ strcasestr (const char *searchee, const char *lookfor) return NULL; } +int __stdcall +check_null_str (const char *name) +{ + if (name && !IsBadStringPtr (name, MAX_PATH)) + return 0; + + return EFAULT; +} + int __stdcall check_null_empty_str (const char *name) { @@ -133,6 +142,15 @@ check_null_empty_str_errno (const char *name) return __err; } +int __stdcall +check_null_str_errno (const char *name) +{ + int __err; + if ((__err = check_null_str (name))) + set_errno (__err); + return __err; +} + int __stdcall __check_null_invalid_struct (const void *s, unsigned sz) { diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index c14a04c53..978872178 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -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); - - if (get_inet_addr (to, tolen, &sin, &tolen) == 0) - return -1; + fhandler_socket *h = get (fd); - if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ())) + if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len)) + || __check_null_invalid_struct_errno (to, tolen) + || !h) + res = -1; + else { - debug_printf ("Fallback to winsock 1 sendto call"); - if ((res = sendto (h->get_socket (), (const char *) buf, len, flags, - (sockaddr *) &sin, tolen)) == SOCKET_ERROR) + 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) + else { - set_winsock_errno (); - res = -1; + 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 ())) + 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 { - debug_printf ("Fallback to winsock 1 recvfrom call"); - if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen)) - == SOCKET_ERROR) + 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) + else { - set_winsock_errno (); - res = -1; + 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 ())) + if (__check_null_invalid_struct_errno (buf, len) || !h) + res = -1; + else { - debug_printf ("Fallback to winsock 1 recv call"); - if ((res = recv (h->get_socket (), (char *) buf, len, flags)) - == SOCKET_ERROR) + 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) + else { - set_winsock_errno (); - res = -1; + 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 ())) + if (__check_invalid_read_ptr_errno (buf, len) || !h) + res = -1; + else { - debug_printf ("Fallback to winsock 1 send call"); - if ((res = send (h->get_socket (), (const char *) buf, len, flags)) - == SOCKET_ERROR) + 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) + else { - set_winsock_errno (); - res = -1; + 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; diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index b74581de2..6efdf7d9e 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -857,8 +857,12 @@ get_devn (const char *name, int &unit) devn = FH_SERIAL; unit++; } - else if (deveq ("pipe") || deveq ("piper") || deveq ("pipew")) + else if (deveq ("pipe")) devn = FH_PIPE; + else if (deveq ("piper")) + devn = FH_PIPER; + else if (deveq ("pipew")) + devn = FH_PIPEW; else if (deveq ("tcp") || deveq ("udp") || deveq ("streamsocket") || deveq ("dgsocket")) devn = FH_SOCKET; diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index d3d64eda8..c54e72723 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -339,7 +339,7 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds, UNIX_FD_SET (me->fd, writefds); ready++; } - if (me->except_ready && me->except_ready) + if (me->except_selected && me->except_ready) { UNIX_FD_SET (me->fd, exceptfds); ready++; diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 7105fb7bc..68ed5d11a 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -190,6 +190,7 @@ void set_console_handler (); int __stdcall check_null_empty_str (const char *name) __attribute__ ((regparm(1))); int __stdcall check_null_empty_str_errno (const char *name) __attribute__ ((regparm(1))); +int __stdcall check_null_str_errno (const char *name) __attribute__ ((regparm(1))); int __stdcall __check_null_invalid_struct (const void *s, unsigned sz) __attribute__ ((regparm(2))); int __stdcall __check_null_invalid_struct_errno (const void *s, unsigned sz) __attribute__ ((regparm(2))); int __stdcall __check_invalid_read_ptr_errno (const void *s, unsigned sz) __attribute__ ((regparm(2))); -- cgit v1.2.3