⬢ DragonFlyBSD Kernel Audit
DF-5730 / drive2.py
← back to finding ↓ download raw
#!/usr/bin/env python3
"""DF-5730 boot 2 — corrected $maxoff demo (offset attribution direction)
plus a network-independent post-continue liveness marker.

$maxoff semantics (db_sym.c:289 `if (name == NULL || d >= (unsigned
long)db_maxoff)` and db_print.c:56): it is the THRESHOLD at which a
looked-up symbol stops being printed as name+offset and falls back to a
raw address.  `set $maxoff=-1` casts to ULONG_MAX, so ANY offset is
"close enough" -> distant raw addresses get misattributed to the nearest
symbol with a huge offset.
"""
import os, socket, sys, threading, time

SOCK  = os.environ.get("SOCK", "/tmp/opencode/df-5730-ser.sock")
DRAIN = os.environ.get("DRAIN", "/tmp/opencode/df-5730-drain2.log")

def connect():
    while True:
        try:
            s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            s.connect(SOCK)
            return s
        except (FileNotFoundError, ConnectionRefusedError) as e:
            print(f"connect failed: {e}; retrying...", flush=True)
            time.sleep(2)

def send_raw(s, data, chunk=8, pace=0.15):
    for i in range(0, len(data), chunk):
        s.sendall(data[i:i+chunk])
        time.sleep(pace)

def send_line(s, line, wait=4):
    print(f"\n>>> {line!r}", flush=True)
    send_raw(s, line.encode() + b"\n")
    time.sleep(wait)

def main():
    s = connect()
    def drainer(sock):
        with open(DRAIN, "ab", buffering=0) as d:
            while True:
                try:
                    b = sock.recv(65536)
                except OSError:
                    return
                if not b:
                    return
                d.write(b)
                sys.stdout.write(b.decode("latin1")); sys.stdout.flush()
    threading.Thread(target=drainer, args=(s,), daemon=True).start()
    time.sleep(2)

    # offset 0x2000000 (32 MiB) >> default maxoff 0x100000 -> RAW address
    send_line(s, "print/a db_active+0x2000000")
    # accepted with no validation; casts to ULONG_MAX
    send_line(s, "set $maxoff=-1")
    # same address now MISATTRIBUTED as symbol+huge-offset
    send_line(s, "print/a db_active+0x2000000")
    # restore and prove it flips back
    send_line(s, "set $maxoff=0x100000")
    send_line(s, "print/a db_active+0x2000000")
    # healthy continue
    send_line(s, "x/x db_active")
    send_line(s, "c")

    print("\n>>> session script complete; waiting for POSTCONT marker...", flush=True)

if __name__ == "__main__":
    main()