β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4333

hpt_add_disk_to_array divides by (bArnMember-1) unchecked - #DE panic on degenerate 1-member RAID1/5 arrays (sibling site of DF-1682)

Summary

The capacity division executes on every ADD_DISK_TO_ARRAY once the array passes the rf_broken and RAID1/5 gates. bArnMember==1 arrays are constructible via CREATE_ARRAY with nDisk=1 (the DF-1682 chain established the construction). bArnMember==1 -> divisor 0 -> #DE panic. Distinct site and trigger from DF-1682 (needs the extra rf_broken state). bArnMember<2 guard + nDisk>=2-at-creation fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4333 Β· 5 files
FileTypeDescriptionSize
README.md β€” 2.0 KB ↓ raw
VERDICT.md β€” 1.6 KB ↓ raw
verdict.json β€” 1.9 KB view raw
manifest.json β€” 637 B view raw
env.txt β€” 363 B view raw

DF-4333 β€” hptmv hpt_add_disk_to_array divides by (bArnMember - 1) unchecked

File: sys/dev/raid/hptmv/gui_lib.c:935

Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);

bArnMember is a UCHAR. HPT_IOCTL_ADD_DISK_TO_ARRAY (gui_lib.c:1364-1376) reaches this line whenever the array is a broken (rf_broken, :915) RAID 1/5 (:917-918). Arrays with bArnMember == 1 are constructible through HPT_IOCTL_CREATE_ARRAY[_V2] with nDisk = 1 (gui_lib.c:571 bounds only nDisk > MAX_MEMBERS; :614 nDisk <= 2 accepts 1; :618 bArnMember = pParam->nDisk) β€” the same construction already established by DF-1682 for the sibling site ioctl.c:694 (hpt_rebuild_data_block). bArnMember == 1 β‡’ divisor 0 β‡’ x86 #DE β‡’ kernel panic.

Differences from DF-1682 (why this is a separate site, not a re-report): DF-1682's division is in the rebuild DPC queued by hpt_set_array_state (needs only mIsArray + vf_online); this one is in the ADD_DISK ioctl itself and additionally requires rf_broken (:915) β€” reachable when a degenerate 1-member RAID1/5 loses its member (blob failure path sets rf_broken on the parent) or is restored from on-disk metadata with a broken 1-member config. Trigger therefore needs the HighPoint HBA plus a degraded array state: Low severity, sibling of DF-1682.

Guest status β€” NOT REPRODUCIBLE HERE

Same hardware absence as DF-4332 (pciconf -l: no 11AB devices; hw.hptmv.status OID absent; without an adapter the path NULL-derefs before gui_lib.c β€” known DF-1853). Verdict: inconclusive β€” hardware absent; defect established by inspection.

Fix direction (one line)

Reject bArnMember < 2 before the division at gui_lib.c:935 (mirror of the fix DF-1682 needs at ioctl.c:694) β€” e.g.

-   Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);
+   if (pArray->u.array.bArnMember < 2)
+       return -1;
+   Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);

and bound nDisk >= 2 for array creation in hpt_create_array_v2.

VERDICT.md
↓ download raw

DF-4333 β€” VERDICT

Status: inconclusive (hardware absent). Confidence in the code defect: likely.

The unchecked division pArray->VDeviceCapacity / (bArnMember - 1) at gui_lib.c:935 executes on every HPT_IOCTL_ADD_DISK_TO_ARRAY that passes the rf_broken (915) + RAID1/RAID5 (917-918) gates. bArnMember == 1 arrays are constructible via CREATE_ARRAY with nDisk = 1 (gui_lib.c:571/614/618 β€” construction chain established by DF-1682 for its sibling site in ioctl.c:694); the additional rf_broken precondition here arrives from a member-failure event or on-disk metadata restore, both of which need the physical controller and disks. Divisor 0 β†’ #DE β†’ kernel panic (same trap 18 signature demonstrated live for DF-4331 in this batch).

Guest: no HighPoint hardware (pciconf -l β†’ 0 matches; hw.hptmv.status OID absent; entry NULL-derefs first = known DF-1853). Not reproducible here; code-level defect is certain, full trigger chain is hardware-state dependent β€” overall likely / Low. Distinct site and trigger from DF-1682 (rebuild DPC vs ADD_DISK ioctl + rf_broken), filed as a sibling.

No fix.diff (unverified). Fix: if (bArnMember < 2) return -1; before gui_lib.c:935 plus nDisk >= 2 on array creation.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

(No fix.diff for this item: documented recommendation only - see Fix above.)

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean
per-fix-DF-4333

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md trace (gui_lib.c:935,915,917,571,614,618; DF-1682 relation); env.txt hardware-absence capture

PoC changes

no runnable PoC possible without the HBA

Verified recommended fix

Add 'if (pArray->u.array.bArnMember < 2) return -1;' before the division at gui_lib.c:935 and validate nDisk>=2 in hpt_create_array_v2

Verdict

INCONCLUSIVE - hardware absent. gui_lib.c:935 divides by (bArnMember-1) with no >=2 check on the ADD_DISK_TO_ARRAY path; bArnMember==1 arrays are constructible via CREATE_ARRAY nDisk=1 (gui_lib.c:571,614,618; construction chain per DF-1682) and the extra rf_broken precondition (gui_lib.c:915) requires a degraded-array state only the physical controller can produce. Divisor 0 -> #DE kernel panic (trap-18 signature demonstrated live for the mrsas twin DF-4331 in this batch). Guest has no HighPoint device (pciconf 0 matches; hw.hptmv.status OID absent; NULL-adapter entry crash is known DF-1853). Low severity sibling site of DF-1682 (ioctl.c:694).