Fix use-after-free when evicting blocked client during unblock (CVE-2026-23479)

When re-executing a pending command after unblocking, check the return value
of `processCommandAndResetClient` and exit if needed.
This commit is contained in:
debing.sun 2025-12-29 16:20:41 +08:00 committed by YaacovHazan
parent 0cca172a17
commit c14e9925e5
2 changed files with 36 additions and 1 deletions

View file

@ -691,7 +691,13 @@ static void unblockClientOnKey(client *c, robj *key) {
client *old_client = server.current_client;
server.current_client = c;
enterExecutionUnit(1, 0);
processCommandAndResetClient(c);
if (processCommandAndResetClient(c) == C_ERR) {
/* Client was freed during command processing, exit immediately */
exitExecutionUnit();
server.current_client = old_client;
return;
}
if (!(c->flags & CLIENT_BLOCKED)) {
if (c->flags & CLIENT_MODULE) {
moduleCallCommandUnblockedHandler(c);

View file

@ -619,5 +619,34 @@ start_server {} {
}
}
start_server {} {
r flushall
r client no-evict on
r config set maxmemory-clients 0
test "Verify blocked client eviction during unblock does not cause use-after-free" {
# Create a deferring client that will be blocked on stream
# Use a long stream name to make client memory usage exceed 200000 bytes
set rd [redis_deferring_client]
$rd XREAD BLOCK 0 STREAMS mystream stream_[string repeat x 200000] $ $
# Wait for the client to be blocked
wait_for_condition 50 100 {
[s blocked_clients] eq {1}
} else {
fail "Client was not blocked"
}
# Now lower MAXMEMORY-CLIENTS to a low value and use
# XADD to unblock the blocked client, triggering eviction.
r MULTI
r CONFIG SET MAXMEMORY-CLIENTS 100000 ;# Put in MULTI to defer blocked client eviction until after EXEC
r XADD mystream * field val
r EXEC
r PING
$rd close
}
}
} ;# tags