diff mbox series

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

Message ID 20261016052110.184934-2-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/0cca172a174642bdae03b871615227896274d9bb
[2] https://nvd.nist.gov/vuln/detail/CVE-2026-23631

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

Patch

diff --git a/meta-oe/recipes-extended/redis/redis-8.0.6/CVE-2026-23631.patch b/meta-oe/recipes-extended/redis/redis-8.0.6/CVE-2026-23631.patch
new file mode 100644
index 0000000000..abb3098820
--- /dev/null
+++ b/meta-oe/recipes-extended/redis/redis-8.0.6/CVE-2026-23631.patch
@@ -0,0 +1,119 @@ 
+From 0cca172a174642bdae03b871615227896274d9bb Mon Sep 17 00:00:00 2001
+From: Ozan Tezcan <ozantezcan@gmail.com>
+Date: Tue, 14 Apr 2026 08:47:04 +0300
+Subject: [PATCH] Fix use-after-free when fullsync happens while replica is
+ running a timed out script (CVE-2026-23631)
+
+Fullsync triggers emptyData and scriptingReset which free the scripting/function engine. If a timed out script is still running on the replica, this causes a use-after-free. Delay fullsync processing in readSyncBulkPayload until the script finishes.
+
+CVE: CVE-2026-23631
+Upstream-Status: Backport [https://github.com/redis/redis/commit/0cca172a174642bdae03b871615227896274d9bb]
+
+(cherry picked from commit 0cca172a174642bdae03b871615227896274d9bb)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ src/replication.c                 |  5 ++
+ tests/integration/replication.tcl | 77 +++++++++++++++++++++++++++++++
+ 2 files changed, 82 insertions(+)
+
+diff --git a/src/replication.c b/src/replication.c
+index 5fab23b1c..489032aed 100644
+--- a/src/replication.c
++++ b/src/replication.c
+@@ -2022,6 +2022,11 @@ void replicationAttachToNewMaster(void) {
+ /* Asynchronously read the SYNC payload we receive from a master */
+ #define REPL_MAX_WRITTEN_BEFORE_FSYNC (1024*1024*8) /* 8 MB */
+ void readSyncBulkPayload(connection *conn) {
++    /* During full sync, the functions engine is freed right before loading
++     * the RDB. To avoid this happening while a function is still running,
++     * delay full sync processing until it finishes. */
++    if (isInsideYieldingLongCommand()) return;
++
+     char buf[PROTO_IOBUF_LEN];
+     ssize_t nread, readlen, nwritten;
+     int use_diskless_load = useDisklessLoad();
+diff --git a/tests/integration/replication.tcl b/tests/integration/replication.tcl
+index 65494f427..412a00740 100644
+--- a/tests/integration/replication.tcl
++++ b/tests/integration/replication.tcl
+@@ -1661,3 +1661,80 @@ start_server {tags {"repl external:skip"}} {
+         }
+     }
+ }
++
++# Fullsync should not free the functions lib ctx while the replica has 
++# a timed out function that is still running.
++foreach type {script function} {
++    start_server {tags {"repl external:skip"}} {
++        start_server {} {
++            set master [srv -1 client]
++            set master_host [srv -1 host]
++            set master_port [srv -1 port]
++            set replica [srv 0 client]
++
++            test "Fullsync should not free scripting engine on a replica while a $type is running" {
++                $master config set repl-diskless-sync yes
++                $master config set repl-diskless-sync-delay 0
++                # Set small client output buffer limit to trigger fullsync quickly
++                $master config set client-output-buffer-limit "replica 1k 1k 0"
++                $replica config set repl-diskless-load yes
++                $replica config set busy-reply-threshold 1 ;# script timeout in 1 ms
++
++                # Load function
++                if {$type eq "function"} {
++                    $master function load replace {#!lua name=blocklib
++                        redis.register_function{
++                            function_name='blockfunc',
++                            callback=function() while true do end end,
++                            flags={'no-writes'}
++                        }
++                    }
++                }
++
++                # Start replication
++                $replica replicaof $master_host $master_port
++                wait_for_sync $replica
++
++                # Run the blocking script on replica
++                set rd [redis_deferring_client]
++                if {$type eq "script"} {
++                    $rd eval {while true do end} 0
++                } else {
++                    $rd fcall_ro blockfunc 0
++                }
++
++                # Verify replica replies with BUSY
++                wait_for_condition 50 100 {
++                    [catch {$replica ping} e] == 1 && [string match {*BUSY*} $e]
++                } else {
++                    fail "$type didn't become busy"
++                }
++
++                # Fills client output buffer and triggers fullsync
++                populate 5 bigkey 1000000 -1
++                wait_for_condition 50 100 {
++                    [s -1 sync_full] >= 2
++                } else {
++                    fail "Fullsync was not triggered"
++                }
++                
++                # Verify replica is still running the function
++                after 1000
++                catch {$replica ping} e
++                assert_match {*BUSY*} $e "replica should still reply with BUSY"
++
++                if {$type eq "script"} {
++                    $replica script kill
++                } else {
++                    $replica function kill
++                }
++
++                # Verify replica is responsive again
++                catch {$rd read} result
++                $rd close
++                wait_for_sync $replica
++                assert_equal [$replica ping] "PONG"
++            }
++        }
++    }
++}
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 f09bb8aba2..a83ffbae48 100644
--- a/meta-oe/recipes-extended/redis/redis_8.0.6.bb
+++ b/meta-oe/recipes-extended/redis/redis_8.0.6.bb
@@ -17,6 +17,7 @@  SRC_URI = "http://download.redis.io/releases/${BP}.tar.gz \
            file://0005-Define-_GNU_SOURCE-to-get-PTHREAD_MUTEX_INITIALIZER.patch \
            file://CVE-2026-81934.patch \
            file://CVE-2026-23479.patch \
+           file://CVE-2026-23631.patch \
           "
 SRC_URI[sha256sum] = "6d0a9913887a4972536f9da226f1575859c34d86354129163260a5f9c6bd4229"