[meta-oe][scarthgap][PATCH 2/3] thrift: fix CVE-2026-58023
"Adarsh Jagadish Kamini" <[email protected]> Mon, 3 Aug 2026 16:17:11 +0200
| Newsgroups | org.openembedded.lists.openembedded-devel |
|---|---|
| Message-ID | <[email protected]> |
From: Adarsh Jagadish Kamini <[email protected]> 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/d68305a7308a11df2c1daef16f55dbc19= dfa6ff0 Signed-off-by: Adarsh Jagadish Kamini <[email protected]> --- .../thrift/thrift/CVE-2026-58023.patch | 231 ++++++++++++++++++ .../thrift/thrift_0.20.0.bb | 1 + 2 files changed, 232 insertions(+) create mode 100644 meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-580= 23.patch diff --git a/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-58023.patc= h b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-58023.patch new file mode 100644 index 0000000000..f6cc703369 --- /dev/null +++ b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-58023.patch @@ -0,0 +1,231 @@ +From 0459eb08472ea28695e0b78088ca7530ebc34238 Mon Sep 17 00:00:00 2001 +From: Javid Khan <[email protected]> +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 str= uct 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 fil= e. thrift_buffered_transport_read_slow contains the same mistake in its lef= tover 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 t= ransport. + +This closes #3607 + +CVE: CVE-2026-58023 +Upstream-Status: Backport [https://github.com/apache/thrift/commit/d68305a= 7308a11df2c1daef16f55dbc19dfa6ff0] + +Signed-off-by: Adarsh Jagadish Kamini <[email protected]> +--- + .../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_transp= ort.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 *tr= ansport, 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 -=3D t->r_buf->len; + t->r_buf =3D 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_transpor= t.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 *tr= ansport, 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 -=3D t->r_buf->len; + t->r_buf =3D 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 f3a0c30df..71cfc7970 100644 +--- a/lib/c_glib/test/Makefile.am ++++ b/lib/c_glib/test/Makefile.am +@@ -150,7 +150,8 @@ testbufferedtransport_LDADD =3D \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_server_socket.o \ +- $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thri= ft_configuration.o=20 ++ $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_memory_buffer.o \ ++ $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thri= ft_configuration.o +=20 + testframedtransport_SOURCES =3D testframedtransport.c + testframedtransport_LDADD =3D \ +@@ -158,7 +159,8 @@ testframedtransport_LDADD =3D \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_server_socket.o \ +- $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thri= ft_configuration.o=20 ++ $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_gl= ib_la-thrift_memory_buffer.o \ ++ $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thri= ft_configuration.o +=20 + testzlibtransport_SOURCES =3D testzlibtransport.c + testzlibtransport_LDADD =3D \ +diff --git a/lib/c_glib/test/testbufferedtransport.c b/lib/c_glib/test/tes= tbufferedtransport.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> +=20 + #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } +=20 +@@ -306,6 +307,51 @@ test_write_fail(void) + } + } +=20 ++/* 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 t= he ++ GByteArray structure itself rather than its data member, which corrupt= ed the ++ result and over-read the small struct allocation once more than a hand= ful 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 =3D 0; i < sizeof (leftover); i++) ++ leftover[i] =3D (guchar) (0x10 + i); ++ for (i =3D 0; i < sizeof (tail); i++) ++ tail[i] =3D (guchar) (0xc0 + i); ++ ++ membuf =3D g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 1024, N= ULL); ++ thrift_transport_write (THRIFT_TRANSPORT (membuf), tail, sizeof (tail),= NULL); ++ ++ transport =3D g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, ++ "transport", THRIFT_TRANSPORT (membuf), NULL)= ; ++ ++ /* leave 96 bytes already buffered, more than sizeof(GByteArray) */ ++ bt =3D 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 buffer= ed ++ data followed by the freshly read tail, not the GByteArray structure= */ ++ got =3D thrift_transport_read (transport, buf, 100, NULL); ++ g_assert (got =3D=3D 100); ++ g_assert (memcmp (buf, leftover, 96) =3D=3D 0); ++ g_assert (memcmp (buf + 96, tail, 4) =3D=3D 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_c= lose); + g_test_add_func ("/testbufferedtransport/ReadAndWrite", test_read_and_w= rite); + g_test_add_func ("/testbufferedtransport/WriteFail", test_write_fail); ++ g_test_add_func ("/testbufferedtransport/ReadAcrossBuffer", test_read_a= cross_buffer); +=20 + return g_test_run (); + } +diff --git a/lib/c_glib/test/testframedtransport.c b/lib/c_glib/test/testf= ramedtransport.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> +=20 + #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } +=20 +@@ -305,6 +306,66 @@ thrift_server (const int port) + g_object_unref (tsocket); + } +=20 ++/* append a framed message (4-byte big-endian size header + body) */ ++static void ++append_frame (GByteArray *wire, const guchar *data, guint32 len) ++{ ++ guint32 netlen =3D 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() pat= h ++ 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 pat= h 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 =3D 0; i < sizeof (f1); i++) ++ { ++ f1[i] =3D (guchar) (0x10 + i); ++ f2[i] =3D (guchar) (0xc0 + i); ++ } ++ ++ GByteArray *wire =3D g_byte_array_new (); ++ append_frame (wire, f1, sizeof (f1)); ++ append_frame (wire, f2, sizeof (f2)); ++ ++ ThriftMemoryBuffer *membuf =3D g_object_new (THRIFT_TYPE_MEMORY_BUFFER, ++ "buf", wire, ++ "buf_size", (guint32) 0, ++ NULL); ++ ThriftTransport *transport =3D g_object_new (THRIFT_TYPE_FRAMED_TRANSPO= RT, ++ "transport", ++ THRIFT_TRANSPORT (membuf), ++ NULL); ++ ++ /* consume part of the first frame so 96 bytes stay buffered */ ++ got =3D thrift_transport_read (transport, buf, 4, NULL); ++ g_assert (got =3D=3D 4); ++ g_assert (memcmp (buf, f1, 4) =3D=3D 0); ++ ++ /* this read spans into the second frame and must return the real buffe= red ++ bytes, not the bytes of the GByteArray structure */ ++ got =3D thrift_transport_read (transport, buf, 100, NULL); ++ g_assert (got =3D=3D 100); ++ g_assert (memcmp (buf, f1 + 4, 96) =3D=3D 0); ++ g_assert (memcmp (buf + 96, f2, 4) =3D=3D 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_clo= se); + g_test_add_func ("/testframedtransport/ReadAndWrite", test_read_and_wri= te); + g_test_add_func ("/testframedtransport/ReadAfterPeerClose", test_read_a= fter_peer_close); ++ g_test_add_func ("/testframedtransport/ReadAcrossFrames", test_read_acr= oss_frames); +=20 + return g_test_run (); + } diff --git a/meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb b/meta-oe= /recipes-connectivity/thrift/thrift_0.20.0.bb index 23a6debf9a..35482d2471 100644 --- a/meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb +++ b/meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb @@ -13,6 +13,7 @@ SRC_URI =3D "https://archive.apache.org/dist/${BPN}/${PV}= /${BP}.tar.gz \ file://0001-thrift-pr2755.patch \ file://0001-THRIFT-5842-Add-missing-cstdint-include-for-int64_t= -.patch \ file://CVE-2026-55971.patch \ + file://CVE-2026-58023.patch \ " SRC_URI[sha256sum] =3D "b5d8311a779470e1502c027f428a1db542f5c051c8e1280ccd= 2163fa935ff2d6" =20