diff mbox series

[meta-oe,wrynose,4/4] redis: fix CVE-2026-66373

Message ID 20261016052110.184934-4-yurade@cisco.com
State New
Headers show
Series [meta-oe,wrynose,1/4] redis: fix CVE-2026-23479 | expand

Commit Message

Yogita Urade Oct. 16, 2026, 5:21 a.m. UTC
This patch applies the upstream fix as referenced in [2],
using the commit shown in [1].

[1] https://github.com/redis/redis/commit/4f62a8bf15c634187d8a87d874f8988032f90b6c
[2] https://nvd.nist.gov/vuln/detail/CVE-2026-66373

Signed-off-by: Yogita Urade <yurade@cisco.com>
---
 .../redis/redis-8.0.6/CVE-2026-66373.patch    | 96 +++++++++++++++++++
 meta-oe/recipes-extended/redis/redis_8.0.6.bb |  1 +
 2 files changed, 97 insertions(+)
 create mode 100644 meta-oe/recipes-extended/redis/redis-8.0.6/CVE-2026-66373.patch
diff mbox series

Patch

diff --git a/meta-oe/recipes-extended/redis/redis-8.0.6/CVE-2026-66373.patch b/meta-oe/recipes-extended/redis/redis-8.0.6/CVE-2026-66373.patch
new file mode 100644
index 0000000000..3350ad2a70
--- /dev/null
+++ b/meta-oe/recipes-extended/redis/redis-8.0.6/CVE-2026-66373.patch
@@ -0,0 +1,96 @@ 
+From 4f62a8bf15c634187d8a87d874f8988032f90b6c Mon Sep 17 00:00:00 2001
+From: sggeorgiev <s_ggeorgiev@yahoo.com>
+Date: Thu, 23 Apr 2026 15:46:48 +0300
+Subject: [PATCH] Reject corrupt stream RDB with shared NACK across consumers
+ (#15081)
+
+**Summary**
+
+Detects and rejects corrupt stream RDB payloads where the same NACK
+(pending entry) is referenced by more than one consumer, which violates
+a stream data-structure.
+
+**Changes**
+
+- **`rdbLoadObject` (stream consumer PEL loading)**: Added a guard that
+checks `nack->consumer != NULL` before assigning the consumer pointer.
+When a second consumer's PEL references a NACK that was already claimed
+by a prior consumer, the loader now reports a corrupt RDB error and
+aborts instead of silently overwriting the pointer. Without this check,
+two consumers share the same `streamNACK`, and freeing the first
+consumer's PEL leaves the second with a dangling pointer.
+- **`corrupt-dump.tcl`**: Added a regression test that crafts a stream
+with two consumers (`consumerA`, `consumerB`) whose PELs both reference
+the same entry (`1-0`). The `RESTORE` command is expected to fail with
+`"Bad data format"`, and the server must remain responsive (`PING`
+succeeds).
+
+**Benefits**
+
+- **Fail-fast on corrupt data**: The invariant violation is caught at
+load time with a clear diagnostic message rather than manifesting as a
+crash later during normal operation.
+- **Regression coverage**: The crafted payload in the test ensures this
+class of corruption is permanently guarded against.
+
+CVE: CVE-2026-66373
+Upstream-Status: Backport [https://github.com/redis/redis/commit/4f62a8bf15c634187d8a87d874f8988032f90b6c]
+
+(cherry picked from commit 4f62a8bf15c634187d8a87d874f8988032f90b6c)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ src/rdb.c                          |  8 ++++++++
+ tests/integration/corrupt-dump.tcl | 18 +++++++++++++++++-
+ 2 files changed, 25 insertions(+), 1 deletion(-)
+
+diff --git a/src/rdb.c b/src/rdb.c
+index 371353c2c..277ca543c 100644
+--- a/src/rdb.c
++++ b/src/rdb.c
+@@ -3060,6 +3060,14 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int dbid, int *error)
+                     }
+                     streamNACK *nack = result;
+ 
++                    /* If the NACK already has a consumer assigned, the
++                     * payload is corrupt — each global PEL entry must be
++                     * claimed by exactly one consumer. */
++                    if (nack->consumer != NULL) {
++                        rdbReportCorruptRDB("Stream consumer PEL entry already has a consumer assigned");
++                        decrRefCount(o);
++                        return NULL;
++                    }
+                     /* Set the NACK consumer, that was left to NULL when
+                      * loading the global PEL. Then set the same shared
+                      * NACK structure also in the consumer-specific PEL. */
+diff --git a/tests/integration/corrupt-dump.tcl b/tests/integration/corrupt-dump.tcl
+index 6017723e0..b04812e0f 100644
+--- a/tests/integration/corrupt-dump.tcl
++++ b/tests/integration/corrupt-dump.tcl
+@@ -1020,10 +1020,26 @@ test {corrupt payload: stream - duplicated consumer PEL entry} {
+             r restore key 0 "\x15\x01\x10\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\xc3\x39\x40\x42\x15\x42\x00\x00\x00\x11\x00\x02\x01\x00\x01\x01\x01\x86\x66\x69\x65\x6c\x64\x31\x07\x00\x01\x40\x0f\x0a\x00\x01\x86\x76\x61\x6c\x75\x65\x31\x07\x04\x20\x0b\x02\xcd\xd9\x02\xe0\x01\x22\x01\x32\x07\x80\x1a\x04\x32\x07\x06\x01\xff\x02\x81\x00\x00\x01\x9b\x0d\x56\xb7\x90\x00\x81\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x02\x01\x07\x6d\x79\x67\x72\x6f\x75\x70\x81\x00\x00\x01\x9b\x0d\x56\xb7\x90\x00\x02\x02\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\x80\xd9\x56\x0d\x9b\x01\x00\x00\x01\x00\x00\x01\x9b\x0d\x56\xb7\x90\x00\x00\x00\x00\x00\x00\x00\x00\x80\xd9\x56\x0d\x9b\x01\x00\x00\x01\x01\x09\x63\x6f\x6e\x73\x75\x6d\x65\x72\x31\x80\xd9\x56\x0d\x9b\x01\x00\x00\x80\xd9\x56\x0d\x9b\x01\x00\x00\x02\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x9b\x0d\x56\xa9\xb7\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x4b\xe0\x99\x30\x67\x4d\xe5\x87"
+         } err
+         assert_match "*Bad data format*" $err
+-        verify_log_message 0 "*Duplicated consumer PEL entry*" 0
++        verify_log_message 0 "*Stream consumer PEL entry already has a consumer assigned*" 0
+     }
+ }
+ 
+ 
++test {corrupt payload: stream with NACK shared between two consumers} {
++    start_server [list overrides [list loglevel verbose use-exit-on-panic yes crash-memcheck-enabled no]] {
++        r debug set-skip-checksum-validation 1
++        # Payload: stream with entry 1-0, one consumer group (mygroup),
++        # two consumers whose PELs both reference 1-0 (shared NACK).
++        # XACK on one consumer frees the NACK, leaving a dangling
++        # pointer in the other consumer's PEL (use-after-free).
++        catch {r RESTORE mystream 0 "\x1a\x01\x10\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x1d\x00\x00\x00\x0a\x00\x01\x01\x00\x01\x01\x01\x81\x6b\x02\x00\x01\x02\x01\x00\x01\x00\x01\x81\x76\x02\x04\x01\xff\x01\x01\x00\x01\x00\x00\x00\x01\x01\x07\x6d\x79\x67\x72\x6f\x75\x70\x01\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x64\x42\xb9\x9d\x01\x00\x00\x01\x02\x09\x63\x6f\x6e\x73\x75\x6d\x65\x72\x41\x01\x64\x42\xb9\x9d\x01\x00\x00\x01\x64\x42\xb9\x9d\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x09\x63\x6f\x6e\x73\x75\x6d\x65\x72\x42\x01\x64\x42\xb9\x9d\x01\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x40\x64\x40\x64\x00\x00\x00\x0d\x00\xe7\x12\xf7\xcc\x25\xd5\x0e\x44"} err
++        catch {r XACK mystream mygroup 1-0} _
++        catch {r XREADGROUP GROUP mygroup consumerA COUNT 10 STREAMS mystream 0} _
++        catch {r DEL mystream} _
++        assert_match "*Bad data format*" $err
++        r ping
++    }
++}
++
+ } ;# tags
+ 
diff --git a/meta-oe/recipes-extended/redis/redis_8.0.6.bb b/meta-oe/recipes-extended/redis/redis_8.0.6.bb
index 5d4ca143d1..04641a9dab 100644
--- a/meta-oe/recipes-extended/redis/redis_8.0.6.bb
+++ b/meta-oe/recipes-extended/redis/redis_8.0.6.bb
@@ -19,6 +19,7 @@  SRC_URI = "http://download.redis.io/releases/${BP}.tar.gz \
            file://CVE-2026-23479.patch \
            file://CVE-2026-23631.patch \
            file://CVE-2026-25243.patch \
+           file://CVE-2026-66373.patch \
           "
 SRC_URI[sha256sum] = "6d0a9913887a4972536f9da226f1575859c34d86354129163260a5f9c6bd4229"