diff mbox series

[meta-oe,wrynose,2/4] thrift: fix CVE-2026-58023

Message ID 20260803125927.831690-3-adarsh.jagadish.kamini@est.tech
State New
Headers show
Series thrift: multiple CVE fixes | expand

Commit Message

Adarsh Jagadish Kamini Aug. 3, 2026, 12:59 p.m. UTC
From: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>

Backport patch to fix CVE-2026-58023.

References:
  https://nvd.nist.gov/vuln/detail/CVE-2026-58023

Upstream fix:
  https://github.com/apache/thrift/commit/d68305a7308a11df2c1daef16f55dbc19dfa6ff0

Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
---
 .../thrift/thrift/CVE-2026-58023.patch        | 231 ++++++++++++++++++
 .../thrift/thrift_0.22.0.bb                   |   1 +
 2 files changed, 232 insertions(+)
 create mode 100644 meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-58023.patch
diff mbox series

Patch

diff --git a/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-58023.patch b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-58023.patch
new file mode 100644
index 0000000000..e3535fb108
--- /dev/null
+++ b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-58023.patch
@@ -0,0 +1,231 @@ 
+From 2f77969e8f841b225bd74bcfa4eeb341e78c06f7 Mon Sep 17 00:00:00 2001
+From: Javid Khan <dxbjavid@gmail.com>
+Date: Fri, 26 Jun 2026 21:35:32 +0200
+Subject: [PATCH] copy buffered data not the GByteArray struct in c_glib
+ read_slow Client: c_glib
+
+thrift_framed_transport_read_slow copies leftover bytes from the previous frame with memcpy(buf, t->r_buf, t->r_buf->len), passing the GByteArray struct pointer as the source instead of t->r_buf->data. The correct source is the buffer's data member, as used by the other memcpy calls in the same file. thrift_buffered_transport_read_slow contains the same mistake in its leftover path. Both are updated to read from t->r_buf->data, and a regression test using a memory buffer exercises the cross-boundary read path in each transport.
+
+This closes #3607
+
+CVE: CVE-2026-58023
+Upstream-Status: Backport [https://github.com/apache/thrift/commit/d68305a7308a11df2c1daef16f55dbc19dfa6ff0]
+
+Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech>
+---
+ .../transport/thrift_buffered_transport.c     |  2 +-
+ .../transport/thrift_framed_transport.c       |  2 +-
+ lib/c_glib/test/Makefile.am                   |  6 +-
+ lib/c_glib/test/testbufferedtransport.c       | 47 ++++++++++++++
+ lib/c_glib/test/testframedtransport.c         | 62 +++++++++++++++++++
+ 5 files changed, 115 insertions(+), 4 deletions(-)
+
+diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c
+index 30aa95caf..21e3e42d4 100644
+--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c
++++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_buffered_transport.c
+@@ -93,7 +93,7 @@ thrift_buffered_transport_read_slow (ThriftTransport *transport, gpointer buf,
+   /* first copy what we have in our buffer. */
+   if (have > 0)
+   {
+-    memcpy (buf, t->r_buf, t->r_buf->len);
++    memcpy (buf, t->r_buf->data, t->r_buf->len);
+     want -= t->r_buf->len;
+     t->r_buf = g_byte_array_remove_range (t->r_buf, 0, t->r_buf->len);
+   }
+diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c
+index 3cbb245e0..8deed4119 100644
+--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c
++++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c
+@@ -138,7 +138,7 @@ thrift_framed_transport_read_slow (ThriftTransport *transport, gpointer buf,
+   /* first copy what we have in our buffer, if there is anything left */
+   if (have > 0)
+   {
+-    memcpy (buf, t->r_buf, t->r_buf->len);
++    memcpy (buf, t->r_buf->data, t->r_buf->len);
+     want -= t->r_buf->len;
+     t->r_buf = g_byte_array_remove_range (t->r_buf, 0, t->r_buf->len);
+   }
+diff --git a/lib/c_glib/test/Makefile.am b/lib/c_glib/test/Makefile.am
+index 0a5f220ac..a879d9881 100644
+--- a/lib/c_glib/test/Makefile.am
++++ b/lib/c_glib/test/Makefile.am
+@@ -150,7 +150,8 @@ testbufferedtransport_LDADD = \
+     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \
+     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \
+     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o \
+-    $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o 
++    $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_memory_buffer.o \
++    $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
+ 
+ testframedtransport_SOURCES = testframedtransport.c
+ testframedtransport_LDADD = \
+@@ -158,7 +159,8 @@ testframedtransport_LDADD = \
+     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \
+     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \
+     $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o \
+-    $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o 
++    $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_memory_buffer.o \
++    $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_configuration.o
+ 
+ testzlibtransport_SOURCES = testzlibtransport.c
+ testzlibtransport_LDADD = \
+diff --git a/lib/c_glib/test/testbufferedtransport.c b/lib/c_glib/test/testbufferedtransport.c
+index d01806d61..7493b7222 100644
+--- a/lib/c_glib/test/testbufferedtransport.c
++++ b/lib/c_glib/test/testbufferedtransport.c
+@@ -25,6 +25,7 @@
+ #include <thrift/c_glib/transport/thrift_socket.h>
+ #include <thrift/c_glib/transport/thrift_server_transport.h>
+ #include <thrift/c_glib/transport/thrift_server_socket.h>
++#include <thrift/c_glib/transport/thrift_memory_buffer.h>
+ 
+ #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }
+ 
+@@ -306,6 +307,51 @@ test_write_fail(void)
+     }
+ }
+ 
++/* A read larger than the bytes already sitting in the read buffer takes the
++   read_slow() path with have > 0. That leftover used to be copied from the
++   GByteArray structure itself rather than its data member, which corrupted the
++   result and over-read the small struct allocation once more than a handful of
++   bytes were buffered. Pre-load the buffer and drive the read through a memory
++   buffer so the path is exercised without a socket peer. */
++static void
++test_read_across_buffer (void)
++{
++  ThriftBufferedTransport *bt;
++  ThriftTransport *transport;
++  ThriftMemoryBuffer *membuf;
++  guchar leftover[96];
++  guchar tail[4];
++  guchar buf[100];
++  gint32 got;
++  guint i;
++
++  for (i = 0; i < sizeof (leftover); i++)
++    leftover[i] = (guchar) (0x10 + i);
++  for (i = 0; i < sizeof (tail); i++)
++    tail[i] = (guchar) (0xc0 + i);
++
++  membuf = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 1024, NULL);
++  thrift_transport_write (THRIFT_TRANSPORT (membuf), tail, sizeof (tail), NULL);
++
++  transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
++                            "transport", THRIFT_TRANSPORT (membuf), NULL);
++
++  /* leave 96 bytes already buffered, more than sizeof(GByteArray) */
++  bt = THRIFT_BUFFERED_TRANSPORT (transport);
++  g_byte_array_append (bt->r_buf, leftover, sizeof (leftover));
++
++  /* this read exceeds the buffered bytes and must return the real buffered
++     data followed by the freshly read tail, not the GByteArray structure */
++  got = thrift_transport_read (transport, buf, 100, NULL);
++  g_assert (got == 100);
++  g_assert (memcmp (buf, leftover, 96) == 0);
++  g_assert (memcmp (buf + 96, tail, 4) == 0);
++
++  thrift_transport_read_end (transport, NULL);
++  g_object_unref (transport);
++  g_object_unref (membuf);
++}
++
+ int
+ main(int argc, char *argv[])
+ {
+@@ -319,6 +365,7 @@ main(int argc, char *argv[])
+   g_test_add_func ("/testbufferedtransport/OpenAndClose", test_open_and_close);
+   g_test_add_func ("/testbufferedtransport/ReadAndWrite", test_read_and_write);
+   g_test_add_func ("/testbufferedtransport/WriteFail", test_write_fail);
++  g_test_add_func ("/testbufferedtransport/ReadAcrossBuffer", test_read_across_buffer);
+ 
+   return g_test_run ();
+ }
+diff --git a/lib/c_glib/test/testframedtransport.c b/lib/c_glib/test/testframedtransport.c
+index 008e61e40..581b71067 100644
+--- a/lib/c_glib/test/testframedtransport.c
++++ b/lib/c_glib/test/testframedtransport.c
+@@ -24,6 +24,7 @@
+ #include <thrift/c_glib/transport/thrift_socket.h>
+ #include <thrift/c_glib/transport/thrift_server_transport.h>
+ #include <thrift/c_glib/transport/thrift_server_socket.h>
++#include <thrift/c_glib/transport/thrift_memory_buffer.h>
+ 
+ #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }
+ 
+@@ -305,6 +306,66 @@ thrift_server (const int port)
+   g_object_unref (tsocket);
+ }
+ 
++/* append a framed message (4-byte big-endian size header + body) */
++static void
++append_frame (GByteArray *wire, const guchar *data, guint32 len)
++{
++  guint32 netlen = htonl (len);
++  g_byte_array_append (wire, (const guchar *) &netlen, 4);
++  g_byte_array_append (wire, data, len);
++}
++
++/* A read whose length crosses a frame boundary takes the read_slow() path
++   while bytes are still buffered from the previous frame. That leftover used
++   to be copied from the GByteArray structure itself rather than its data
++   member, corrupting the result and over-reading the heap once more than a
++   handful of bytes remained. Drive it through a memory buffer so the path is
++   exercised without a socket peer. */
++static void
++test_read_across_frames (void)
++{
++  guchar f1[100];
++  guchar f2[100];
++  guchar buf[100];
++  gint32 got;
++  guint i;
++
++  for (i = 0; i < sizeof (f1); i++)
++    {
++      f1[i] = (guchar) (0x10 + i);
++      f2[i] = (guchar) (0xc0 + i);
++    }
++
++  GByteArray *wire = g_byte_array_new ();
++  append_frame (wire, f1, sizeof (f1));
++  append_frame (wire, f2, sizeof (f2));
++
++  ThriftMemoryBuffer *membuf = g_object_new (THRIFT_TYPE_MEMORY_BUFFER,
++                                             "buf", wire,
++                                             "buf_size", (guint32) 0,
++                                             NULL);
++  ThriftTransport *transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
++                                             "transport",
++                                             THRIFT_TRANSPORT (membuf),
++                                             NULL);
++
++  /* consume part of the first frame so 96 bytes stay buffered */
++  got = thrift_transport_read (transport, buf, 4, NULL);
++  g_assert (got == 4);
++  g_assert (memcmp (buf, f1, 4) == 0);
++
++  /* this read spans into the second frame and must return the real buffered
++     bytes, not the bytes of the GByteArray structure */
++  got = thrift_transport_read (transport, buf, 100, NULL);
++  g_assert (got == 100);
++  g_assert (memcmp (buf, f1 + 4, 96) == 0);
++  g_assert (memcmp (buf + 96, f2, 4) == 0);
++
++  thrift_transport_read_end (transport, NULL);
++  g_object_unref (transport);
++  g_object_unref (membuf);
++}
++
+ int
+ main(int argc, char *argv[])
+ {
+@@ -318,6 +379,7 @@ main(int argc, char *argv[])
+   g_test_add_func ("/testframedtransport/OpenAndClose", test_open_and_close);
+   g_test_add_func ("/testframedtransport/ReadAndWrite", test_read_and_write);
+   g_test_add_func ("/testframedtransport/ReadAfterPeerClose", test_read_after_peer_close);
++  g_test_add_func ("/testframedtransport/ReadAcrossFrames", test_read_across_frames);
+ 
+   return g_test_run ();
+ }
diff --git a/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb b/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
index 26849da0c8..b3f420bfe3 100644
--- a/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
+++ b/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
@@ -14,6 +14,7 @@  SRC_URI = "https://downloads.apache.org/${BPN}/${PV}/${BP}.tar.gz \
            file://CVE-2026-43868.patch \
            file://CVE-2026-43870.patch \
            file://CVE-2026-55971.patch \
+           file://CVE-2026-58023.patch \
            "
 SRC_URI[sha256sum] = "794a0e455787960d9f27ab92c38e34da27e8deeda7a5db0e59dc64a00df8a1e5"