DF-5630 / verdict.json
{ "finding_id": "DF-5630", "status": "reproduced", "verdict": "Unprivileged-triggerable 4-byte OOB read: note_overflow() (imgact_elf.c:1700-1707) bounds only n_namesz, but bsd_trans_osrel() (imgact_elf.c:1866-1875) reads the 4-byte descriptor at note+24 of any note whose header matches the DragonFly brandnote {10,4,1,DragonFly} bound into the exec path at elf_machdep.c:66-67. A note truncated right after the vendor name (22 bytes) at the end of the first page makes the kernel read image_header[4096..4099] - the adjacent physical page via the DMAP. Proven by value differential with a KLD sysctl harness: control note -> p_osrel=0x44332211 (exact in-file descriptor), bug note -> p_osrel=0x200a2a2f (/*\\n ) which appears nowhere in the crafted file. Silent on this guest (p_osrel has no userspace reader; DMAP read never faults) - Low severity now, a 4-byte kernel-memory oracle the day p_osrel gains exposure. Fix validated: truncated note rejected with ENOEXEC, full notes unaffected.", "reproduced": true, "impact": "none", "confidence": "certain", "exploit_chain": "execve(crafted ELF EI_OSABI=255, uid 1001) -> get_brandinfo loop 1 (BI_BRAND_NOTE) -> check_PT_NOTE accepts {10,4,1}+DragonFly\\0 within 22 proven bytes -> BN_TRANSLATE_OSREL callback bsd_trans_osrel reads *(int32_t*)(note+24) past segment/page end (DMAP neighbor physical page) -> imgp->proc->p_osrel = OOB bytes; observable only via the root-loaded df_osrel.ko sysctl harness (evidence gathering, not part of the attack).", "evidence": "run.log: case2 control p_osrel=0x44332211 vs case3 bug p_osrel=0x200a2a2f (3/3 runs), case1 nonote ENOEXEC; fix validation: bug binary ENOEXEC on patched kernel while control still yields 0x44332211. df_osrel.c KLD harness in pack.", "kernel_refs": [ "sys/kern/imgact_elf.c:1700", "sys/kern/imgact_elf.c:1786", "sys/kern/imgact_elf.c:1792", "sys/kern/imgact_elf.c:1866", "sys/kern/imgact_elf.c:1872", "sys/kern/imgact_elf.c:129", "sys/cpu/x86_64/misc/elf_machdep.c:66", "sys/cpu/x86_64/misc/elf_machdep.c:67", "sys/kern/kern_exec.c:838" ], "poc_changes": "Authored from scratch. Three harness iterations were needed: (1) note offsets must be 4-aligned or check_PT_NOTE breaks at aligned(note, Elf32_Addr); (2) e_entry must lie within [p_vaddr, p_vaddr+p_memsz) or exec_elf64_imgact leaves entry=0 (SIGSEGV at address 0) - used p_memsz=258 to span the stub at 0x400100; (3) CTLTYPE_STRING sysctl harness replaced with RW-int pid + RD-int value pair.", "attempts": 6, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (baseline) / #1 patched build Oct 8 23:30:36 UTC 2026", "runtime_sec": 1500, "guest_dirty": 0, "build_cmd": "cc -o make_note make_note.c && ./make_note bug note_bug.bin && ./make_note control note_ctl.bin && ./make_note nonote note_none.bin && (cd kld && make) && kldload kld/df_osrel.ko", "run_cmd": "sh run_guest.sh # as root: runs the three binaries as maxx, reads p_osrel via sysctl debug.df_osrel_pid/debug.df_osrel_val", "code_hash": "29696012b558fb5f16a77bdca2051fc06f87900f44461648d5a962c27b16e907", "notes": "Heap path variant (PT_NOTE beyond first page, imgact_elf.c:1757) reads past a kmalloc(notesz<=PAGE_SIZE) chunk instead - same root cause. No panic route on this guest: first page is DMAP-backed (cpu/x86_64/misc/lwbuf.c:95) and kmalloc neighbors stay mapped. p_osrel currently write-only in kernel (kern_exec.c:298, imgact_elf.c:867, init_main.c:385) - impact none today, escalation to a leak primitive if p_osrel is ever exposed (procstat/sysctl).", "recommended_fix": "note_overflow(): require the whole declared note (header + rounded name + descriptor) to fit within the remaining segment bytes (see fix.diff).", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Patched kernel (kernel #1 with fix.diff): bug-note binary rejected with ENOEXEC (was: execs + p_osrel=0x200a2a2f from OOB); control note still execs with p_osrel=0x44332211 (no regression for every real DragonFly binarys ABI note); nonote still ENOEXEC.", "fix_evidence": "run.log DF-5630 fix validation section; VERDICT.md; fix.diff in pack." } |