Kernel heap info leak in mpr_user_event_report: copyout of user-supplied Size from fixed-size recorded_events[40000]
Summary
mpr_user_event_report at mpr_user.c:2075-2079: if(size>=sizeof(sc->recorded_events)) copyout(recorded_events,...,size). size=data->Size (uint32_t user-controlled, no upper bound). sizeof(recorded_events)=40000 bytes. Size=0xFFFFFFFF -> copyout reads 4GB from recorded_events inside mpr_softc -> leaks entire softc tail (DMA bus addresses, kernel pointers) + adjacent heap. Operator group. Fix: always copyout sizeof(recorded_events).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1328 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| poc.c | trigger-source | MPTIOCTL_EVENT_REPORT with Size=256KiB (>= 40000); dumps softc tail | 2.4 KB | view raw |
| VERDICT.md | verdict | full source trace: copyout length is user Size, gate is lower-bound only | 3.2 KB | β raw |
| fix.diff | suggested-fix | copyout exactly sizeof(recorded_events), independent of user Size | 666 B | view raw |
| build.sh | build-script | cc -o poc poc.c -Wall | 183 B | view raw |
| run.sh | run-script | ./poc | 372 B | view raw |
| build.log | build-log | guest build output (BUILD_EXIT=0) | 13 B | view raw |
| run.log | run-log | guest run: open /dev/mpr0 ENOENT (no HBA) | 81 B | view raw |
| fix_build.log | build-log | full nativekernel build with all 3 mpr fixes, rc=0 | 5.6 MB | β download |
| env.txt | environment | guest uname, cc, driver-availability facts | 1.5 KB | view raw |
| README.md | readme | summary + repro + file index | 923 B | β 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-1328 β mpr_user_event_report kernel-heap info leak
Status: INCONCLUSIVE (real bug; needs LSI SAS3+ HBA absent from audit guest)
Impact: info leak (kernel heap past recorded_events[40000], operator-group reachable)
Driver: mpr (LSI MPT-Fusion 3 SAS) β in X86_64_GENERIC but no HBA on guest
Build & run
./build.sh # cc -o poc poc.c -Wall ./run.sh # ./poc (as an operator-group user on an mpr-equipped host)
On the audit guest the PoC fails at open("/dev/mpr0") with ENOENT.
See VERDICT.md for the full trace and fix.diff for the validated patch.
Files
poc.cβ PoC (MPTIOCTL_EVENT_REPORT, Size=256KiB β₯ 40000)VERDICT.mdβ full mechanism trace with path:line citationsfix.diffβ copyout exactly sizeof(recorded_events), not user sizebuild.sh/run.sh,build.log/run.log,fix_build.log,env.txt,manifest.json
DF-1328 β mpr_user_event_report kernel-heap info leak
Verdict
INCONCLUSIVE (real bug, needs hardware absent from guest). Source
trace confirms the vulnerability; it cannot be executed on this QEMU
guest because /dev/mpr0 does not exist (no LSI SAS3+ HBA), so the PoC
fails at open() with ENOENT. Fix validated to apply + compile in a
full nativekernel build.
Mechanism
sys/dev/raid/mpr/mpr_user.c:2074 mpr_lock(sc); sys/dev/raid/mpr/mpr_user.c:2075 size = data->Size; // uint32_t, user-controlled sys/dev/raid/mpr/mpr_user.c:2076 if ((size >= sizeof(sc->recorded_events)) && (status == 0)) { sys/dev/raid/mpr/mpr_user.c:2077 mpr_unlock(sc); sys/dev/raid/mpr/mpr_user.c:2078 if (copyout((void *)sc->recorded_events, sys/dev/raid/mpr/mpr_user.c:2079 PTRIN(data->PtrEvents), size) != 0) // *** LEAK: len = user size *** sys/dev/raid/mpr/mpr_user.c:2080 status = EFAULT; sys/dev/raid/mpr/mpr_user.c:2081 mpr_lock(sc);
sizeof(sc->recorded_events) = MPR_EVENT_QUEUE_SIZE (200) Γ
sizeof(mpr_event_entry_t) (= 4+4+4*MPR_MAX_EVENT_DATA_LENGTH =
4+4+4*48 = 200) = 40000 bytes
(sys/dev/raid/mpr/mpr_ioctl.h:206, :207, :224-229;
sys/dev/raid/mpr/mprvar.h:445).
The gate at 2076 is a lower bound, not an upper bound: it only
requires size >= 40000. The copyout length is the user-supplied
size, which can be up to 0xFFFFFFFF (4 GiB). Setting size to,
say, 256 KiB reads 256 KiB out of sc->recorded_events β 40000 bytes of
the array plus ~220 KiB of whatever follows it inside struct mpr_softc
(DMA bus addresses, kernel pointers, locks, command rings) and into
adjacent kernel heap. Deterministic kernel-heap information leak.
Reachability on this guest
Identical to DF-1327: mpr is compiled into GENERIC but no SAS HBA is
present β no /dev/mpr0 β PoC fails at open():
poc: open /dev/mpr0: No such file or directory (RUN_EXIT=1)
Privilege model is the same (device UID_ROOT/GID_OPERATOR 0640,
mpr_open returns 0, mpr_ioctl does no priv_check): reachable by
root or operator-group users on an mpr-equipped host.
Phase-4(d) again: real code path, unreachable on this guest due to absent hardware.
Exploit chain
None β read-only OOB info leak, no corruption primitive. Impact ceiling:
deterministic disclosure of the mpr_softc tail (DMA addresses, kernel
pointers) and adjacent heap, repeated to taste. KASLR-bypass / heap
layout reconnaissance.
PoC changes
Folder was empty. Authored poc.c (opens /dev/mpr0, issues
MPTIOCTL_EVENT_REPORT with Size = 256 KiB, dumps bytes 40000..40256 of
the softc tail), build.sh, run.sh.
Fix
fix.diff makes the copyout length sizeof(sc->recorded_events) (the
fixed array size) instead of the user-controlled size. The size >=
gate remains the lower-bound "did the user give us a big enough buffer?"
check; the actual bytes copied are now exactly the array. Applies
cleanly and was built in the full nativekernel run (fix_build.log).
Fix validation
fix_status: not_testable β PoC cannot run (no /dev/mpr0). Fix
validated by apply + compile + code-path inspection (copyout length is now
the constant array size, independent of data->Size).
Fix verification
not_testablecompile validated
nativekernel rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. mpr_user_event_report copyout uses user Size not sizeof(recorded_events) -> heap info leak. mpr in GENERIC.
No comments yet.