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

Bug#1014447: bullseye-pu: package lwip/2.1.2+dfsg1-8



Package: release.debian.org
Severity: important
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu

Hi,

This patch fixes  CVE-2020-22283 and  CVE-2020-22284 in bullseye.

Attached is the debdiff.

[1] https://security-tracker.debian.org/tracker/CVE-2020-22283
[2] https://security-tracker.debian.org/tracker/CVE-2020-22284



*** /home/jlledom/CVEsdebdiff.diff
diff -Nru lwip-2.1.2+dfsg1/debian/changelog lwip-2.1.2+dfsg1/debian/changelog
--- lwip-2.1.2+dfsg1/debian/changelog   2020-08-09 09:55:09.000000000 +0200
+++ lwip-2.1.2+dfsg1/debian/changelog   2022-07-06 10:55:52.000000000 +0200
@@ -1,3 +1,10 @@
+lwip (2.1.2+dfsg1-8+deb11u1) bullseye; urgency=high
+
+  * Fix CVE-2020-22283
+  * Fix CVE-2020-22284
+
+ -- Joan Lledó <jlledom@member.fsf.org>  Wed, 06 Jul 2022 10:55:52 +0200
+
 lwip (2.1.2+dfsg1-8) unstable; urgency=medium

   * No-change source-only upload to allow testing migration.
diff -Nru lwip-2.1.2+dfsg1/debian/patches/CVE-2020-22283_22284
lwip-2.1.2+dfsg1/debian/patches/CVE-2020-22283_22284
--- lwip-2.1.2+dfsg1/debian/patches/CVE-2020-22283_22284        1970-01-01
01:00:00.000000000 +0100
+++ lwip-2.1.2+dfsg1/debian/patches/CVE-2020-22283_22284        2022-07-06
10:48:50.000000000 +0200
@@ -0,0 +1,261 @@
+--- a/src/core/ipv6/icmp6.c
++++ b/src/core/ipv6/icmp6.c
+@@ -57,9 +57,9 @@
+
+ #include <string.h>
+
+-#if LWIP_ICMP6_DATASIZE == 0
++#if !LWIP_ICMP6_DATASIZE || (LWIP_ICMP6_DATASIZE > (IP6_MIN_MTU_LENGTH -
IP6_HLEN - ICMP6_HLEN))
+ #undef LWIP_ICMP6_DATASIZE
+-#define LWIP_ICMP6_DATASIZE   8
++#define LWIP_ICMP6_DATASIZE   (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN)
+ #endif
+
+ /* Forward declarations */
+@@ -387,26 +387,35 @@
+ {
+   struct pbuf *q;
+   struct icmp6_hdr *icmp6hdr;
++  u16_t datalen = LWIP_MIN(p->tot_len, LWIP_ICMP6_DATASIZE);
++  u16_t offset;
+
+-  /* ICMPv6 header + IPv6 header + data */
+-  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN +
LWIP_ICMP6_DATASIZE,
++ /* ICMPv6 header + datalen (as much of the offending packet as possible) */
++  q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + datalen,
+                  PBUF_RAM);
+   if (q == NULL) {
+ LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for
ICMPv6 packet.\n"));
+     ICMP6_STATS_INC(icmp6.memerr);
+     return;
+   }
+-  LWIP_ASSERT("check that first pbuf can hold icmp 6message",
+-             (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN +
LWIP_ICMP6_DATASIZE)));
++  LWIP_ASSERT("check that first pbuf can hold icmp6 header",
++             (q->len >= (sizeof(struct icmp6_hdr))));
+
+   icmp6hdr = (struct icmp6_hdr *)q->payload;
+   icmp6hdr->type = type;
+   icmp6hdr->code = code;
+   icmp6hdr->data = lwip_htonl(data);
+
+-  /* copy fields from original packet */
+- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
+-          IP6_HLEN + LWIP_ICMP6_DATASIZE);
++  /* copy fields from original packet (which may be a chain of pbufs) */
++  offset = sizeof(struct icmp6_hdr);
++  while (p && datalen) {
++    u16_t len = LWIP_MIN(datalen, p->len);
++    err_t res = pbuf_take_at(q, p->payload, len, offset);
++    if (res != ERR_OK) break;
++    datalen -= len;
++    offset += len;
++    p = p->next;
++  }
+
+   /* calculate checksum */
+   icmp6hdr->chksum = 0;
+--- a/src/core/ipv6/nd6.c
++++ b/src/core/ipv6/nd6.c
+@@ -693,7 +693,7 @@
+         }
+         mtu_opt = (struct mtu_option *)buffer;
+         mtu32 = lwip_htonl(mtu_opt->mtu);
+-        if ((mtu32 >= 1280) && (mtu32 <= 0xffff)) {
++        if ((mtu32 >= IP6_MIN_MTU_LENGTH) && (mtu32 <= 0xffff)) {
+ #if LWIP_ND6_ALLOW_RA_UPDATES
+           if (inp->mtu) {
+             /* don't set the mtu for IPv6 higher than the netif driver
supports */
+@@ -2300,7 +2300,7 @@
+     return netif_mtu6(netif);
+   }
+
+-  return 1280; /* Minimum MTU */
++  return IP6_MIN_MTU_LENGTH; /* Minimum MTU */
+ }
+
+
+--- a/src/core/pbuf.c
++++ b/src/core/pbuf.c
+@@ -960,54 +960,88 @@
+ err_t
+ pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
+ {
+-  size_t offset_to = 0, offset_from = 0, len;
+-
+   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
+               (const void *)p_to, (const void *)p_from));
+
++ LWIP_ERROR("pbuf_copy: invalid source", p_from != NULL, return ERR_ARG;);
++  return pbuf_copy_partial_pbuf(p_to, p_from, p_from->tot_len, 0);
++}
++
++/**
++ * @ingroup pbuf
++ * Copy part or all of one packet buffer into another, to a specified offset.
++ *
++ * @note Only data in one packet is copied, no packet queue!
++ * @note Argument order is shared with pbuf_copy, but different than
pbuf_copy_partial.
++ *
++ * @param p_to pbuf destination of the copy
++ * @param p_from pbuf source of the copy
++ * @param copy_len number of bytes to copy
++ * @param offset offset in destination pbuf where to copy to
++ *
++ * @return ERR_OK if copy_len bytes were copied
++ *         ERR_ARG if one of the pbufs is NULL or p_from is shorter than
copy_len
++ *                 or p_to is not big enough to hold copy_len at offset
++ *         ERR_VAL if any of the pbufs are part of a queue
++ */
++err_t
++pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t
copy_len, u16_t offset)
++{
++  size_t offset_to = offset, offset_from = 0, len_calc;
++  u16_t len;
++
++ LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf(%p, %p,
%"U16_F", %"U16_F")\n",
++ (const void *)p_to, (const void *)p_from, copy_len, offset));
++
++  /* is the copy_len in range? */
++ LWIP_ERROR("pbuf_copy_partial_pbuf: copy_len bigger than source", ((p_from
!= NULL) &&
++             (p_from->tot_len >= copy_len)), return ERR_ARG;);
+   /* is the target big enough to hold the source? */
+-  LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to !=
NULL) &&
+- (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return
ERR_ARG;);
++ LWIP_ERROR("pbuf_copy_partial_pbuf: target not big enough", ((p_to != NULL)
&&
++             (p_to->tot_len >= (offset + copy_len))), return ERR_ARG;);
+
+   /* iterate through pbuf chain */
+   do {
+     /* copy one part of the original chain */
+     if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
+       /* complete current p_from fits into current p_to */
+-      len = p_from->len - offset_from;
++      len_calc = p_from->len - offset_from;
+     } else {
+       /* current p_from does not fit into current p_to */
+-      len = p_to->len - offset_to;
++      len_calc = p_to->len - offset_to;
+     }
++    len = (u16_t)LWIP_MIN(copy_len, len_calc);
+     MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload +
offset_from, len);
+     offset_to += len;
+     offset_from += len;
++    copy_len -= len;
+     LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
+     LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
+     if (offset_from >= p_from->len) {
+       /* on to next p_from (if any) */
+       offset_from = 0;
+       p_from = p_from->next;
++      LWIP_ERROR("p_from != NULL", (p_from != NULL) || (copy_len == 0),
return ERR_ARG;);
+     }
+     if (offset_to == p_to->len) {
+       /* on to next p_to (if any) */
+       offset_to = 0;
+       p_to = p_to->next;
+- LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL), return
ERR_ARG;);
++      LWIP_ERROR("p_to != NULL", (p_to != NULL) || (copy_len == 0), return
ERR_ARG;);
+     }
+
+     if ((p_from != NULL) && (p_from->len == p_from->tot_len)) {
+       /* don't copy more than one packet! */
+-      LWIP_ERROR("pbuf_copy() does not allow packet queues!",
++      LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
+                  (p_from->next == NULL), return ERR_VAL;);
+     }
+     if ((p_to != NULL) && (p_to->len == p_to->tot_len)) {
+       /* don't copy more than one packet! */
+-      LWIP_ERROR("pbuf_copy() does not allow packet queues!",
++      LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
+                  (p_to->next == NULL), return ERR_VAL;);
+     }
+-  } while (p_from);
+-  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain
reached.\n"));
++  } while (copy_len);
++  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf: copy
complete.\n"));
+   return ERR_OK;
+ }
+
+--- a/src/include/lwip/opt.h
++++ b/src/include/lwip/opt.h
+@@ -2502,10 +2502,12 @@
+
+ /**
+  * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in
+- * ICMPv6 error messages.
++ * ICMPv6 error messages (0 = default of IP6_MIN_MTU_LENGTH)
++ * ATTENTION: RFC4443 section 2.4 says IP6_MIN_MTU_LENGTH is a MUST,
++ * so override this only if you absolutely have to!
+  */
+ #if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__
+-#define LWIP_ICMP6_DATASIZE             8
++#define LWIP_ICMP6_DATASIZE             0
+ #endif
+
+ /**
+--- a/src/include/lwip/pbuf.h
++++ b/src/include/lwip/pbuf.h
+@@ -293,6 +293,7 @@
+ void pbuf_chain(struct pbuf *head, struct pbuf *tail);
+ struct pbuf *pbuf_dechain(struct pbuf *p);
+ err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from);
++err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from,
u16_t copy_len, u16_t offset);
+ u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t
offset);
+ void *pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize,
u16_t len, u16_t offset);
+ err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
+--- a/src/include/lwip/prot/icmp6.h
++++ b/src/include/lwip/prot/icmp6.h
+@@ -146,6 +146,8 @@
+ #  include "arch/epstruct.h"
+ #endif
+
++#define ICMP6_HLEN 8
++
+ /** This is the ICMP6 header adapted for echo req/resp. */
+ #ifdef PACK_STRUCT_USE_INCLUDES
+ #  include "arch/bpstruct.h"
+--- a/src/include/lwip/prot/ip6.h
++++ b/src/include/lwip/prot/ip6.h
+@@ -44,6 +44,8 @@
+ extern "C" {
+ #endif
+
++#define IP6_MIN_MTU_LENGTH 1280
++
+ /** This is the packed version of ip6_addr_t,
+     used in network headers that are itself packed */
+ #ifdef PACK_STRUCT_USE_INCLUDES
+--- a/src/netif/lowpan6.c
++++ b/src/netif/lowpan6.c
+@@ -881,7 +881,7 @@
+   MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
+
+   /* maximum transfer unit */
+-  netif->mtu = 1280;
++  netif->mtu = IP6_MIN_MTU_LENGTH;
+
+   /* broadcast capability */
+   netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */;
+--- a/src/netif/lowpan6_ble.c
++++ b/src/netif/lowpan6_ble.c
+@@ -417,7 +417,7 @@
+   MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
+
+   /* maximum transfer unit, set according to RFC7668 ch2.4 */
+-  netif->mtu = 1280;
++  netif->mtu = IP6_MIN_MTU_LENGTH;
+
+   /* no flags set (no broadcast, ethernet,...)*/
+   netif->flags = 0;
+--- a/src/netif/zepif.c
++++ b/src/netif/zepif.c
+@@ -201,7 +201,7 @@
+   state->seqno++;
+   zep->len = (u8_t)p->tot_len;
+
+-  err = pbuf_take_at(q, p->payload, p->tot_len, sizeof(struct zep_hdr));
++  err = pbuf_copy_partial_pbuf(q, p, p->tot_len, sizeof(struct zep_hdr));
+   if (err == ERR_OK) {
+ #if ZEPIF_LOOPBACK
+     zepif_udp_recv(netif, state->pcb, pbuf_clone(PBUF_RAW, PBUF_RAM, q),
NULL, 0);
diff -Nru lwip-2.1.2+dfsg1/debian/patches/series
lwip-2.1.2+dfsg1/debian/patches/series
--- lwip-2.1.2+dfsg1/debian/patches/series 2020-08-09 09:55:09.000000000
+0200
+++ lwip-2.1.2+dfsg1/debian/patches/series 2022-07-06 10:48:50.000000000
+0200
@@ -1,6 +1,7 @@
 patch9350
 patch9807
 CVE-2020-8597
+CVE-2020-22283_22284
 port


Reply to: