DragonFlyBSD Kernel Audit
← dashboard
DF-0109

l32_fixlabel partition loop lacks internal d_npartitions cap

Field Value
ID DF-0109
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:N
CWE CWE-129 Improper Validation of Array Index
File sys/kern/subr_disklabel32.c
Lines 592-614
Area kern
Confidence low
Discovered 2026-06-30
Reported pending

Summary

l32_fixlabel iterates lp->d_npartitions times over the fixed-size d_partitions[] array (:592) with no internal cap. Currently gated by the dkcksum32 OOB bug (DF-0106/DF-0107), but as defense-in-depth the function should not trust its caller.

Root cause

l32_fixlabel at :592:

for (part = 0; part < lp->d_npartitions; part++, pp++) {
    if (pp->p_offset != 0 || pp->p_size != 0) {
        ...
        bzero(pp, sizeof *pp);   // line 609
        pp->p_offset += offset;  // line 611
    }
}

pp starts at &d_partitions[RAW_PART] (:590) and increments. If d_npartitions > MAXPARTITIONS32, pp walks past the array, and bzero(pp, sizeof *pp) corrupts memory past the struct.

Currently this is only reachable if dkcksum32 returned 0 on a label with d_npartitions > MAXPARTITIONS32 — which requires the OOB bytes to XOR to 0 against an attacker-chosen checksum. In the writedisklabel path, *dlp = *lp at :365 replaces the on-disk label with the new label before fixlabel runs, so d_npartitions is the new label's value (typically 16). The risk is theoretical.

Threat model & preconditions

  • Attacker position: N/A — defense-in-depth.
  • Impact: Would allow OOB write if dkcksum32 gate were bypassed.
  • Required config: N/A.
--- a/sys/kern/subr_disklabel32.c
+++ b/sys/kern/subr_disklabel32.c
@@ -589,7 +589,8 @@
    if (lp->d_secpercyl <= 0)
        return ("fixlabel: d_secpercyl <= 0");
    pp -= RAW_PART;
-   warned = FALSE;
+   if (lp->d_npartitions > MAXPARTITIONS32)
+       lp->d_npartitions = MAXPARTITIONS32;
+   warned = FALSE;
    for (part = 0; part < lp->d_npartitions; part++, pp++) {

Timeline

  • 2026-06-30 Discovered during automated audit.