feed_matrix_feed FXROUND misrounds: entry rounding sizes the matrixing pass past the destination window and the ialign>oalign path computes a source window that starts before the buffer
Summary
Same generated-table defect consumed at entry count, the j=FXROUND(count-oalign,ialign) window math (src can start before dst), and the partial-return FXDIV. HARNESS-VERIFIED: 4891/23706 checks fail (e.g. 2ch->6ch upmix count=8195 writes at offset 8196 past the window); fixed generator: 0. Unpriv via CHANNELS on any channel-count mismatch. Supersedes this file's earlier 'clean' soak (bad residues not driven).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4847 Β· 16 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.9 KB | β raw | |
| VERDICT.md | β | 2.5 KB | β raw | |
| verdict.json | β | 3.5 KB | view raw | |
| fxshim.h | β | 6.9 KB | view raw | |
| fxsrc.c | β | 2.0 KB | view raw | |
| ffmat.c | β | 5.3 KB | view raw | |
| fxfmt.c | β | 6.6 KB | view raw | |
| ffmat.c | β | 5.3 KB | view raw | |
| ffvol.c | β | 5.5 KB | view raw | |
| ffmix.c | β | 9.2 KB | view raw | |
| dspchurn.c | β | 2.1 KB | view raw | |
| ctlchurn.c | β | 991 B | view raw | |
| build.sh | β | 119 B | view raw | |
| run.sh | β | 140 B | view raw | |
| fix.diff | β | 1.0 KB | view raw | |
| snd_fxdiv_gen_fixed.awk | β | 4.0 KB | β download |
DF-4847 β feeder_matrix.c FXROUND align-overshoot (evidence pack)
What this proves
The REAL, UNMODIFIED sys/dev/sound/pcm/feeder_matrix.c sizes its feed
window with the inexact generated SND_FXROUND/SND_FXDIV macros (see
DF-4846 for the table defect β misround-up within the claimed [1,65536]
domain from xβ5.4K for align 14, xβ8.2K for align 12, 15β40% of counts):
- :479
count = SND_FXROUND(count, info->oalign)misrounds past the caller's count β pass sized past the destination window. - :501 (ialign>oalign, e.g. 7chβ5ch)
j = SND_FXROUND(count - oalign, ialign)misrounds β j can exceed countβoalign by up to ialignβ1 βsrc = dst + count - jbefore the window start AND the source ask window exceeds the destination. - :509
SND_FXDIV(FEEDER_FEED(...), ialign)miscounts frames on partial (user-paced) source returns.
The pass-2 soak that previously cleared this file (220k iterations) did not drive the bad-residue count values; this harness enumerates them exactly.
Build / run (guest)
cd /root/fx && sh build.sh && ./ffmat # baseline: FAIL (4891/23706) # fixed generator: cp snd_fxdiv_gen_fixed.h snd_fxdiv_gen.h && cc -O1 -g -o ffmat_fixed ffmat.c fxsrc.c ./ffmat_fixed # ALL PASS
Expected output
mat.log: ffmat: checks=23706 failures=4891 -> FAIL, decisive lines:
FAIL[T2 upmix ialign=4<oalign=12] in_ch=2 out_ch=6 count=8195 ret=8184 REAR
guard (write past window) maxwrite_off=8196 maxask=2728.
In-kernel reachability
feeder_matrix inserted on any channel-count mismatch (feeder_chain.c:284-336,
use_matrix when feeder_matrix_compare(origin,target) != 0) β an
unprivileged SNDCTL_DSP_CHANNELS choice; counts from buffer.c:705-709 as in
DF-4846. In-kernel churn logs in the DF-4849 pack.
Fix
fix.diff (shared generator fix). A/B: baseline 4891 failures β fixed 0.
DF-4847 β VERDICT
status: reproduced (feeder level, real unmodified code on the audit guest) primitive: up to ialignβ1 byte OOB write past the destination window (including window-preceding underwrite via the :501 misround) + return over-report into sndbuf_acquire (ring overflow) confidence: certain
Root cause
Shared table defect (snd_fxdiv_gen.awk calcdiv single-point validation β see
DF-4846 VERDICT for the exhaustive enumeration) consumed on the caller's
window by feed_matrix_feed:
feeder_matrix.c:479count = SND_FXROUND(count, info->oalign)β misround β count' > count: the source fill and matrixing pass are sized past the window.:494-506for ialign>oalign:j = SND_FXROUND(count - info->oalign, info->ialign)β misround β j up to count+ialignβoalignβ1 > count βsrc = dst + count - j < dstβ the source writes BEFORE the destination window and past its end.:509SND_FXDIV(FEEDER_FEED(...), ialign)β frame miscount on partial user-paced returns;apply()then processes frames the source never delivered.
Reproduction (guest, pristine file)
ffmat (mat.log): checks=23706 failures=4891, decisive:
FAIL[T2 upmix ialign=4<oalign=12] in_ch=2 out_ch=6 count=8195 ret=8184 REAR guard (write past window) maxwrite_off=8196 maxask=2728
count=8195 is the first bad value for align 12 (FXROUND(8195,12)=8196):
a 2chβ6ch upmix writes past the 8195-byte window (maxwrite_off 8196).
Note: the previous pass-2 result for this file ("clean, 220k iterations") did not include the bad-residue count enumeration; the defect is deterministic arithmetic, not timing.
Kernel reachability
feeder_build_matrix (feeder_chain.c:284-336) on any channel-count mismatch β unprivileged SNDCTL_DSP_CHANNELS (2β6/7 etc.); default chain. Counts as in DF-4846 (buffer.c:705-709). In-kernel churn: no differential anomaly vs aligned control on this no-INVARIANTS kernel (DF-4849 pack logs) β same reasoning as DF-4710/DF-4846.
Fix validation
fix.diff (generator, shared): baseline 4891 failures β fixed 0 (ALL
PASS) (mat.log vs mat_fixed.log). Fixed table exhaustively exact for
all 44 divisors over [1,65536]. fix_status: fixed.
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.
Fix verification
fixedA/B at harness level, only the generated header swapped: 4891 failures vs 0 (mat.log vs mat_fixed.log). Kernel rebuild A/B not performed (null in-kernel baseline observable on this rig, same standard as DF-4710).
mat_fixed.log (failures=0); fix.diff; snd_fxdiv_gen_fixed.awk
Confirmed kernel references
- sys/dev/sound/pcm/feeder_matrix.c:479
- sys/dev/sound/pcm/feeder_matrix.c:494-506
- sys/dev/sound/pcm/feeder_matrix.c:501
- sys/dev/sound/pcm/feeder_matrix.c:509
- sys/dev/sound/pcm/feeder_chain.c:284-336
- sys/dev/sound/pcm/buffer.c:705
- sys/dev/sound/pcm/buffer.c:708-712
- sys/dev/sound/pcm/buffer.c:615-636
- sys/tools/sound/snd_fxdiv_gen.awk:56-71
Detail
Evidence (decisive lines)
mat.log (baseline: checks=23706 failures=4891, REAR-guard hits with exact counts); mat_fixed.log (fixed table: failures=0 ALL PASS); ffmat.c/fxshim.h/fxsrc.c (harness compiling the pristine feeder_matrix.c with real headers and the real generated table); VERDICT.md
PoC changes
Fresh harness (DF-4846 infrastructure); source pattern lowered to tiny amplitudes so the file's own FEEDMATRIX_CLIP_CHECK errx diagnostic never terminates the run.
Verified recommended fix
Fix snd_fxdiv_gen.awk (domain-exact reciprocals + 64-bit multiply, fix.diff); optionally clamp count in feed_matrix_feed to the caller's window.
Verdict
Reproduced at feeder level on the audit guest against the real, unmodified sys/dev/sound/pcm/feeder_matrix.c: feed_matrix_feed() sizes its pass with the inexact generated SND_FXROUND/SND_FXDIV macros (shared table defect with DF-4846: misround-up within [1,65536] from x~4.7K-8.2K for non-pow2 aligns). :479 FXROUND(count,oalign) can exceed the caller's count (pass sized past the window); :501 FXROUND(count-oalign,ialign) can make j>count so src=dst+count-j lands BEFORE the window and the source window exceeds the destination; :509 FXDIV of a partial user-paced return miscounts frames. Harness: 4891/23706 checks fail with canary-guard hits (e.g. 2ch->6ch upmix, count=8195, FXROUND(8195,12)=8196, write past window); with the fixed generator header 0 failures. The previous pass-2 soak (220k iterations) did not drive the bad-residue counts - the defect is deterministic arithmetic. Reachability: feeder_build_matrix on any channel-count mismatch (feeder_chain.c:284-336), unprivileged SNDCTL_DSP_CHANNELS, default chain; counts user-paced via buffer.c:705-709. In-kernel churn: no differential anomaly vs aligned control on this no-INVARIANTS kernel (logs in DF-4849 pack), as expected for <=ialign-1-byte writes plus silent ring overflow. Impact ceiling: kernel heap OOB write past tmpbuf at exact-page allocation geometry + sndbuf ring invariant breakage, unprivileged, default config.
No comments yet.