diff mbox series

[meta-oe,wrynose] rabbitmq-c: fix CVE-2026-61547

Message ID 20261009100104.2059406-1-Poornima.Lokesh@windriver.com
State New
Headers show
Series [meta-oe,wrynose] rabbitmq-c: fix CVE-2026-61547 | expand

Commit Message

Poornima Lokesh Oct. 9, 2026, 10:01 a.m. UTC
A heap buffer overflow exists in rabbitmq-c when the public
amqp_send_frame() API is used to serialize an oversized AMQP_FRAME_BODY.
The issue occurs because amqp_frame_to_bytes() copies
frame.payload.body_fragment.len bytes into the connection outbound
buffer without validating that the body fragment fits within the
allocated frame buffer. An application that passes an oversized body
frame to amqp_send_frame() can trigger a heap out-of-bounds write,
resulting in process crash and memory corruption.

Reference:
[https://security-tracker.debian.org/tracker/CVE-2026-61547]
[https://github.com/alanxz/rabbitmq-c/security/advisories/GHSA-hfjv-vcp3-39wh]

Backport the patch to fix CVE-2026-61547
[https://github.com/alanxz/rabbitmq-c/commit/02d278663f3a93db9fe4fb4e7e34dc96b83c107b]

Signed-off-by: Poornima Lokesh <Poornima.Lokesh@windriver.com>
---
 .../rabbitmq-c/CVE-2026-61547.patch           | 128 ++++++++++++++++++
 .../rabbitmq-c/rabbitmq-c_0.15.0.bb           |   1 +
 2 files changed, 129 insertions(+)
 create mode 100644 meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c/CVE-2026-61547.patch
diff mbox series

Patch

diff --git a/meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c/CVE-2026-61547.patch b/meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c/CVE-2026-61547.patch
new file mode 100644
index 0000000000..d1e479c308
--- /dev/null
+++ b/meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c/CVE-2026-61547.patch
@@ -0,0 +1,128 @@ 
+From 413658f73078b91dee9efb442add63cbf3cc8dea Mon Sep 17 00:00:00 2001
+From: Poornima Lokesh <Poornima.Lokesh@windriver.com>
+Date: Thu, 8 Oct 2026 09:29:12 +0000
+Subject: [PATCH] rabbitmq-c: patch CVE-2026-61547
+
+Fix heap buffer overflow in amqp_frame_to_bytes for oversized body frames.
+
+amqp_send_frame() -> amqp_frame_to_bytes() copied
+frame.payload.body_fragment.len bytes into the outbound buffer without
+validating that the body fragment fit within the allocated frame buffer.
+An application passing an oversized AMQP_FRAME_BODY to the public
+amqp_send_frame() API could trigger a heap out-of-bounds write.
+
+Bound the body fragment to the usable payload size
+(buffer.len - HEADER_SIZE - FOOTER_SIZE), returning
+AMQP_STATUS_BAD_AMQP_DATA when it does not fit. Add a regression test.
+
+Details:
+https://nvd.nist.gov/vuln/detail/CVE-2026-61547
+
+CVE: CVE-2026-61547
+
+Upstream-Status: Backport [https://github.com/alanxz/rabbitmq-c/commit/02d278663f3a93db9fe4fb4e7e34dc96b83c107b]
+
+Signed-off-by: Poornima Lokesh <Poornima.Lokesh@windriver.com>
+---
+ librabbitmq/amqp_connection.c |  8 +++++
+ tests/CMakeLists.txt          |  3 ++
+ tests/test_send_frame.c       | 57 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 68 insertions(+)
+ create mode 100644 tests/test_send_frame.c
+
+diff --git a/librabbitmq/amqp_connection.c b/librabbitmq/amqp_connection.c
+index 56ab8a8..8c1e9c0 100644
+--- a/librabbitmq/amqp_connection.c
++++ b/librabbitmq/amqp_connection.c
+@@ -441,6 +441,14 @@ static int amqp_frame_to_bytes(const amqp_frame_t *frame, amqp_bytes_t buffer,
+     case AMQP_FRAME_BODY: {
+       const amqp_bytes_t *body = &frame->payload.body_fragment;
+ 
++      /* Ensure the body fragment fits within the outbound buffer, leaving
++       * room for the frame header and footer. Without this check an
++       * oversized body fragment would overflow the heap-allocated buffer. */
++      if (buffer.len < HEADER_SIZE + FOOTER_SIZE ||
++          body->len > buffer.len - (HEADER_SIZE + FOOTER_SIZE)) {
++        return AMQP_STATUS_BAD_AMQP_DATA;
++      }
++
+       memcpy(amqp_offset(out_frame, HEADER_SIZE), body->bytes, body->len);
+ 
+       out_frame_len = body->len;
+diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
+index 8c0aee0..194af0c 100644
+--- a/tests/CMakeLists.txt
++++ b/tests/CMakeLists.txt
+@@ -41,3 +41,6 @@ add_executable(test_merge_capabilities test_merge_capabilities.c)
+ target_link_libraries(test_merge_capabilities rabbitmq-static)
+ add_test(merge_capabilities test_merge_capabilities)
+ 
++add_executable(test_send_frame test_send_frame.c)
++target_link_libraries(test_send_frame rabbitmq-static)
++add_test(send_frame test_send_frame)
+diff --git a/tests/test_send_frame.c b/tests/test_send_frame.c
+new file mode 100644
+index 0000000..4d8e067
+--- /dev/null
++++ b/tests/test_send_frame.c
+@@ -0,0 +1,57 @@
++// Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
++// SPDX-License-Identifier: mit
++
++#include "amqp_private.h"
++#include <rabbitmq-c/amqp.h>
++#include <rabbitmq-c/framing.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++/* Regression test for GHSA-hfjv-vcp3-39wh: passing an oversized
++ * AMQP_FRAME_BODY to amqp_send_frame() must not overflow the outbound
++ * buffer. It should be rejected with AMQP_STATUS_BAD_AMQP_DATA. */
++static void test_oversized_body_frame_rejected(void) {
++  amqp_connection_state_t state = amqp_new_connection();
++  amqp_frame_t frame;
++  size_t body_len;
++  char *body;
++  int res;
++
++  if (state == NULL) {
++    fprintf(stderr, "amqp_new_connection failed\n");
++    abort();
++  }
++
++  /* The default outbound buffer is AMQP_DEFAULT_FRAME_SIZE bytes; use a
++   * body fragment that is larger than that buffer can hold. */
++  body_len = state->outbound_buffer.len + 1024;
++  body = malloc(body_len);
++  if (body == NULL) {
++    fprintf(stderr, "malloc failed\n");
++    abort();
++  }
++  memset(body, 'A', body_len);
++
++  memset(&frame, 0, sizeof(frame));
++  frame.frame_type = AMQP_FRAME_BODY;
++  frame.channel = 1;
++  frame.payload.body_fragment.bytes = body;
++  frame.payload.body_fragment.len = body_len;
++
++  res = amqp_send_frame(state, &frame);
++  if (res != AMQP_STATUS_BAD_AMQP_DATA) {
++    fprintf(stderr, "expected AMQP_STATUS_BAD_AMQP_DATA (%d), got %d\n",
++            AMQP_STATUS_BAD_AMQP_DATA, res);
++    abort();
++  }
++
++  free(body);
++  amqp_destroy_connection(state);
++}
++
++int main(void) {
++  test_oversized_body_frame_rejected();
++  return 0;
++}
+-- 
+2.35.5
+
diff --git a/meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c_0.15.0.bb b/meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c_0.15.0.bb
index 4fd6302f2c..b8bc5b57e3 100644
--- a/meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c_0.15.0.bb
+++ b/meta-oe/recipes-connectivity/rabbitmq-c/rabbitmq-c_0.15.0.bb
@@ -4,6 +4,7 @@  LIC_FILES_CHKSUM = "file://LICENSE;md5=7e12f6e40e662e039e2f02b4893011ec"
 LICENSE = "MIT"
 
 SRC_URI = "git://github.com/alanxz/rabbitmq-c.git;branch=master;protocol=https \
+	   file://CVE-2026-61547.patch \
 "
 SRCREV = "84b81cd97a1b5515d3d4b304796680da24c666d8"