[meta-oe,dunfell] libmicrohttpd: Add patch to fix CVE-2021-3466

Message ID 4880577cbd16ccf732daf804bb720373c3a4de05.camel@lists.verisure.com
State New
Headers show
Series [meta-oe,dunfell] libmicrohttpd: Add patch to fix CVE-2021-3466 | expand

Commit Message

Ernst Sjöstrand Dec. 21, 2021, 1:09 p.m. UTC
Extract patch from the 0.9.71 release commit.

Signed-off-by: Ernst Sjöstrand <ernst.sjostrand@verisure.com>
---
 .../libmicrohttpd/CVE-2021-3466.patch         | 152 ++++++++++++++++++
 .../libmicrohttpd/libmicrohttpd_0.9.70.bb     |   3 +-
 2 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-3466.patch

-- 
2.34.0

Comments

Ernst Sjöstrand Dec. 22, 2021, 9:44 a.m. UTC | #1
On Tue, 2021-12-21 at 14:29 -0800, akuster808 wrote:
> Ernst,
> 
> On 12/21/21 5:09 AM, Ernst Sjöstrand wrote:
> > Extract patch from the 0.9.71 release commit.
> Does this affect any other branch ? What version does it affect?

Only version 0.9.70 is vulnerable, and gatesgarth has 0.9.71.

> > Signed-off-by: Ernst Sjöstrand <ernst.sjostrand@verisure.com>
> > ---
> >  .../libmicrohttpd/CVE-2021-3466.patch         | 152 ++++++++++++++++++
> >  .../libmicrohttpd/libmicrohttpd_0.9.70.bb     |   3 +-
> >  2 files changed, 154 insertions(+), 1 deletion(-)
> >  create mode 100644 meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-
> > 2021-3466.patch
> > 
> > diff --git a/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-
> > 3466.patch b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-
> > 3466.patch
> > new file mode 100644
> > index 000000000..8c36c2263
> > --- /dev/null
> > +++ b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-
> > 3466.patch
> > @@ -0,0 +1,152 @@
> > +From 86d9a61be6395220714b1a50d5144e65668961f6 Mon Sep 17 00:00:00 2001
> > +From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= <ernst.sjostrand@verisure.com>
> > +Date: Tue, 21 Dec 2021 11:05:22 +0000
> > +Subject: [PATCH] Fix buffer overflow in url parser and add test
> > +
> > +Fixes CVE-2021-3466
> 
> Also the patch itself is missing;
> 
> Upstream-Status: (Backport ?)
> CVE: CVE-2021-3466
> Signed-off-by:  Ernst Sjöstrand <ernst.sjostrand@verisure.com>
> 

I'll send a v2.

> -armin
> > +---
> > + src/microhttpd/postprocessor.c      | 18 ++++++--
> > + src/microhttpd/test_postprocessor.c | 66 +++++++++++++++++++++++++++++
> > + 2 files changed, 80 insertions(+), 4 deletions(-)
> > +
> > +diff --git a/src/microhttpd/postprocessor.c
> > b/src/microhttpd/postprocessor.c
> > +index b7f6b10..ebd1686 100644
> > +--- a/src/microhttpd/postprocessor.c
> > ++++ b/src/microhttpd/postprocessor.c
> > +@@ -137,8 +137,7 @@ struct MHD_PostProcessor
> > +   void *cls;
> > + 
> > +   /**
> > +-   * Encoding as given by the headers of the
> > +-   * connection.
> > ++   * Encoding as given by the headers of the connection.
> > +    */
> > +   const char *encoding;
> > + 
> > +@@ -586,7 +585,7 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
> > +       pp->state = PP_Error;
> > +       break;
> > +     case PP_Callback:
> > +-      if ( (pp->buffer_pos + (end_key - start_key) >
> > ++      if ( (pp->buffer_pos + (end_key - start_key) >=
> > +             pp->buffer_size) ||
> > +            (pp->buffer_pos + (end_key - start_key) <
> > +             pp->buffer_pos) )
> > +@@ -636,6 +635,11 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
> > +   {
> > +     if (NULL == end_key) 
> > +       end_key = &post_data[poff];
> > ++    if (pp->buffer_pos + (end_key - start_key) >= pp->buffer_size)
> > ++    {
> > ++      pp->state = PP_Error;
> > ++      return MHD_NO;
> > ++    }
> > +     memcpy (&kbuf[pp->buffer_pos],
> > +             start_key,
> > +             end_key - start_key);
> > +@@ -663,6 +667,11 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
> > +                    last_escape);
> > +     pp->must_ikvi = false;
> > +   }
> > ++  if (PP_Error == pp->state)
> > ++  {
> > ++    /* State in error, returning failure */
> > ++    return MHD_NO;
> > ++  }
> > +   return MHD_YES;
> > + }
> > + 
> > +@@ -1424,7 +1433,8 @@ MHD_destroy_post_processor (struct MHD_PostProcessor
> > *pp)
> > +      the post-processing may have been interrupted
> > +      at any stage */
> > +   if ( (pp->xbuf_pos > 0) ||
> > +-       (pp->state != PP_Done) )
> > ++       ( (pp->state != PP_Done) &&
> > ++         (pp->state != PP_Init) ) )
> > +     ret = MHD_NO;
> > +   else
> > +     ret = MHD_YES;
> > +diff --git a/src/microhttpd/test_postprocessor.c
> > b/src/microhttpd/test_postprocessor.c
> > +index 2c37565..cba486d 100644
> > +--- a/src/microhttpd/test_postprocessor.c
> > ++++ b/src/microhttpd/test_postprocessor.c
> > +@@ -451,6 +451,71 @@ test_empty_value (void)
> > + }
> > + 
> > + 
> > ++static enum MHD_Result
> > ++value_checker2 (void *cls,
> > ++                enum MHD_ValueKind kind,
> > ++                const char *key,
> > ++                const char *filename,
> > ++                const char *content_type,
> > ++                const char *transfer_encoding,
> > ++                const char *data,
> > ++                uint64_t off,
> > ++                size_t size)
> > ++{
> > ++  return MHD_YES;
> > ++}
> > ++
> > ++
> > ++static int
> > ++test_overflow ()
> > ++{
> > ++  struct MHD_Connection connection;
> > ++  struct MHD_HTTP_Header header;
> > ++  struct MHD_PostProcessor *pp;
> > ++  size_t i;
> > ++  size_t j;
> > ++  size_t delta;
> > ++  char *buf;
> > ++
> > ++  memset (&connection, 0, sizeof (struct MHD_Connection));
> > ++  memset (&header, 0, sizeof (struct MHD_HTTP_Header));
> > ++  connection.headers_received = &header;
> > ++  header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
> > ++  header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
> > ++  header.header_size = strlen (header.header);
> > ++  header.value_size = strlen (header.value);
> > ++  header.kind = MHD_HEADER_KIND;
> > ++  for (i = 128; i < 1024 * 1024; i += 1024)
> > ++  {
> > ++    pp = MHD_create_post_processor (&connection,
> > ++                                    1024,
> > ++                                    &value_checker2,
> > ++                                    NULL);
> > ++    buf = malloc (i);
> > ++    if (NULL == buf)
> > ++      return 1;
> > ++    memset (buf, 'A', i);
> > ++    buf[i / 2] = '=';
> > ++    delta = 1 + (MHD_random_ () % (i - 1));
> > ++    j = 0;
> > ++    while (j < i)
> > ++    {
> > ++      if (j + delta > i)
> > ++        delta = i - j;
> > ++      if (MHD_NO ==
> > ++          MHD_post_process (pp,
> > ++                            &buf[j],
> > ++                            delta))
> > ++        break;
> > ++      j += delta;
> > ++    }
> > ++    free (buf);
> > ++    MHD_destroy_post_processor (pp);
> > ++  }
> > ++  return 0;
> > ++}
> > ++
> > ++
> > + int
> > + main (int argc, char *const *argv)
> > + {
> > +@@ -463,6 +528,7 @@ main (int argc, char *const *argv)
> > +   errorCount += test_multipart ();
> > +   errorCount += test_nested_multipart ();
> > +   errorCount += test_empty_value ();
> > ++  errorCount += test_overflow ();
> > +   if (errorCount != 0)
> > +     fprintf (stderr, "Error (code: %u)\n", errorCount);
> > +   return errorCount != 0;       /* 0 == pass */
> > diff --git a/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb
> > b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb
> > index 94976d2e9..9d5e85e1a 100644
> > --- a/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb
> > +++ b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb
> > @@ -7,7 +7,8 @@ SECTION = "net"
> >  DEPENDS = "file"
> >  
> >  SRC_URI = "${GNU_MIRROR}/libmicrohttpd/${BPN}-${PV}.tar.gz \
> > -"
> > +           file://CVE-2021-3466.patch \
> > +           "
> >  SRC_URI[md5sum] = "dcd6045ecb4ea18c120afedccbd1da74"
> >  SRC_URI[sha256sum] =
> > "90d0a3d396f96f9bc41eb0f7e8187796049285fabef82604acd4879590977307"
> >  
> > 
> > -=-=-=-=-=-=-=-=-=-=-=-
> > Links: You receive all messages sent to this group.
> > View/Reply Online (#94466): 
> > https://urldefense.com/v3/__https://lists.openembedded.org/g/openembedded-devel/message/94466__;!!BFCLnRDDbM3FOmw!rOMP9VaDgUq33ddlZfmPANWR6K7C2lZdTg7hc4xqWfCLsvTaIpRAjppEA_rq2QLyX_a0uHGg1A$
> >  
> > Mute This Topic: 
> > https://urldefense.com/v3/__https://lists.openembedded.org/mt/87876647/3616698__;!!BFCLnRDDbM3FOmw!rOMP9VaDgUq33ddlZfmPANWR6K7C2lZdTg7hc4xqWfCLsvTaIpRAjppEA_rq2QLyX_a-1ysYQA$
> >  
> > Group Owner: openembedded-devel+owner@lists.openembedded.org
> > Unsubscribe: 
> > https://urldefense.com/v3/__https://lists.openembedded.org/g/openembedded-devel/unsub__;!!BFCLnRDDbM3FOmw!rOMP9VaDgUq33ddlZfmPANWR6K7C2lZdTg7hc4xqWfCLsvTaIpRAjppEA_rq2QLyX_ZrBVyiTg$
> >   [akuster808@gmail.com]
> > -=-=-=-=-=-=-=-=-=-=-=-
> >

Patch

diff --git a/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-3466.patch b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-3466.patch
new file mode 100644
index 000000000..8c36c2263
--- /dev/null
+++ b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-3466.patch
@@ -0,0 +1,152 @@ 
+From 86d9a61be6395220714b1a50d5144e65668961f6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= <ernst.sjostrand@verisure.com>
+Date: Tue, 21 Dec 2021 11:05:22 +0000
+Subject: [PATCH] Fix buffer overflow in url parser and add test
+
+Fixes CVE-2021-3466
+---
+ src/microhttpd/postprocessor.c      | 18 ++++++--
+ src/microhttpd/test_postprocessor.c | 66 +++++++++++++++++++++++++++++
+ 2 files changed, 80 insertions(+), 4 deletions(-)
+
+diff --git a/src/microhttpd/postprocessor.c b/src/microhttpd/postprocessor.c
+index b7f6b10..ebd1686 100644
+--- a/src/microhttpd/postprocessor.c
++++ b/src/microhttpd/postprocessor.c
+@@ -137,8 +137,7 @@ struct MHD_PostProcessor
+   void *cls;
+ 
+   /**
+-   * Encoding as given by the headers of the
+-   * connection.
++   * Encoding as given by the headers of the connection.
+    */
+   const char *encoding;
+ 
+@@ -586,7 +585,7 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
+       pp->state = PP_Error;
+       break;
+     case PP_Callback:
+-      if ( (pp->buffer_pos + (end_key - start_key) >
++      if ( (pp->buffer_pos + (end_key - start_key) >=
+             pp->buffer_size) ||
+            (pp->buffer_pos + (end_key - start_key) <
+             pp->buffer_pos) )
+@@ -636,6 +635,11 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
+   {
+     if (NULL == end_key) 
+       end_key = &post_data[poff];
++    if (pp->buffer_pos + (end_key - start_key) >= pp->buffer_size)
++    {
++      pp->state = PP_Error;
++      return MHD_NO;
++    }
+     memcpy (&kbuf[pp->buffer_pos],
+             start_key,
+             end_key - start_key);
+@@ -663,6 +667,11 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
+                    last_escape);
+     pp->must_ikvi = false;
+   }
++  if (PP_Error == pp->state)
++  {
++    /* State in error, returning failure */
++    return MHD_NO;
++  }
+   return MHD_YES;
+ }
+ 
+@@ -1424,7 +1433,8 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
+      the post-processing may have been interrupted
+      at any stage */
+   if ( (pp->xbuf_pos > 0) ||
+-       (pp->state != PP_Done) )
++       ( (pp->state != PP_Done) &&
++         (pp->state != PP_Init) ) )
+     ret = MHD_NO;
+   else
+     ret = MHD_YES;
+diff --git a/src/microhttpd/test_postprocessor.c b/src/microhttpd/test_postprocessor.c
+index 2c37565..cba486d 100644
+--- a/src/microhttpd/test_postprocessor.c
++++ b/src/microhttpd/test_postprocessor.c
+@@ -451,6 +451,71 @@ test_empty_value (void)
+ }
+ 
+ 
++static enum MHD_Result
++value_checker2 (void *cls,
++                enum MHD_ValueKind kind,
++                const char *key,
++                const char *filename,
++                const char *content_type,
++                const char *transfer_encoding,
++                const char *data,
++                uint64_t off,
++                size_t size)
++{
++  return MHD_YES;
++}
++
++
++static int
++test_overflow ()
++{
++  struct MHD_Connection connection;
++  struct MHD_HTTP_Header header;
++  struct MHD_PostProcessor *pp;
++  size_t i;
++  size_t j;
++  size_t delta;
++  char *buf;
++
++  memset (&connection, 0, sizeof (struct MHD_Connection));
++  memset (&header, 0, sizeof (struct MHD_HTTP_Header));
++  connection.headers_received = &header;
++  header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
++  header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
++  header.header_size = strlen (header.header);
++  header.value_size = strlen (header.value);
++  header.kind = MHD_HEADER_KIND;
++  for (i = 128; i < 1024 * 1024; i += 1024)
++  {
++    pp = MHD_create_post_processor (&connection,
++                                    1024,
++                                    &value_checker2,
++                                    NULL);
++    buf = malloc (i);
++    if (NULL == buf)
++      return 1;
++    memset (buf, 'A', i);
++    buf[i / 2] = '=';
++    delta = 1 + (MHD_random_ () % (i - 1));
++    j = 0;
++    while (j < i)
++    {
++      if (j + delta > i)
++        delta = i - j;
++      if (MHD_NO ==
++          MHD_post_process (pp,
++                            &buf[j],
++                            delta))
++        break;
++      j += delta;
++    }
++    free (buf);
++    MHD_destroy_post_processor (pp);
++  }
++  return 0;
++}
++
++
+ int
+ main (int argc, char *const *argv)
+ {
+@@ -463,6 +528,7 @@ main (int argc, char *const *argv)
+   errorCount += test_multipart ();
+   errorCount += test_nested_multipart ();
+   errorCount += test_empty_value ();
++  errorCount += test_overflow ();
+   if (errorCount != 0)
+     fprintf (stderr, "Error (code: %u)\n", errorCount);
+   return errorCount != 0;       /* 0 == pass */
diff --git a/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb
index 94976d2e9..9d5e85e1a 100644
--- a/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb
+++ b/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd_0.9.70.bb
@@ -7,7 +7,8 @@  SECTION = "net"
 DEPENDS = "file"
 
 SRC_URI = "${GNU_MIRROR}/libmicrohttpd/${BPN}-${PV}.tar.gz \
-"
+           file://CVE-2021-3466.patch \
+           "
 SRC_URI[md5sum] = "dcd6045ecb4ea18c120afedccbd1da74"
 SRC_URI[sha256sum] = "90d0a3d396f96f9bc41eb0f7e8187796049285fabef82604acd4879590977307"