aac_cam_fix_inquiry dereferences csio->data_ptr on successful INQUIRY completions without checking a data buffer exists (NULL-deref panic via no-data pass-through INQUIRY)
Summary
fix_inquiry reads and writes data_ptr[0] on every CAM_REQ_CMP INQUIRY with no dxfer_len/data_ptr check - a CAM_DIR_NONE passthrough INQUIRY that the adapter completes successfully NULL-derefs. Same trigger surface as DF-1822 (root /dev/passN); hw-gated. Guard fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4718 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.6 KB | β raw | |
| fix.diff | β | 382 B | view raw | |
| verdict.json | β | 1.5 KB | view raw | |
| manifest.json | β | 491 B | view raw |
DF-4718 β aac_cam_complete/aac_cam_fix_inquiry: INQUIRY completion dereferences csio->data_ptr without any data buffer
Root cause (code trace; hw-gated β no AAC adapter in the QEMU guest)
aac_cam_complete() calls aac_cam_fix_inquiry() for every XPT_SCSI_IO
(sys/dev/raid/aac/aac_cam.c:626). aac_cam_fix_inquiry() matches on
data[0] == INQUIRY (the CDB copy) and, when the adapter reports success,
unconditionally dereferences the customer's data buffer
(:551-573):
inq = (struct scsi_inquiry_data *)ccb->csio.data_ptr;
device = SID_TYPE(inq); /* reads data_ptr[0] */
qual = SID_QUAL(inq);
...
ccb->csio.data_ptr[0] = (qual << 5) | T_NODEVICE; /* writes data_ptr[0] */
Nothing checks dxfer_len/data_ptr. A pass-through INQUIRY issued with
CAM_DIR_NONE (dxfer_len == 0, data_ptr == NULL) β perfectly legal via
/dev/passN (camcontrol passthrough with a CDB and no data) β returns
SRB_STATUS_SUCCESS from the controller, making the fix-up read NULL and
panic the kernel* (Fatal trap 12, fault VA 0). Kernel-internal periph
INQUIRYs always attach buffers, so the trigger is a user-issued (root, pass
device is 0600) or otherwise synthetic no-data INQUIRY; still a
one-ioctl DoS on AAC systems and the same class DF-1822 filed for
CAM_SCATTER_VALID.
Also note sense[] in struct aac_srb_response is 30 bytes
(AAC_HOST_SENSE_DATA_MAX) while the copy length is bounded only by
ccb->csio.sense_len β the 2-byte overread inside the FIB is part of
DF-1823's known unbounded-sense finding.
Fix
fix.diff guards the dereference on data_ptr != NULL && dxfer_len >= 1.
Fix verification
not_testableConfirmed kernel references
Detail
Exploit chain
root (pass device 0600): camcontrol passthrough INQUIRY with no data buffer on an AAC bus -> adapter returns SUCCESS -> fix_inquiry reads *(NULL) -> kernel panic
Evidence (decisive lines)
code trace: aac_cam.c:543-549 (CDB match), :551-573 (unguarded data_ptr read+write), :626 (called for every XPT_SCSI_IO completion)
PoC changes
n/a (no seeded PoC)
Verified recommended fix
guard: status==CAM_REQ_CMP && data_ptr != NULL && dxfer_len >= 1 before touching the inquiry data (fix.diff)
Verdict
aac_cam_fix_inquiry (aac_cam.c:551-573) dereferences ccb->csio.data_ptr for successful INQUIRY completions without checking that the CCB carried a data buffer; a pass-through INQUIRY with CAM_DIR_NONE (data_ptr NULL) that the adapter completes successfully NULL-derefs in kernel mode -> panic (local DoS, same trigger class as DF-1822). Runtime verification impossible on this guest (no AAC emulation in QEMU); trace is unambiguous. fix.diff adds the buffer guard.
No comments yet.