feat(memhub): detection 增强 - free 后用户区填 0xCD + 记录保留并置 free 标志,探测时对仍 free 的块验证 0xCD 完整(首末 8 字节),被写穿即 [DET] UAF 写入 报警终止 - 拦截 use-after-free 写入(如 SlotsBugTest KwEntry cargs 块 free 后被部分覆盖),与后标记越界写检测互补;块被重新 alloc 后块头变奇数自动跳过旧 free 记录防误报
This commit is contained in:
1 parent
0efd438bfb
commit
91120ae00a
1 file changed
+30
-5
+30
-5
@@ -729,13 +729,18 @@ class MemBuddy(MemManager):
|
||||
if self.detection != 0:
|
||||
# [DET] 返回指针比实际用户区靠后 2 字节,回收时向前偏移 2
|
||||
p_eff = t.CVoid(t.CUInt64T(ptr) - 2, t.CPtr)
|
||||
# 从记录表移除该条(置 size=0):块复用后旧后标记位置
|
||||
# 会被新数据覆盖,若不移除会导致 _det_probe 误报
|
||||
# 从记录表取本条真实 size,free 后把用户区填 0xCD(UAF 写入
|
||||
# 检测:free 后块被写穿 → 探测时 0xCD 被破坏 → 报警);记录
|
||||
# 保留并置 free 标志(探测时对仍 free 的块验证 0xCD 完整)。
|
||||
if self._det_records is not None:
|
||||
ri: t.CSizeT = 0
|
||||
while ri < self._det_count:
|
||||
if self._det_records[ri * 2] == t.CUInt64T(ptr):
|
||||
self._det_records[ri * 2 + 1] = 0
|
||||
rp: t.CUInt64T = self._det_records[ri * 2]
|
||||
rs: t.CUInt64T = self._det_records[ri * 2 + 1]
|
||||
if rp == t.CUInt64T(ptr) and (rs & (t.CUInt64T(1) << 63)) == 0:
|
||||
if rs > 0:
|
||||
string.memset(ptr, MEMBUDDY_FILL_PATTERN, rs)
|
||||
self._det_records[ri * 2 + 1] = rs | (t.CUInt64T(1) << 63)
|
||||
break
|
||||
ri += 1
|
||||
if self._is_valid_ptr(p_eff) != 0:
|
||||
@@ -821,13 +826,33 @@ class MemBuddy(MemManager):
|
||||
def _det_probe(self):
|
||||
if self._det_records is None:
|
||||
return
|
||||
free_flag: t.CUInt64T = t.CUInt64T(1) << 63
|
||||
cd_word: t.CUInt64T = (t.CUInt64T(0xCDCDCDCD) << 32) | t.CUInt64T(0xCDCDCDCD)
|
||||
i: t.CSizeT = 0
|
||||
while i < self._det_count:
|
||||
p: t.CUInt64T = self._det_records[i * 2]
|
||||
s: t.CUInt64T = self._det_records[i * 2 + 1]
|
||||
if (s & free_flag) != 0:
|
||||
# free 记录:块头仍为 0(未被重新 alloc)则验证用户区 0xCD
|
||||
# 完整——被写穿 = use-after-free 写入(free 后块被某代码覆盖)
|
||||
real_s: t.CUInt64T = s & (free_flag - 1)
|
||||
if real_s > 0:
|
||||
blk_h: t.CUInt64T = p - 2 - MEMBUDDY_HEADER_SIZE
|
||||
hdr_v: t.CUInt64T = t.CUInt64T(c.Deref(t.CUInt64T(blk_h, t.CPtr)))
|
||||
if (hdr_v & 1) == 0:
|
||||
w0: t.CUInt64T = t.CUInt64T(c.Deref(t.CUInt64T(p, t.CPtr)))
|
||||
w1: t.CUInt64T = w0
|
||||
if real_s >= 8:
|
||||
w1 = t.CUInt64T(c.Deref(t.CUInt64T(p + real_s - 8, t.CPtr)))
|
||||
if w0 != cd_word or w1 != cd_word:
|
||||
stdio.printf("[DET] UAF 写入: ptr=%llu size=%llu(free 后块被写,首=0x%llX 末=0x%llX)\n",
|
||||
p, real_s, w0, w1)
|
||||
stdlib.exit(1)
|
||||
i += 1
|
||||
continue
|
||||
if s == 0:
|
||||
i += 1
|
||||
continue # 该条已被 free(记录移除)
|
||||
continue # 无 size 记录(理论不发生,防御)
|
||||
m16: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(p + s, t.CPtr))
|
||||
mv: t.CUInt16T = m16[0]
|
||||
if mv != t.CUInt16T(MEMBUDDY_DET_MARKER):
|
||||
|
||||
Reference in new issue
Block a user