Skip to main content

RDB_OPCODE_SLOT_IMPORT short job_name causes server-side heap out-of-bounds read during startup RDB loading

Author
quanye
Systems software: OS, networking, distributed systems.
Table of Contents

https://github.com/valkey-io/valkey/issues/4207

A security-class issue — link above; worth trying to fix.

Classic trust-boundary length-contract mismatch: the command path requires job_name to be exactly 40 bytes, but the RDB load path does not validate, so memcpy(..., 40) OOB-reads from a short SDS.

Nature of the bug (memory layout)
#

Subsystem contract
#

CLUSTER_NAMELEN == 40; job name is a fixed-length hex string (like a node id):

char name[CLUSTER_NAMELEN];               /* Unique name for the job, hex
	                                       * string, sha1-size. */
  • Save path: always writes 40 bytes
    rdbSaveRawString(rdb, job->name, CLUSTER_NAMELEN)
  • Command path: explicitly rejects non-40
    sdslen(...) != CLUSTER_NAMELEN
  • Load path (the hole): rdbLoadStringObject() accepts any length and hands it to createSlotImportJob()

Crash site
#

// 这就是RDB导入的时候造成的问题?
slotMigrationJob *createSlotImportJob(client *c,
                                      clusterNode *source_node,
                                      char *name,
                                      list *slot_ranges) {
    slotMigrationJob *job = zcalloc(sizeof(slotMigrationJob));
    memcpy(job->name, name, CLUSTER_NAMELEN);

When RDB job_name is only 1 byte:

heap:  [sdshdr...]['A']['\0'][ 后续可能是 freelist/相邻分配物 ...]
         ^ objectGetVal()
memcpy 要读 40 字节  越过 SDS 逻辑长度  heap OOB read

Destination job->name[40] is itself valid; the problem is the source lacks 40 readable bytes. ASan reports read, not write — typical DoS (reliable crash), not a direct arbitrary write.

Attack surface
#

Requires placing a malicious dump.rdb in the instance data directory with cluster-enabled yes. Common scenarios: backup poisoning, shared storage, bad restore flows. Not an unauthenticated remote protocol bug, but a startup trusted-input validation failure.

Trying to reproduce
#

How did AI find this? Fascinating. The issue describes the repro path in detail.

Step What
A Branch from unstable
B ASan repro (confirm crash)
C Add length check as suggested
D Add regression test (preferably Tcl, reject at startup load)
E Push to fork quanyeyang/valkey, open PR against valkey-io/valkey, link #4207
# 1) ASan 构建
make distclean
make -j"$(nproc)" SANITIZER=address OPTIMIZATION=-O0

# 2) 按 issue 生成 empty.rdb → 插入 opcode 0xF3 短 name → 重算 CRC64
# 3) cluster-enabled 实例加载该 dump.rdb
# 期望:ASan 在 memcpy 处报 heap-buffer-overflow READ