Remote kernel heap overflow in scsi_decap via attacker-controlled Data-In buffer offset (write-what-where)
| Field | Value |
|---|---|
| ID | DF-1869 |
| Status | new |
| Severity | Critical |
| CVSS 3.1 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-787 Out-of-bounds Write |
| File | sys/dev/disk/iscsi/initiator/iscsi_subr.c |
| Lines | 566-574 |
| Area | dev/disk (iSCSI initiator Data-In) |
| Confidence | certain |
| Discovered | 2026-07-20 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
When a malicious iSCSI target returns a SCSI Data-In PDU (opcode 0x25),
scsi_decap() computes the kernel write destination as csio->data_ptr +
ntohl(rcmd->bo) using the attacker-controlled DataOffset field bo, and copies
pq->pdu.ds_len attacker-supplied bytes into it via i_mbufcopy(). The only
bounds check present is ntohl(cmd->edtlen) >= pq->pdu.ds_len, which validates
the segment length alone β it never checks offset + len against the CCB buffer
size edtlen. A target can therefore write attacker bytes at an attacker-chosen
kernel heap offset, yielding a deterministic write-what-where primitive.
Root cause
In scsi_decap() at iscsi_subr.c:556-590, the ISCSI_READ_DATA branch:
if(ntohl(cmd->edtlen) >= pq->pdu.ds_len) { /* line 566 */
int offset, len = pq->pdu.ds_len;
if(pq->mp != NULL) {
caddr_t dp;
offset = ntohl(rcmd->bo); /* line 573: attacker-controlled */
dp = csio->data_ptr + offset; /* NO bounds check */
i_mbufcopy(pq->mp, dp, len); /* writes len attacker bytes */
}
}
rcmd->bo is the Data-In 'Data Offset' field (u_int, iscsi.h:256), fully
controlled by the iSCSI target on the wire. csio->data_ptr is a kernel heap
buffer of size csio->dxfer_len bytes, and cmd->edtlen equals exactly that
buffer size. The check edtlen >= ds_len at line 566 only constrains the per-PDU
segment length, never the (offset, offset+len) window against edtlen. The
offset local is a signed int, so a bo with the high bit set sign-extends to a
negative ptrdiff_t and the write goes BELOW csio->data_ptr; a large positive
bo overruns above it. i_mbufcopy() then writes exactly len = ds_len
attacker bytes from the mbuf chain.
Threat model & preconditions
- Attacker position: the iSCSI target (server); the kernel running this code is the initiator (client). On any DragonFlyBSD host where the operator has established a session to an attacker-controlled or compromised iSCSI target.
- Privileges gained or impact: remote kernel code execution β full host compromise with ring-0 privileges. The attacker chooses the offset and supplies the bytes β a write-what-where primitive. With slab grooming this corrupts arbitrary kernel objects (ufs_inode, cred, pipe buffers, vop_vector etc.).
- Required config or capabilities:
device iscsi_initiator; iSCSI session to the attacker's target. - Reachability: after login, when the initiator issues any SCSI read (e.g.
dd if=/dev/da0 of=/dev/null bs=512 count=1), the target sends a Data-In PDU echoing the itt of the outstanding SCSI read withboset to the overflow offset. The check at line 566 passes (segment length β€ expected length), then attacker bytes are written at the attacker-chosen offset.
Proof of concept
The malicious iSCSI target performs a normal Login (text negotiation, FFP), waits for the first SCSI_CMD, extracts the itt, and replies with one crafted Data-In:
opcode=0x25 (ISCSI_READ_DATA), flag.F=1, flag.S=1, flag.A=0, status=0x00 LUN echoed, itt=<observed itt>, ttt=0xFFFFFFFF statSN/ExpCmdSN/MaxCmdSN populated to advance the window dataSN=0, bo=<chosen overflow offset, e.g. 0x1000>, DSLength=<N <= edtlen> data segment = N attacker bytes (slab-grooming pattern / vop_vector overwrite)
Build & run
# On the attacker (Python 3 evil iSCSI target): python3 evil_target.py # On the victim: iscontrol -d 0 -t 0 -h <attacker_ip> dd if=/dev/da0 of=/dev/null bs=512 count=1
Expected output
kernel panic: corrupted next-pointer / method table on first deref OR with heap grooming: RIP control -> kernel code execution -> root stack trace through i_mbufcopy -> scsi_decap -> ism_recv
Impact
Critical: remote kernel code execution from the iSCSI target side. The target needs no credentials β it just needs to be the target that the initiator is talking to. A compromised target, a spoofed SendTargets/iSNS discovery result, or a MITM can all deliver this. With slab grooming the write-what-where primitive achieves ring-0 code execution and full host compromise.
Recommended fix
Validate offset + len against the CCB buffer before copying.
--- a/sys/dev/disk/iscsi/initiator/iscsi_subr.c
+++ b/sys/dev/disk/iscsi/initiator/iscsi_subr.c
@@ -563,13 +563,22 @@ scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
if(cmd->R) {
if(ntohl(cmd->edtlen) >= pq->pdu.ds_len) {
- int offset, len = pq->pdu.ds_len;
+ u_int offset, len = pq->pdu.ds_len;
+ u_int edtlen = ntohl(cmd->edtlen);
if(pq->mp != NULL) {
caddr_t dp;
offset = ntohl(rcmd->bo);
+ /*
+ | rcmd->bo is attacker-controlled.
+ | Reject any PDU whose [offset, offset+len)
+ | window is not fully within the CCB buffer.
+ */
+ if (offset > edtlen || len > edtlen - offset) {
+ xdebug("bad data-in: bo=%u len=%u edtlen=%u",
+ offset, len, edtlen);
+ break;
+ }
dp = csio->data_ptr + offset;
i_mbufcopy(pq->mp, dp, len);
}
References
- Sibling OOB read in
iscsi_r2t: DF-1870 (this file). - Sibling CDB overflow in
scsi_encap: DF-1871 (this file). - Prior iSCSI findings: DF-1703/1704 (iscsi.c), DF-1759β1761 (isc_sm.c), DF-1827β1830 (isc_soc.c).
Timeline
- 2026-07-20 Discovered during automated audit.
- 2026-07-20 Reported to DragonFlyBSD security contact (pending).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1869 Β· 14 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | trigger-source | faithful userspace port of scsi_decap ISCSI_READ_DATA; proves write-what-where primitive; runs both unfixed and fixed modes from same source | 6.7 KB | view raw |
| build.sh | build-script | cc -O2 -Wall build of harness + harness_fixed | 312 B | view raw |
| run.sh | run-script | runs both binaries; PASS iff unfixed shows OOB and fixed shows 0 | 638 B | view raw |
| fix.diff | suggested-fix | git-apply-able one-hunk fix: widen offset/len/edtlen to u_int, add offset+len<=edtlen bounds check before dp=data_ptr+offset | 850 B | view raw |
| VERDICT.md | verdict | full narrative: source trace, primitive characterization, PHASE 6 escalation analysis (hard blocker = root-only module load), PHASE 8 fix validation | 12.7 KB | β raw |
| README.md | readme | human-facing build/run + caveat on local unprivileged reachability | 2.8 KB | β raw |
| build.log | build-log | full guest cc 8.3 build of the harness | 343 B | view raw |
| run.log | run-log | decisive UNFIXED run: 416 OOB bytes, exit 1 | 671 B | view raw |
| run.2.log | run-log | FIXED run: 0 OOB bytes, exit 0 | 621 B | view raw |
| run.3.log | run-log | UNFIXED rerun for determinism (identical to run.log) | 677 B | view raw |
| fix_build.log | build-log | full guest build of iscsi_initiator.ko with fix.diff applied; rc=0, no warnings | 17.4 KB | view raw |
| env.txt | environment | uname, cc, INVARIANTS=ON, KASLR=OFF, iscsi module status, maxx perms | 1.3 KB | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-1869 β PoC evidence pack
Remote kernel heap overflow in scsi_decap() via attacker-controlled
Data-In buffer offset. Path:
sys/dev/disk/iscsi/initiator/iscsi_subr.c:566-574.
What is in this folder
| File | Purpose |
|---|---|
harness.c |
Faithful userspace port of scsi_decap ISCSI_READ_DATA; runs both unfixed and fixed |
build.sh |
Builds harness (unfixed kernel logic) and harness_fixed (with offset+len<=edtlen guard) |
run.sh |
Runs both binaries; PASS iff unfixed shows OOB and fixed shows 0 OOB |
fix.diff |
git apply-able one-hunk fix for sys/dev/disk/iscsi/initiator/iscsi_subr.c |
VERDICT.md |
Full narrative: source trace, primitive characterization, PHASE 6 escalation analysis, PHASE 8 fix validation |
build.log |
Full guest build of the harness (cc 8.3, DragonFly) |
run.log |
UNFIXED run: 416 bytes written OOB, exit 1 |
run.2.log |
FIXED run: 0 bytes written OOB, exit 0 |
run.3.log |
UNFIXED rerun for determinism |
fix_build.log |
Full guest build of iscsi_initiator.ko with fix applied |
env.txt |
Guest environment (uname, cc, INVARIANTS, module status, maxx perms) |
manifest.json |
Machine-readable catalog for the static-site generator |
Build & run (on the audit guest as the unprivileged user)
sh build.sh sh run.sh
Expected:
UNFIXED total_oob_bytes=416 exit=1 FIXED total_oob_bytes=0 exit=0 RESULT: unfixed_rc=1 fixed_rc=0 PASS β primitive reproduced unfixed; fix closes it.
Reproducing the fix at the module level (root only)
ssh dfbsd cd /usr/src patch -p1 < /path/to/this/dir/fix.diff cd sys/dev/disk/iscsi/initiator make KERNCONF=X86_64_GENERIC # rc=0, iscsi_initiator.ko built strings iscsi_subr.o | grep 'bad data-in' # Expect: >>> %s: bad data-in bo=%u len=%u edtlen=%u (absent in the unfixed build)
Caveat β local unprivileged reachability
The vulnerable code lives in the iscsi_initiator loadable module
(NOT in X86_64_GENERIC). An unprivileged user cannot kldload it
(Operation not permitted) and cannot establish an iSCSI session
(iscontrol requires the module). The bug is therefore a remote bug:
the realistic threat is a malicious iSCSI target taking over the
initiator kernel after an admin has connected to it. The userspace
harness proves the write-what-where primitive deterministically without
requiring the module loaded. See VERDICT.md Β§3 for the full escalation
analysis and the documented hard blocker.
DF-1869 β VERDICT
| Field | Value |
|---|---|
| Verdict | REPRODUCED (primitive confirmed; remote-only reachability) |
| Status | reproduced |
| Impact | corruption (write-what-where; remote RCE ceiling in threat model) |
| Confidence | certain |
| Class | CWE-787 Out-of-bounds Write |
| Kernel | DragonFly 6.5-DEVELOPMENT #0 (master DEV, X86_64_GENERIC, INVARIANTS ON) |
1. The bug (line-by-line source confirmation)
In sys/dev/disk/iscsi/initiator/iscsi_subr.c, scsi_decap(), the
ISCSI_READ_DATA branch handles a SCSI Data-In PDU coming back from the
iSCSI target. The relevant lines:
566: if(ntohl(cmd->edtlen) >= pq->pdu.ds_len) { // ONLY check: segment length
567: int offset, len = pq->pdu.ds_len; // signed int offset
...
572: offset = ntohl(rcmd->bo); // bo = attacker-controlled (u_int, iscsi.h:256)
573: dp = csio->data_ptr + offset; // NO bounds check vs edtlen
574: i_mbufcopy(pq->mp, dp, len); // writes len attacker bytes at offset
cmd->edtlenis set atiscsi_subr.c:516tohtonl(csio->dxfer_len)β the size of the initiator's kernel-side CCB data buffer (csio->data_ptr).rcmd->bois the iSCSI Data-In PDU's "Data Offset" field (data_in_t.bo,u_int,iscsi.h:256), fully controlled by the target on the wire.- The only guard is
edtlen >= ds_len(segment length fits) β there is nooffset + ds_len <= edtlencheck. offsetis declaredint(iscsi_subr.c:567); assigningu_int bowhose high bit is set sign-extends to a negative ptrdiff_t, sodp = csio->data_ptr + offsetwrites below the buffer. Large positivebowrites above it.i_mbufcopy()(iscsivar.h:565) then copieslen = ds_lenattacker bytes from the PDU's mbuf chain intodpβ a deterministic write-what-where with both offset and content controlled by the remote target.
2. Reproduction β userspace harness (faithful port)
Because iscsi_initiator is a loadable module (NOT in X86_64_GENERIC) and
the trigger requires an established iSCSI session (which an unprivileged user
cannot create β see Β§4), the primitive is reproduced with a faithful userspace
port of the exact kernel arithmetic in harness.c. It:
- Allocates an
edtlen-sized buffer (csio->data_ptranalogue) flanked by 4096-byte REDZONE (0xA5) canaries on each side. - Replays the kernel
if (edtlen >= ds_len)check, theoffset = ntohl(bo)assignment, thedp = buf + offsetarithmetic, andi_mbufcopy. - Counts every redzone byte that is no longer 0xA5 after the copy (= an attacker byte written outside the legitimate CCB buffer).
Build & run
sh build.sh # cc -O2 -Wall -o harness harness.c (+ harness_fixed) sh run.sh # runs both, compares
Result (decisive)
UNFIXED (verbatim kernel logic):
[in_bounds_bo=0_ds=512] -> in-bounds (no OOB) # legal case still works [OOB_pos_bo=0x200_ds=0x100] -> OOB WRITE oob_bytes=256 # positive overrun [OOB_pos_bo=0x300_ds=0x80] -> OOB WRITE oob_bytes=128 # large positive overrun [OOB_neg_bo=0xFFFFFC00_ds=16] -> OOB WRITE oob_bytes=16 # NEGATIVE offset (sign-ext) [OOB_pos_bo=0x200_ds=16_pattern] -> OOB WRITE oob_bytes=16 # crafted bytes (slab-groom) SUMMARY mode=UNFIXED total_oob_bytes=416 exit=1
FIXED (offset+len <= edtlen guard):
[in_bounds_bo=0_ds=512] -> in-bounds (no OOB) # legal case unaffected [OOB_pos_bo=0x200_ds=0x100] -> REJECTED by fix [OOB_pos_bo=0x300_ds=0x80] -> REJECTED by fix [OOB_neg_bo=0xFFFFFC00_ds=16] -> REJECTED by fix # negative offset also rejected [OOB_pos_bo=0x200_ds=16_pattern] -> REJECTED by fix SUMMARY mode=FIXED total_oob_bytes=0 exit=0
All 4 attacker offset/byte combinations write 416 bytes outside the CCB buffer when unfixed; the proposed fix rejects all four while leaving the legal in-bounds case untouched. Reproduced 3Γ β fully deterministic.
3. PHASE 6 β escalation analysis (the honest answer)
This is a memory-corruption primitive (write-what-where), so the audit's primary question is: can unprivileged maxx turn this into uid=0?
Primitive characterization
- Write capability: arbitrary
lenbytes (len =ds_len, β€ edtlen), attacker-controlled content (PDU data segment), at attacker-controlled offset (bo), into a kernel heap allocation of sizeedtlenwhose start address iscsio->data_ptr. - Allocation:
csio->data_ptris a CAM-periph kmalloc of sizecsio->dxfer_len(e.g.scsi_da.cusesM_SCSIDA/M_DEVBUF). A 512-byte SCSI read β kmalloc-512 bucket; a 4 KB read β page zone, etc. - Negative-offset variant: because
offsetisintandboisu_int, abowith the high bit set yields a negativedp, writing belowcsio->data_ptrβ into whatever earlier slab object or slab metadata precedes it. - Slab victim candidates in kmalloc-512 (same bucket, controllable
fields):
struct file(function-pointerf_ops),struct ucred-adjacent objects,struct pipe,struct socket/so_optionsvectors, various periph softc blobs. On this guest (no SMAP / no SMEP / no KASLR, INVARIANTS ON), an ideal chain would: 1. Groom kmalloc-512 so astruct filelands immediately after a predictable CCB allocation. 2. Issue a SCSI read whose Data-In PDU returnsbo = +0x200,ds_len = 64, bytes crafted to overwritefile->f_opswith the address of a forgedfileopsin userspace (no SMAP β kernel reads user pages). 3. Trigger aread()on the victim fd; the forgedfo_readjumps to userspace shellcode (no SMEP β user page executable from ring 0) which callscommit_creds(prepare_kernel_cred(NULL))and returns. 4. Back in userspace,setresuid(0,0,0)β uid=0.
Why uid=0 is NOT delivered here β a VALID hard blocker
The chain above cannot be exercised by the unprivileged user maxx on the
default GENERIC guest, for a concrete reason:
iscsi_initiatoris not inX86_64_GENERIC; it is a loadable module (/boot/kernel/iscsi_initiator.ko) and loading it requires root.
Verified on the guest (see env.txt):
maxx$ kldload iscsi_initiator kldload: can't load iscsi_initiator: Operation not permitted maxx$ iscontrol # the userland initiator helper (tries to kldload) iscsi_initiator: Error while handling kernel module: Operation not permitted
Without the module loaded there is no /dev/iscsi* device, no active session,
and the buggy scsi_decap() function is not even resident in kernel memory.
This matches the agent's "valid hard blocker" rule:
The write is reachable only from an already-root context (kldload / wheel-only ioctl / devfs root:operator node with no group membership), so there is no privilege boundary to cross.
A kldload from a setuid-root helper or a custom-built module would be
circular and is explicitly disallowed by the bright-line rule.
What this finding IS (the realistic threat model)
A remote kernel-corruption bug:
- Attacker position: the iSCSI target (server). The victim kernel runs the initiator code.
- Precondition (realistic, NOT circular): an admin has established an iSCSI session to an attacker-controlled or compromised target. This is the normal operating mode of any DragonFlyBSD host using iSCSI storage.
- Impact under that precondition: the malicious target sends one crafted Data-In PDU per SCSI read; the write-what-where lands; on this guest the chain above achieves ring-0 code execution (the target, not the local user, becomes root inside the initiator kernel).
- On GENERIC with INVARIANTS ON, slab-grooming for cross-bucket reuse would
typically panic (chunk poisoning / magic checks in
kern_slaballoc.c) before escalation lands, so the realistic default-kernel ceiling is panic/corruption β but a same-bucket overwrite (e.g. adjacent CCB β adjacentstruct filein kmalloc-512, no free in between) fires before any INVARIANTS check, so a surgical remote RCE on GENERIC is not excluded.
Honest summary
- The primitive is real and Critical-class (write-what-where with both offset and bytes attacker-controlled).
- Local unprivileged β uid=0 on default GENERIC: NOT achievable β
the code path is gated on a root-only
kldload. - Remote target β ring-0 when an admin has an iSCSI session: achievable in principle; the harness proves the offset/byte control, and the slab-groom/forge chain is standard for a no-SMEP/no-SMAP/no-KASLR target. Full end-to-end demonstration would require setting up an evil iSCSI target on the guest, loading the module as root, establishing a session, and issuing a SCSI read β beyond what an unprivileged user can drive.
Reported impact: corruption (the demonstrated primitive), with the remote-RCE ceiling documented. This is a Critical remote bug; it is NOT a local unprivileged β root bug on default GENERIC.
4. PHASE 8 β fix validation
fix.diff
A one-hunk, minimal, git apply-able unified diff against
sys/dev/disk/iscsi/initiator/iscsi_subr.c. The change:
- Widens the locals
offset/len/edtlentou_int(eliminates the signed-offset underflow class entirely). - Adds a single bounds check before the pointer arithmetic:
c
if (offset > edtlen || len > edtlen - offset) {
xdebug("bad data-in bo=%u len=%u edtlen=%u", offset, len, edtlen);
break;
}
break exits the ISCSI_READ_DATA case without copying, matching the
function's existing error-handling style.
This supersedes the finding markdown's proposal (which used the same
arithmetic but added a comment-only change); the verdict's fix.diff is
functionally identical in intent and additionally tightens the local types
to u_int.
Validation results
| Check | Result |
|---|---|
git apply --check -p1 fix.diff (host, on sys/) |
OK applies cleanly |
patch -p1 < fix.diff in guest /usr/src |
Hunk #1 succeeded at 564 |
Build iscsi_initiator.ko with fix applied |
rc=0, no warnings, no errors (see fix_build.log) |
Fixed iscsi_subr.o contains the new xdebug string |
YES: >>> %s: bad data-in bo=%u len=%u edtlen=%u |
Unfixed iscsi_subr.o (after patch -R) contains it |
NO (clean differential) |
| Harness UNFIXED run | 416 bytes written OOB (exit 1) |
| Harness FIXED run | 0 bytes written OOB (exit 0); legal case unaffected |
Because the bug is in pointer arithmetic (a deterministic computation, not a stateful race or memory-layout flake), the harness's unfixed-vs-fixed comparison is a fully deterministic proof of the fix. The end-to-end module-level proof (load fixed module, run evil target, observe no OOB) is gated on the same root-only module-load blocker that gates escalation (Β§3), so the harness + object-file string differential is the cleanest deterministic validation available on this guest.
Before / after contrast
baseline (unfixed kernel logic): [OOB_pos_bo=0x200_ds=0x100] -> OOB WRITE oob_bytes=256 [OOB_neg_bo=0xFFFFFC00_ds=16] -> OOB WRITE oob_bytes=16 SUMMARY mode=UNFIXED total_oob_bytes=416 exit=1 patched (offset+len <= edtlen guard): [OOB_pos_bo=0x200_ds=0x100] -> REJECTED by fix [OOB_neg_bo=0xFFFFFC00_ds=16] -> REJECTED by fix SUMMARY mode=FIXED total_oob_bytes=0 exit=0
The fix closes the bug.
5. PoC changes vs. the finding markdown
The finding markdown's "Proof of concept" section described an evil Python
iSCSI target plus an iscontrol-driven SCSI read on the victim β a correct
real-world reproduction recipe, but infeasible to drive from the
unprivileged user on this guest (module + session require root). The
runner substituted a faithful userspace port of the exact kernel
arithmetic (harness.c) that:
- proves the primitive deterministically (no setup privileged needed),
- runs identically in UNFIXED and FIXED modes from the same source,
- makes the before/after comparison crisp and self-contained.
The harness source, build/run scripts, fix.diff, and full untrimmed logs are all in this directory.
Fix verification
fixedVALIDATED. baseline 416 bytes OOB; fixed 0 bytes. Module rc=0.
UNFIXED: 4 OOB writes total 416 bytes. FIXED: 0 OOB. Module builds rc=0 with 'bad data-in' xdebug string.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- i
- s
- c
- s
- i
- /
- i
- n
- i
- t
- i
- a
- t
- o
- r
- /
- i
- s
- c
- s
- i
- _
- s
- u
- b
- r
- .
- c
- :
- 5
- 1
- 6
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- i
- s
- c
- s
- i
- /
- i
- n
- i
- t
- i
- a
- t
- o
- r
- /
- i
- s
- c
- s
- i
- _
- s
- u
- b
- r
- .
- c
- :
- 5
- 6
- 6
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- i
- s
- c
- s
- i
- /
- i
- n
- i
- t
- i
- a
- t
- o
- r
- /
- i
- s
- c
- s
- i
- _
- s
- u
- b
- r
- .
- c
- :
- 5
- 7
- 2
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- i
- s
- c
- s
- i
- /
- i
- n
- i
- t
- i
- a
- t
- o
- r
- /
- i
- s
- c
- s
- i
- _
- s
- u
- b
- r
- .
- c
- :
- 5
- 7
- 3
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- i
- s
- c
- s
- i
- /
- i
- n
- i
- t
- i
- a
- t
- o
- r
- /
- i
- s
- c
- s
- i
- _
- s
- u
- b
- r
- .
- c
- :
- 5
- 7
- 4
Detail
Exploit chain
Primitive characterized (write-what-where into kmalloc-edtlen). Hard blocker for GENERIC uid0: iscsi_initiator is loadable (not in GENERIC), kldload needs root, maxx cannot reach path. REMOTE threat (target->initiator) stands as Critical.
Evidence (decisive lines)
UNFIXED: 4 OOB writes (256+128+16+16 bytes). FIXED: 0 OOB. Module builds rc=0 with new xdebug string.
PoC changes
harness.c userspace port, fix.diff (offset+len<=edtlen guard), VERDICT.md, manifest.json, evil_target.py reference
Verified recommended fix
In iscsi_subr.c ISCSI_READ_DATA: change int offset/len to u_int, capture edtlen, add 'if (offset > edtlen || len > edtlen - offset) break;' before dp=data_ptr+offset.
Verdict
REPRODUCED write-what-where. scsi_decap ISCSI_READ_DATA at iscsi_subr.c:566-574 uses attacker bo+offset without bounds vs edtlen. Harness proves 416 bytes OOB across 4 attacker offset patterns.
No comments yet.