https://github.com/valkey-io/valkey/issues/4207 一类安全性问题,上面是issue界面,可以尝试解决一下。
典型的 trust-boundary 长度契约不一致——命令路径强制 job_name 必须是 40 字节,
RDB 加载路径却没校验,导致 memcpy(..., 40) 从短 SDS 上越界读。
漏洞本质(从内存布局看) #
子系统约定 #
CLUSTER_NAMELEN == 40,job name 是固定长度 hex(类似 node id):
char name[CLUSTER_NAMELEN]; /* Unique name for the job, hex
* string, sha1-size. */
- Save 路径:写死 40 字节
rdbSaveRawString(rdb, job->name, CLUSTER_NAMELEN) - 命令路径:显式拒绝非 40 字节
sdslen(...) != CLUSTER_NAMELEN - Load 路径(有洞):
rdbLoadStringObject()接受任意长度字符串,原样交给createSlotImportJob()
崩溃点 #
// 这就是RDB导入的时候造成的问题?
slotMigrationJob *createSlotImportJob(client *c,
clusterNode *source_node,
char *name,
list *slot_ranges) {
slotMigrationJob *job = zcalloc(sizeof(slotMigrationJob));
memcpy(job->name, name, CLUSTER_NAMELEN);
当 RDB 里 job_name 只有 1 字节时:
heap: [sdshdr...]['A']['\0'][ 后续可能是 freelist/相邻分配物 ...]
^ objectGetVal()
memcpy 要读 40 字节 → 越过 SDS 逻辑长度 → heap OOB read
目标 job->name[40] 本身合法;问题是源指针没有 40 字节可读数据。
ASan 报的是 read,不是 write——典型 DoS(可靠 crash),不是直接任意写。
攻击面 #
需要把恶意 dump.rdb 放到实例数据目录,并开 cluster-enabled yes。
常见场景:备份投毒、共享存储、错误恢复流程。不是远程未认证协议洞,但仍是启动期可信输入校验失败。
尝试复现问题 #
太神奇了,这是怎么使用AI发现的? 复现路径在issue中描述的非常详细。
| 步骤 | 做什么 |
|---|---|
| A | 从 unstable 拉新分支 |
| B | ASan 复现(确认 crash) |
| C | 按建议加长度校验 |
| D | 加回归测试(最好 Tcl,启动期拒载) |
| E | 推到你的 fork quanyeyang/valkey,对 valkey-io/valkey 开 PR,关联 #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