new file mode 100644
@@ -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"
++ }
++ }
++ }
++}
@@ -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"
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