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

hptmv AS_INITIALIZE_START queues the rebuild DPC with flag VERIFY - initialization never starts; ioctl spins 80s and returns success

Summary

Copy-paste bug: the INITIALIZE_START case queues hpt_rebuild_data_block with VERIFY, so rf_initializing is never set and the wait loop polls 1-tick tsleeps until the 80s timeout - then falls through to return 0: the management tool is told the array initialization (the data-hygiene wipe feature) started when nothing happened, with ET_VERIFY_STARTED in the event log. Root-gated sysctl on HighPoint hardware. Queue-INITIALIZE + timeout-returns-failure fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4541 Β· 7 files
FileTypeDescriptionSize
README.md β€” 2.4 KB ↓ raw
VERDICT.md β€” 2.6 KB ↓ raw
hptinit.c β€” 3.0 KB view raw
build.sh β€” 108 B view raw
run.sh β€” 166 B view raw
manifest.json β€” 684 B view raw
verdict.json β€” 2.2 KB view raw

DF-4541 β€” hptmv AS_INITIALIZE_START queues the wrong DPC flag; initialize never runs, ioctl stalls 80 s and reports success

What

hpt_set_array_state() case AS_INITIALIZE_START (sys/dev/raid/hptmv/ioctl.c:572-591) queues the rebuild DPC with the VERIFY flag:

580:  hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);

Compare AS_VERIFY_START (ioctl.c:540) which correctly queues VERIFY, and HPT_IOCTL_CREATE_ARRAY with CAF_CREATE_R5_ZERO_INIT (ioctl.c:392) which correctly queues INITIALIZE. This is a copy-paste bug: hpt_rebuild_data_block(flags==VERIFY) only ever sets rf_verifying (ioctl.c:729-736), never rf_initializing (ioctl.c:720-727).

Consequence

  1. while (!pVDevice->u.array.rf_initializing) (ioctl.c:583-589) can never become true: the calling thread polls with tsleep(..., 1) until timeout >= hz*80 β€” an ~80-second stall of the sysctl-write thread per call.
  2. After the timeout the function falls through and return 0 (ioctl.c:616) β€” the management tool is told the array initialization started when nothing happened. The event queue gets ET_VERIFY_STARTED instead of ET_INITIALIZE_STARTED.
  3. Security-relevant residue: "initialize array" is the data-hygiene feature that is supposed to write the array; a silent no-op defeats the user's wipe expectation when arrays are re-purposed.

The same silent-timeout-returns-success protocol exists in every wait loop of this function (ioctl.c:494-500, 519-525, 543-549, 562-568, 602-608) and in Kernel_DeviceIoControl's ADD_DISK_TO_ARRAY post- processing (ioctl.c:430-436), but only the INITIALIZE case is guaranteed to hit it on every call.

Reachability

The hptmv ioctl channel is the writable sysctl dev.hptmv.status (hptproc.c:614-617). Sysctl writes require root; the array must exist on real HighPoint hardware. Not testable on the audit QEMU guest (no HighPoint HBA β†’ gIal_Adapter NULL, see DF-1853 for that path).

Trigger

hptinit.c <array-id> β€” builds the HPT_IOCTL_PARAM packet for HPT_IOCTL_SET_ARRAY_STATE (0xFF0F) with state = AS_INITIALIZE_START (7) and writes it to dev.hptmv.status.

Expected on vulnerable driver: returns success after ~80 s; dmesg shows hptmv: Verifying started. rather than Initializing started.

Fix

Queue INITIALIZE, and make the wait loops report failure on timeout.

VERDICT.md
↓ download raw

DF-4541 β€” VERDICT

Status: untested (no HighPoint hardware on the audit guest; path is root-only sysctl). The finding is established by code trace, not by execution.

Code trace (why this is certain without hardware)

  • hpt_set_array_state() AS_INITIALIZE_START: sys/dev/raid/hptmv/ioctl.c:572-591.
  • ioctl.c:580 β€” hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); β€” VERIFY, not INITIALIZE.
  • ioctl.c:583-589 β€” waits on rf_initializing, which is only set by hpt_rebuild_data_block case INITIALIZE (ioctl.c:720-727); the VERIFY case sets rf_verifying (ioctl.c:729-736). Wait can never succeed β†’ 80 s of 1-tick tsleep polling (timeout >= hz*80).
  • ioctl.c:616 β€” return 0 after the timeout: success despite no-op.
  • Correct comparators: AS_VERIFY_START queues VERIFY (ioctl.c:540); CREATE_ARRAY CAF_CREATE_R5_ZERO_INIT queues INITIALIZE (ioctl.c:392); AS_INITIALIZE_ABORT waits on rf_initializing (ioctl.c:595) β€” i.e. the rest of the driver agrees INITIALIZE is a distinct operation.

Why not run

  • The only user entry is sysctl dev.hptmv.status write (hptproc.c:614-617, CTLFLAG_RW) β†’ root-only.
  • Requires a HighPoint RocketRAID controller with a functional RAID1/5 array; the QEMU guest has none (gIal_Adapter == NULL; a sysctl write on the guest panics via the already-known DF-1853 NULL-deref before reaching this code).

Impact assessment

Logic/data-hygiene bug + per-call 80 s kernel-thread stall, root-only, hardware-bound: Low. Bucket: base:dev.

--- a/sys/dev/raid/hptmv/ioctl.c
+++ b/sys/dev/raid/hptmv/ioctl.c
@@ -577,7 +577,7 @@ hpt_set_array_state(DEVICEID idArray, DWORD state)
            unlock_driver();

-           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
+           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, INITIALIZE);
            unlock_driver();

            while (!pVDevice->u.array.rf_initializing)

Additionally, the wait loops (ioctl.c:494-500, 519-525, 543-549, 562-568, 583-589, 602-608, 430-436) should return -1 (or otherwise report failure) when they time out instead of falling through to return 0.

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

not_testable - requires HighPoint hardware

VERDICT.md contains the one-line diff; not applied (sys/ read-only; no hardware to validate on)
per-fix-DF-4541

Confirmed kernel references

Detail

Evidence (decisive lines)

findings/poc/DF-4541/VERDICT.md (full path:line trace); hptinit.c (faithful trigger packet: HPT_IOCTL_MAGIC + SET_ARRAY_STATE 0xFF0F + AS_INITIALIZE_START 7)

PoC changes

authored from scratch; HPT_IOCTL_PARAM layout taken from hptintf.h:744-753, ioctl code HPT_CTL_CODE(15)=0xFF0F per hptintf.h:166,197

Verified recommended fix

queue INITIALIZE instead of VERIFY at ioctl.c:580 and make the wait loops return failure on timeout

Verdict

Not executed: the hptmv ioctl channel is the root-only sysctl dev.hptmv.status and requires a HighPoint SATA RAID controller with a valid array; the QEMU audit guest has no such hardware. The defect is established by code trace: AS_INITIALIZE_START queues the rebuild DPC with flag VERIFY (ioctl.c:580) so rf_initializing is never set (only hpt_rebuild_data_block case INITIALIZE sets it, ioctl.c:720-727), the ioctl thread then polls for 80 seconds (ioctl.c:583-589) and returns 0 (success, ioctl.c:616) although the array was never initialized - silent failure of the data-hygiene 'initialize array' operation plus an 80 s kernel-thread stall per call.