You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Use-after-free: KeyDB does not remove module cluster message receivers on MODULE UNLOAD #980
Summary
When a module registers a cluster message receiver (RM_RegisterClusterMessageReceiver), an entry is stored in the global clusterReceivers[] list holding the module handle and a callback pointer into the module's .so. KeyDB's module-unload path (moduleUnload, src/module.cpp:8806) cleans up commands, shared APIs, notifications, etc., but never removes the module's cluster receivers. After MODULE UNLOAD, clusterReceivers[type] still points at a receiver whose module/callback reference the freed module and the dlclose'd .so. The next CLUSTERMSG_TYPE_MODULE packet of that type → moduleCallClusterReceivers dereferences the freed module and calls the stale callback → use-after-free.
Affected version
KeyDB @603ebb27fb (2024-04-04, dev "255.255.255"). Present since the Redis fork point; KeyDB is frozen at ~2024 and never took the Valkey fix (#4360). Confirm the affected release range (KeyDB 6.x) with the vendor.
Technical details
moduleUnload (src/module.cpp:8806+) calls moduleUnregisterCommands, moduleUnregisterSharedAPI, moduleUnsubscribeNotifications, ... — there is no clusterReceivers cleanup anywhere in the unload path (the only references to clusterReceivers are the register/dispatch sites at module.cpp:6184–6241). So the receiver node survives (leaked-but-live) with dangling module/callback.
Proof of concept
Dynamically reproduced on a 2-node ASan KeyDB cluster (@603ebb27, built SANITIZE=address MALLOC=libc BUILD_TLS=no NO_MOTD=yes):
Both nodes --loadmodule uaftest.so (registers a cluster receiver for type 42 + a sendbad command that broadcasts a type-42 cluster message).
CLUSTER MEET; wait for full connectivity (both nodes connected, no handshake).
MODULE UNLOAD uaftest on node1 → clusterReceivers[42] dangles.
sendbad on node2 → broadcasts a type-42 cluster message.
node1 crashes — SIGSEGV on the cluster-message thread executing the dlclose'd module's callback: Module uaftest unloaded → crashed by signal: 11 ... Crashed running the instruction at: 0x.
(evidence/node1-crash-backtrace.txt; POC/uaftest.c; POC/repro-2node-cluster.sh.) Matches the ASan-confirmed Redis finding ID-REDIS-CLUSTERRECV-UNLOAD-UAF-01.
Activity