DragonFlyBSD Kernel Audit
← dashboard
DF-0056

Heap overflow via unchecked p_filesz > p_memsz in PT_LOAD segment loading

Field Value
ID DF-0056
Status new
Severity Medium
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
CWE CWE-787 Out-of-bounds Write
File sys/kern/link_elf.c
Lines 507-563
Area kern
Confidence certain
Discovered 2026-06-29
Reported pending

Summary

link_elf_load_file never validates p_filesz <= p_memsz for PT_LOAD segments. The kmalloc'd buffer (mapsize) is derived from p_memsz (:541-543), but vn_rdwr (:554) writes p_filesz bytes into it. If p_filesz > p_memsz, the write overflows. Immediately after, bzero(segbase + p_filesz, p_memsz - p_filesz) (:562-563) underflows (both Elf64_Xword/uint64) to a huge value, zeroing far past the allocation. Attacker controls both the overflow size and the data written (file bytes at p_offset). Root-only (SYSCAP_NOKLD); the cleanest heap-overflow primitive in the ELF loaders.

Root cause

sys/kern/link_elf.c:

case PT_LOAD:                     /* :507  no p_filesz <= p_memsz check */
    segs[nsegs] = phdr;
...
mapsize = round_page(segs[1]->p_vaddr + segs[1]->p_memsz) - trunc_page(segs[0]->p_vaddr); /* :543 */
ef->address = kmalloc(mapsize, M_LINKER, M_WAITOK);  /* :546 */
...
vn_rdwr(UIO_READ, vp, segbase, segs[i]->p_filesz, ...); /* :554  writes p_filesz */
bzero(segbase + segs[i]->p_filesz, segs[i]->p_memsz - segs[i]->p_filesz); /* :562 underflow */
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -507,6 +507,11 @@
    case PT_LOAD:
+       if (phdr->p_filesz > phdr->p_memsz) {
+       link_elf_error("p_filesz > p_memsz");
+       error = ENOEXEC;
+       goto out;
+       }
        if (nsegs == 2) {

Timeline

  • 2026-06-29 Discovered during automated file-by-file audit of sys/kern/link_elf.c.
  • pending Reported to DragonFlyBSD security contact.