https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=51af517cabcf2677f9ad1b8540dcd98f8e141928

commit 51af517cabcf2677f9ad1b8540dcd98f8e141928
Author: Corinna Vinschen <cori...@vinschen.de>
Date:   Wed Feb 7 15:37:48 2018 +0100

    Cygwin: setsockopt/getsockopt: Add missing optlen checks
    
    Signed-off-by: Corinna Vinschen <cori...@vinschen.de>

Diff:
---
 winsup/cygwin/net.cc | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 9ff64b8..6f96acb 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -842,6 +842,11 @@ cygwin_setsockopt (int fd, int level, int optname, const 
void *optval,
                 SO_REUSEADDR has been set but don't call setsockopt.
                 Instead fhandler_socket::bind sets SO_EXCLUSIVEADDRUSE if
                 the application did not set SO_REUSEADDR. */
+             if (optlen < (socklen_t) sizeof (int))
+               {
+                 set_errno (EINVAL);
+                 __leave;
+               }
              if (fh->get_socket_type () == SOCK_STREAM)
                ignore = true;
              break;
@@ -901,7 +906,7 @@ cygwin_setsockopt (int fd, int level, int optname, const 
void *optval,
            }
        }
 
-      if (optlen == sizeof (int))
+      if (optlen == (socklen_t) sizeof (int))
        debug_printf ("setsockopt optval=%x", *(int *) optval);
 
       /* Postprocessing setsockopt, setting fhandler_socket members, etc. */
@@ -966,7 +971,15 @@ cygwin_getsockopt (int fd, int level, int optname, void 
*optval,
            case SO_PEERCRED:
              {
                struct ucred *cred = (struct ucred *) optval;
+
+               if (*optlen < (socklen_t) sizeof *cred)
+                 {
+                   set_errno (EINVAL);
+                   __leave;
+                 }
                res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid);
+               if (!res)
+                 *optlen = (socklen_t) sizeof *cred;
                __leave;
              }
              break;
@@ -974,8 +987,14 @@ cygwin_getsockopt (int fd, int level, int optname, void 
*optval,
            case SO_REUSEADDR:
              {
                unsigned int *reuseaddr = (unsigned int *) optval;
+
+               if (*optlen < (socklen_t) sizeof *reuseaddr)
+                 {
+                   set_errno (EINVAL);
+                   __leave;
+                 }
                *reuseaddr = fh->saw_reuseaddr();
-               *optlen = sizeof *reuseaddr;
+               *optlen = (socklen_t) sizeof *reuseaddr;
                ignore = true;
              }
              break;

Reply via email to