guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

02/03: gnu: address@hidden: Fix CVE-2015-5180, CVE-2016-{3075, 3706, 442


From: Efraim Flashner
Subject: 02/03: gnu: address@hidden: Fix CVE-2015-5180, CVE-2016-{3075, 3706, 4429}.
Date: Wed, 2 Aug 2017 14:56:47 -0400 (EDT)

efraim pushed a commit to branch master
in repository guix.

commit a0ae64a334ce4dda269828bbb3c9182842e5cd50
Author: Efraim Flashner <address@hidden>
Date:   Wed Aug 2 21:11:57 2017 +0300

    gnu: address@hidden: Fix CVE-2015-5180, CVE-2016-{3075,3706,4429}.
    
    * gnu/packages/base.scm (address@hidden)[source]: Add patches.
    * gnu/packages/patches/glibc-CVE-2016-3075.patch,
    gnu/packages/patches/glibc-CVE-2016-3706.patch,
    gnu/packages/patches/glibc-CVE-2016-4429.patch: New files.
    * gnu/local.mk (dist_patch_DATA): Register them.
---
 gnu/local.mk                                   |   3 +
 gnu/packages/base.scm                          |   4 +
 gnu/packages/patches/glibc-CVE-2016-3075.patch |  43 ++++++
 gnu/packages/patches/glibc-CVE-2016-3706.patch | 188 +++++++++++++++++++++++++
 gnu/packages/patches/glibc-CVE-2016-4429.patch |  58 ++++++++
 5 files changed, 296 insertions(+)

diff --git a/gnu/local.mk b/gnu/local.mk
index 5cc8b64..67150ae 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -645,6 +645,9 @@ dist_patch_DATA =                                           
\
   %D%/packages/patches/glib-networking-ssl-cert-file.patch     \
   %D%/packages/patches/glib-tests-timer.patch                  \
   %D%/packages/patches/glibc-CVE-2015-5180.patch               \
+  %D%/packages/patches/glibc-CVE-2016-3075.patch               \
+  %D%/packages/patches/glibc-CVE-2016-3706.patch               \
+  %D%/packages/patches/glibc-CVE-2016-4429.patch               \
   %D%/packages/patches/glibc-CVE-2017-1000366-pt1.patch                \
   %D%/packages/patches/glibc-CVE-2017-1000366-pt2.patch                \
   %D%/packages/patches/glibc-CVE-2017-1000366-pt3.patch                \
diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm
index f23db9a..37e09eb 100644
--- a/gnu/packages/base.scm
+++ b/gnu/packages/base.scm
@@ -953,6 +953,10 @@ GLIBC/HURD for a Hurd host"
                                        "glibc-versioned-locpath.patch"
                                        "glibc-o-largefile.patch"
                                        "glibc-vectorized-strcspn-guards.patch"
+                                       "glibc-CVE-2015-5180.patch"
+                                       "glibc-CVE-2016-3075.patch"
+                                       "glibc-CVE-2016-3706.patch"
+                                       "glibc-CVE-2016-4429.patch"
                                        "glibc-CVE-2017-1000366-pt1.patch"
                                        "glibc-CVE-2017-1000366-pt2.patch"
                                        "glibc-CVE-2017-1000366-pt3.patch"))))))
diff --git a/gnu/packages/patches/glibc-CVE-2016-3075.patch 
b/gnu/packages/patches/glibc-CVE-2016-3075.patch
new file mode 100644
index 0000000..d167228
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2016-3075.patch
@@ -0,0 +1,43 @@
+From 146b58d11fddbef15b888906e3be4f33900c416f Mon Sep 17 00:00:00 2001
+From: Florian Weimer <address@hidden>
+Date: Tue, 29 Mar 2016 12:57:56 +0200
+Subject: [PATCH] CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r [BZ
+ #19879]
+
+The defensive copy is not needed because the name may not alias the
+output buffer.
+
+(cherry picked from commit 317b199b4aff8cfa27f2302ab404d2bb5032b9a4)
+(cherry picked from commit 883dceebc8f11921a9890211a4e202e5be17562f)
+---
+ ChangeLog                    |  7 +++++++
+ NEWS                         | 10 ++++++++--
+ resolv/nss_dns/dns-network.c |  5 +----
+ 3 files changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
+index 2eb2f67..8f301a7 100644
+--- a/resolv/nss_dns/dns-network.c
++++ b/resolv/nss_dns/dns-network.c
+@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent 
*result,
+   } net_buffer;
+   querybuf *orig_net_buffer;
+   int anslen;
+-  char *qbuf;
+   enum nss_status status;
+ 
+   if (__res_maybe_init (&_res, 0) == -1)
+     return NSS_STATUS_UNAVAIL;
+ 
+-  qbuf = strdupa (name);
+-
+   net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
+ 
+-  anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
++  anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
+                              1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
+   if (anslen < 0)
+     {
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2016-3706.patch 
b/gnu/packages/patches/glibc-CVE-2016-3706.patch
new file mode 100644
index 0000000..617242d
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2016-3706.patch
@@ -0,0 +1,188 @@
+From 1a8a7c12950a0026a3c406a7cb1608f96aa1460e Mon Sep 17 00:00:00 2001
+From: Florian Weimer <address@hidden>
+Date: Fri, 29 Apr 2016 10:35:34 +0200
+Subject: [PATCH] CVE-2016-3706: getaddrinfo: stack overflow in hostent
+ conversion [BZ #20010]
+
+When converting a struct hostent response to struct gaih_addrtuple, the
+gethosts macro (which is called from gaih_inet) used alloca, without
+malloc fallback for large responses.  This commit changes this code to
+use calloc unconditionally.
+
+This commit also consolidated a second hostent-to-gaih_addrtuple
+conversion loop (in gaih_inet) to use the new conversion function.
+
+(cherry picked from commit 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9)
+---
+ ChangeLog                   |  10 ++++
+ sysdeps/posix/getaddrinfo.c | 130 +++++++++++++++++++++++---------------------
+ 2 files changed, 79 insertions(+), 61 deletions(-)
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index 1ef3f20..fed2d3b 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct 
gaih_typeproto *tp,
+   return 0;
+ }
+ 
++/* Convert struct hostent to a list of struct gaih_addrtuple objects.
++   h_name is not copied, and the struct hostent object must not be
++   deallocated prematurely.  *RESULT must be NULL or a pointer to an
++   object allocated using malloc, which is freed.  */
++static bool
++convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
++                                 int family,
++                                 struct hostent *h,
++                                 struct gaih_addrtuple **result)
++{
++  free (*result);
++  *result = NULL;
++
++  /* Count the number of addresses in h->h_addr_list.  */
++  size_t count = 0;
++  for (char **p = h->h_addr_list; *p != NULL; ++p)
++    ++count;
++
++  /* Report no data if no addresses are available, or if the incoming
++     address size is larger than what we can store.  */
++  if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
++    return true;
++
++  struct gaih_addrtuple *array = calloc (count, sizeof (*array));
++  if (array == NULL)
++    return false;
++
++  for (size_t i = 0; i < count; ++i)
++    {
++      if (family == AF_INET && req->ai_family == AF_INET6)
++      {
++        /* Perform address mapping. */
++        array[i].family = AF_INET6;
++        memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
++        array[i].addr[2] = htonl (0xffff);
++      }
++      else
++      {
++        array[i].family = family;
++        memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
++      }
++      array[i].next = array + i + 1;
++    }
++  array[0].name = h->h_name;
++  array[count - 1].next = NULL;
++
++  *result = array;
++  return true;
++}
++
+ #define gethosts(_family, _type) \
+  {                                                                          \
+-  int i;                                                                    \
+   int herrno;                                                               \
+   struct hostent th;                                                        \
+   struct hostent *h;                                                        \
+@@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct 
gaih_typeproto *tp,
+     }                                                                       \
+   else if (h != NULL)                                                       \
+     {                                                                       \
+-      for (i = 0; h->h_addr_list[i]; i++)                                   \
++      /* Make sure that addrmem can be freed.  */                           \
++      if (!malloc_addrmem)                                                  \
++      addrmem = NULL;                                                       \
++      if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem))      
\
+       {                                                                     \
+-        if (*pat == NULL)                                                   \
+-          {                                                                 \
+-            *pat = __alloca (sizeof (struct gaih_addrtuple));               \
+-            (*pat)->scopeid = 0;                                            \
+-          }                                                                 \
+-        uint32_t *addr = (*pat)->addr;                                      \
+-        (*pat)->next = NULL;                                                \
+-        (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL;                 \
+-        if (_family == AF_INET && req->ai_family == AF_INET6)               \
+-          {                                                                 \
+-            (*pat)->family = AF_INET6;                                      \
+-            addr[3] = *(uint32_t *) h->h_addr_list[i];                      \
+-            addr[2] = htonl (0xffff);                                       \
+-            addr[1] = 0;                                                    \
+-            addr[0] = 0;                                                    \
+-          }                                                                 \
+-        else                                                                \
+-          {                                                                 \
+-            (*pat)->family = _family;                                       \
+-            memcpy (addr, h->h_addr_list[i], sizeof(_type));                \
+-          }                                                                 \
+-        pat = &((*pat)->next);                                              \
++        _res.options |= old_res_options & RES_USE_INET6;                    \
++        result = -EAI_SYSTEM;                                               \
++        goto free_and_return;                                               \
+       }                                                                     \
++      *pat = addrmem;                                                       \
++      /* The conversion uses malloc unconditionally.  */                    \
++      malloc_addrmem = true;                                                \
+                                                                             \
+       if (localcanon !=       NULL && canon == NULL)                          
      \
+       canon = strdupa (localcanon);                                         \
+                                                                             \
+-      if (_family == AF_INET6 && i > 0)                                       
      \
++      if (_family == AF_INET6 && *pat != NULL)                                
      \
+       got_ipv6 = true;                                                      \
+     }                                                                       \
+  }
+@@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service 
*service,
+               {
+                 if (h != NULL)
+                   {
+-                    int i;
+-                    /* We found data, count the number of addresses.  */
+-                    for (i = 0; h->h_addr_list[i]; ++i)
+-                      ;
+-                    if (i > 0 && *pat != NULL)
+-                      --i;
+-
+-                    if (__libc_use_alloca (alloca_used
+-                                           + i * sizeof (struct 
gaih_addrtuple)))
+-                      addrmem = alloca_account (i * sizeof (struct 
gaih_addrtuple),
+-                                                alloca_used);
+-                    else
+-                      {
+-                        addrmem = malloc (i
+-                                          * sizeof (struct gaih_addrtuple));
+-                        if (addrmem == NULL)
+-                          {
+-                            result = -EAI_MEMORY;
+-                            goto free_and_return;
+-                          }
+-                        malloc_addrmem = true;
+-                      }
+-
+-                    /* Now convert it into the list.  */
+-                    struct gaih_addrtuple *addrfree = addrmem;
+-                    for (i = 0; h->h_addr_list[i]; ++i)
++                    /* We found data, convert it.  */
++                    if (!convert_hostent_to_gaih_addrtuple
++                        (req, AF_INET, h, &addrmem))
+                       {
+-                        if (*pat == NULL)
+-                          {
+-                            *pat = addrfree++;
+-                            (*pat)->scopeid = 0;
+-                          }
+-                        (*pat)->next = NULL;
+-                        (*pat)->family = AF_INET;
+-                        memcpy ((*pat)->addr, h->h_addr_list[i],
+-                                h->h_length);
+-                        pat = &((*pat)->next);
++                        result = -EAI_MEMORY;
++                        goto free_and_return;
+                       }
++                    *pat = addrmem;
++                    /* The conversion uses malloc unconditionally.  */
++                    malloc_addrmem = true;
+                   }
+               }
+             else
+-- 
+2.9.3
+
diff --git a/gnu/packages/patches/glibc-CVE-2016-4429.patch 
b/gnu/packages/patches/glibc-CVE-2016-4429.patch
new file mode 100644
index 0000000..5eebd10
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2016-4429.patch
@@ -0,0 +1,58 @@
+From bdce95930e1d9a7d013d1ba78740243491262879 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <address@hidden>
+Date: Mon, 23 May 2016 20:18:34 +0200
+Subject: [PATCH] CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call [BZ
+ #20112]
+
+The call is technically in a loop, and under certain circumstances
+(which are quite difficult to reproduce in a test case), alloca
+can be invoked repeatedly during a single call to clntudp_call.
+As a result, the available stack space can be exhausted (even
+though individual alloca sizes are bounded implicitly by what
+can fit into a UDP packet, as a side effect of the earlier
+successful send operation).
+
+(cherry picked from commit bc779a1a5b3035133024b21e2f339fe4219fb11c)
+---
+ ChangeLog         |  7 +++++++
+ NEWS              |  4 ++++
+ sunrpc/clnt_udp.c | 10 +++++++++-
+ 3 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
+index a6cf5f1..4d9acb1 100644
+--- a/sunrpc/clnt_udp.c
++++ b/sunrpc/clnt_udp.c
+@@ -388,9 +388,15 @@ send_again:
+         struct sock_extended_err *e;
+         struct sockaddr_in err_addr;
+         struct iovec iov;
+-        char *cbuf = (char *) alloca (outlen + 256);
++        char *cbuf = malloc (outlen + 256);
+         int ret;
+ 
++        if (cbuf == NULL)
++          {
++            cu->cu_error.re_errno = errno;
++            return (cu->cu_error.re_status = RPC_CANTRECV);
++          }
++
+         iov.iov_base = cbuf + 256;
+         iov.iov_len = outlen;
+         msg.msg_name = (void *) &err_addr;
+@@ -415,10 +421,12 @@ send_again:
+                cmsg = CMSG_NXTHDR (&msg, cmsg))
+             if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
+               {
++                free (cbuf);
+                 e = (struct sock_extended_err *) CMSG_DATA(cmsg);
+                 cu->cu_error.re_errno = e->ee_errno;
+                 return (cu->cu_error.re_status = RPC_CANTRECV);
+               }
++        free (cbuf);
+       }
+ #endif
+       do
+-- 
+2.9.3
+



reply via email to

[Prev in Thread] Current Thread [Next in Thread]