Dangling RRIP NM-CONTINUE chain: cd9660_rrip_defname fallback writes the ISO name at the un-reset advanced ana->outbuf β OOB write past altname[NAME_MAX] (kernel stack, lookup) and past the isoreaddir d_name area (kernel heap, readdir); verified unprivileged uid=0
| Field | Value |
|---|---|
| ID | DF-NNNN |
| Status | new |
| Severity | |
| CVSS 3.1 | |
| CWE | |
| File | |
| Lines | |
| Area | |
| Confidence | |
| Discovered | |
| Pass | <1 = GLM 5.2 first pass / 2 = GLM 5.3 second pass> |
| Bucket | |
| Reported | |
| Known CVE | |
| CVE match |
Summary
<2-4 sentences. What is broken, where, and the security consequence.>
Root cause
Threat model & preconditions
- Attacker position:
- Privileges gained or impact:
- Required config or capabilities:
vfs.mount.<fs> allowed, needs a specific device node> - Reachability:
Proof of concept
PoC source: findings/poc/DF-NNNN/<file>
Build & run
<exact commands to compile and run the PoC on a DragonFlyBSD host/VM>
Expected output
<what a successful trigger looks like β panic dump, leaked bytes, uid=0, etc.>
Impact
Recommended fix
--- a/sys/<path>
+++ b/sys/<path>
@@ -<l>,<n> +<l>,<n> @@
<context>
-<vulnerable line>
+<fixed line>
<context>
References
Timeline
Discovered during automated audit. Reported to DragonFlyBSD security contact.
Verification (latest)
status: reproduced | impact: uid0_privesc | confidence: certain
Fix status: fixed β validated fix.diff lives at findings/poc/DF-3156/fix.diff
Unprivileged uid=0 on the stock INVARIANTS kernel #0. A dangling RRIP NM-CONTINUE chain (final NM fragment in a CE continuation area, no terminating fragment) leaves ana->outbuf advanced by up to 255 bytes; cd9660_rrip_loop's default fallback then runs cd9660_rrip_defname, isofntrans-ing up to 183 attacker-chosen name bytes at base+255 -- past altname[NAME_MAX] on the cd9660_lookup stack (measured saved-RBP at OOB+22, saved-RIP at OOB+30; panic_lstat.txt) and past the dirent name in the kmalloc'd isoreaddir on the readdir path (panic in iso_uiodir+0x25 dereferencing the smashed idp->uio). The heap variant was weaponized: idp->uio redirected to a fake struct uio/iovec in the unprivileged process (no SMAP) turns iso_uiodir's uiomove into an arbitrary 152-byte kernel bcopy; one getdents writes the dirent+NM-chain bytes over &sysent[71]-16, hijacking the obsolete syscall 71 sy_call to a ring0 stub at a fixed user address (no SMEP) while restoring every adjacent live sysent entry; syscall(71) executes the stub which zeroes cr_uid/cr_ruid/cr_svuid, sets cr_ngroups=1 and cr_caps=~0 via %gs:0->gd_curthread->td_proc->p_ucred and returns through the intact syscall path. run.log: 'uid after: 0 euid: 0' as nobody plus the contents of mode-0400 /root/df3156_rootproof, guest stays up. All fragment lengths are individually valid (>=5, each accumulation <= NAME_MAX) -- distinct root cause from DF-3146 (negative-wlen underflow) and DF-0878 (entry-length OOB reads). fix.diff (2-line rewind in cd9660_rrip_defname) built as kernel #1 and validated: both triggers become clean fallback names, no panic, no escalation, uid stays 65534.
Evidence pack: findings/poc/DF-3156/ (README.md, VERDICT.md, sources, full logs, fix.diff, manifest.json).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3156 Β· 23 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 4.9 KB | β raw | |
| VERDICT.md | β | 9.3 KB | β raw | |
| build.sh | β | 251 B | view raw | |
| craft_dangle.py | β | 5.6 KB | view raw | |
| craft_exploit.py | β | 4.9 KB | view raw | |
| df3156_exploit.iso | β | 80.0 KB | β download | |
| df3156_pat183.iso | β | 80.0 KB | β download | |
| df3156_rop.iso | β | 80.0 KB | β download | |
| df3156_x4242.iso | β | 80.0 KB | β download | |
| env.txt | β | 746 B | view raw | |
| exploit.c | β | 5.9 KB | view raw | |
| fix.diff | β | 1.2 KB | view raw | |
| fix_build.log | β | 4.6 KB | view raw | |
| fix_run_exploit.log | β | 847 B | view raw | |
| manifest.json | β | 2.6 KB | view raw | |
| panic_dents_serial.log | β | 13.8 KB | view raw | |
| panic_lstat_serial.log | β | 13.6 KB | view raw | |
| run.2.log | β | 337 B | view raw | |
| run.log | β | 288 B | view raw | |
| run.sh | β | 509 B | view raw | |
| run_shell.log | β | 2.0 KB | view raw | |
| run_shell.raw | β | 661 B | β download | |
| trigger.c | β | 1.4 KB | view raw |
DF-3156 β dangling RRIP NM-CONTINUE chain makes the defname fallback write the ISO name out of bounds (kernel stack in lookup, kernel heap in readdir) β verified to unprivileged uid=0
What (root cause)
cd9660_rrip_altname() (sys/vfs/isofs/cd9660/cd9660_rrip.c:226-284) advances
ana->outbuf by every NM fragment (:276-277) and only rewinds it on the
> ana->maxlen rejection (:271). A fragment whose FLAGS byte has
CONTINUE set never completes the name β it returns 0 without setting the
ISO_SUSP_ALTNAME result bit (:279-283).
If the SUSP walk then ends without a terminating NM fragment β trivially
arranged: the last field of the walk is a CONTINUE-flagged NM in a CE
continuation area β cd9660_rrip_loop()'s default-value fallback
(:581-584) invokes cd9660_rrip_defname(), which runs
isofntrans(isodir->name, isonum_711(isodir->name_len),
ana->outbuf, ana->outlen, ...); /* rrip.c:289-292 */
at the stale advanced pointer base + N where N is the accumulated
fragment length (up to 255, reached via CE continuations), writing the
record's translated ISO name (up to ~183 bytes, attacker-chosen content,
copied verbatim at joliet_level 0 / original=1) β up to 183 bytes past the
end of a 255-byte output buffer:
cd9660_lookup()(cd9660_lookup.c:109char altname[NAME_MAX]) β kernel stack; OOB bytes 22..29 = saved RBP, 30..37 = saved RIP (measured:frame pointer = 0x444342415a595857= our cycling A..Z pattern,Stopped at cd9660_lookup+0x461: ret).cd9660_readdir()(cd9660_vnops.c:542, buffer =idp->current.de.d_nameinside the kmalloc'dstruct isoreaddir) β kernel heap; the write smashes the isoreaddir tail:curroff,uiopointer,uio_off,eofflag,cookies,ncookies(measured:Fatal trap 9 ... iso_uiodir+0x25: cmpq %rax,0x18(%r8)β the corruptedidp->uiodereferenced).
All fragment lengths are individually valid (>= 5) and each passes the
> maxlen check β this is not the DF-3146 negative-wlen underflow and
not the DF-0878 entry-length OOB-read family; the defect is the missing
output-buffer reset on the default-name fallback path.
Verified impact (guest 6.5-DEVELOPMENT #0, stock INVARIANTS kernel)
- Unprivileged kernel memory corruption β
getdents/ls(heap) or anystat/path resolution (stack) under the mount, as any user. - Full unprivileged β uid=0 chain (
exploit.c+df3156_exploit.iso): * the heap variant corruptsidp->uioto point at a **fakestruct uiostruct iovecin the (unprivileged) process address space**;iso_uiodir()βuiomove(dirent, 152, fake_uio)withuio_segflg=UIO_SYSSPACEbcopys the dirent (16-byte header + the NM-chain bytes, all attacker data) to the fakeiov_baseβ an arbitrary kernel write with no SMAP to stop it;- the write targets
&sysent[71]-16, hijacking the obsolete syscall 71 (old mmap)sy_callto a ring0 stub at a fixed user address (no SMEP), while restoring every live sysent entry it touches (munmap/mprotect/madvise/sbrk-neighbors) with their original values; syscall(71)executes the stub in ring0:%gs:0 β gd_curthread(+8) β td_proc(+168) β p_ucred(+16)thencr_uid=cr_ruid=cr_svuid=0,cr_ngroups=1,cr_caps=~0;- the syscall returns through the intact syscall path; the process is
now root β
uid after: 0 euid: 0, reads the root-only/root/df3156_rootproof(mode 0400). Guest stays up.
- The stack variant gives direct saved-RIP/RBP control (panic evidence in
panic_lstat.txt) β an alternative escalation route not needed for the demonstrated chain.
Threat model: crafted RRIP ISO mounted by root (same setup as the DF-0878/0879/DF-3124/DF-3146 crafted-media family); after the mount ANY unprivileged user with read access triggers via getdents/stat/ls.
Reproduce
Host: python3 craft_dangle.py pat184 out.iso (pattern trigger),
python3 craft_exploit.py df3156_exploit.iso (full chain).
Stage the pack into the guest and:
cc -O -o /tmp/exploit /root/exploit.c ; cc -O -o /tmp/trigger /root/trigger.c echo "SECRET-ROOT-ONLY-DF3156-$(date +%s)" > /root/df3156_rootproof chmod 400 /root/df3156_rootproof ; mkdir -p /mnt/df3156 vnconfig -c -S 2048 /dev/vn0 /root/df3156_exploit.iso mount_cd9660 -o ro /dev/vn0 /mnt/df3156 su -m nobody -c "/tmp/exploit /mnt/df3156" # -> uid after: 0 + secret # stack-smash proof (panics the box): vnconfig -u /dev/vn0 ; vnconfig -c -S 2048 /dev/vn0 /root/df3156_pat183.iso mount_cd9660 -o ro /dev/vn0 /mnt/df3156 su -m nobody -c "/tmp/trigger lstat /mnt/df3156"
Fix
fix.diff β rewind ana->outbuf/*ana->outlen to the buffer base at the
top of cd9660_rrip_defname() (no-op when no NM fragment was seen).
Validated on a rebuilt kernel (#1): both triggers become clean fallback
names (name='A', pattern name at base), no panic, no uid0
(fix_run_exploit.log).
DF-3156 VERDICT β reproduced, uid0
Bottom line
reproduced / uid0_privesc / certain. A crafted Rock Ridge ISO makes
cd9660_rrip_defname() write up to 183 fully attacker-controlled bytes at
output_buffer + 255 β past a 255-byte kernel-stack array in
cd9660_lookup() and past the dirent name area of the kmalloc'd
struct isoreaddir in cd9660_readdir(). The heap variant was turned into
an arbitrary kernel write (fake struct uio), then into a hijack of
sysent[71].sy_call, then into ring0 execution of a userland stub that
zeroes the calling process's credentials β nobody ends with
uid=0 euid=0 and reads a mode-0400 root file, on the stock INVARIANTS
kernel #0, from a fresh vm.sh reset. The two-line fix.diff was built as
kernel #1 and re-tested: both triggers degrade to clean fallback names, no
panic, no escalation.
How it works (path:line)
- Dangling chain.
cd9660_rrip_altname(sys/vfs/isofs/cd9660/cd9660_rrip.c:226-284) bcopy()s every NM fragment and advancesana->outbuf(:276-277). A fragment with FLAGS&ISO_SUSP_CFLAG_CONTINUE (0x01) returns 0 without setting theISO_SUSP_ALTNAMEresult bit (:279-283) β the name is "still coming". The craft places such an NM as the final field of a CE continuation area (craft_exploit.py): after it the walk simply runs out of fields (pendreached,iso_ce_len == 0β loop breaks at :544-545). - Fallback at the stale pointer. Because
resultlacksISO_SUSP_ALTNAME, the default-value loop (:581-584) callscd9660_rrip_defname, whichisofntrans()es the record's ISO name atana->outbuf=base + 255(:289-292) β OOB. Budget arithmetic:reclen(255) = 33 + name_len + NM1(10) + CE(28)β name_len β€ 183; chain length N = 5 + 250 = 255 (the*outlen > maxlen=NAME_MAXcheck caps N at 255 β both fragments individually legal). - Stack sink.
cd9660_lookup(cd9660_lookup.c:109char altname[NAME_MAX]) β 183 controlled bytes from base+255; measured saved RBP at OOB+22, saved RIP at OOB+30:frame pointer = 0x444342415a595857,Stopped at cd9660_lookup+0x461: ret(panic_lstat.txt) β direct return-address control. - Heap sink β arbitrary write. In
cd9660_readdir(cd9660_vnops.c:542) the buffer isidp->current.de.d_name; the write lands onstruct isoreaddirtail fields (d_name ends at idp+816):currooff(name[17..24)),uio(name[25..32)),uio_off,eofflag,cookies(name[53..60) = 0),ncookies. Naive corruption panics iniso_uiodir+0x25(panic_dents_serial.log); pointingidp->uioat a fakestruct uio/iovecin userland (no SMAP) turnsiso_uiodir()'suiomove(dp, _DIRENT_DIRSIZ(dp), idp->uio)intobcopy(dirent, <any kernel address>, 152)(uio_segflg=UIO_SYSSPACE,uio_rw=UIO_READβ no td KASSERT on that path, kern_subr.c:105-108, :138-143).curroffset huge exits the readdir loop cleanly; cookies NULL avoids the cookie free; the syscall returns normally. - sysent hijack β ring0 β uid0. The copied dirent = 16-byte header +
the NM-chain bytes (both attacker data; the ISO name only supplies
the OOB tail smash). Target
&sysent[71]-16: header lands on deadsysent[70](sstk), chain byte 0..8 βsysent[71].{sy_narg=0, sy_rsize=4}, bytes 8..16 βsy_call= ring0 stub at 0x20000040, bytes 24..128 restoresysent[72..77](vadvise/munmap/mprotect/ madvise/vhangup/vlimit) to their exact original table values so every live syscall (incl. sbrk/mmap used by exec) keeps working.syscall(71)executes the stub in ring0 (no SMEP):%gs:0 β gd_curthread(+8) β td_proc(+168) β p_ucred(+16) β cr_uid(+64)/cr_ruid(+160)/cr_svuid(+164) = 0, cr_ngroups(+68)=1, cr_caps(+176)=~0; returns 0 through the intact syscall frame. Result (run.log):uid after: 0 euid: 0+ contents of/root/df3156_rootproof(0400 root).
Why this is new (not DF-3146 / DF-0878 / DF-0879)
- DF-3146: negative
wlen = length - 5underflow β u_short wrap β 64KB rewind. Here every fragment length is β₯ 5 and every accumulation passes the maxlen check; the write offset is a positive legitimate chain length and the sink is the fallback writer, notaltname's bcopy. - DF-0878: loop-level entry-length upper-bound OOB reads (handlers reading past short entries). This is an OOB write caused by walk termination semantics, and my entry lengths are honest.
- DF-0879: unbounded CE chains / infinite loop. Two CE hops only.
Reproduction matrix (guest 6.5-DEVELOPMENT, x86_64, securelevel -1)
| run | kernel | trigger | result |
|---|---|---|---|
| run.log | #0 stock | exploit as nobody |
uid after: 0 euid: 0, root file read, rc=0, guest up |
| panic_lstat.txt / panic_lstat_serial.log | #0 stock | trigger lstat as nobody |
Fatal trap 9, controlled rbp/rip, cd9660_lookup+0x461: ret |
| panic_dents_serial.log | #0 stock | trigger dents as nobody |
Fatal trap 9 in iso_uiodir+0x25 (corrupted idp->uio) |
| fix_run_exploit.log | #1 patched | exploit as nobody |
poison entry ships as namlen=131 name=A (fallback at base); syscall(71) β SIGSYS from the stock nosys slot; uid stays 65534 |
| fix_run_exploit.log | #1 patched | trigger lstat/dents |
SURVIVED, clean pattern fallback name, guest up |
Fix kernel: patch -p1 < fix.diff, make -j8 nativekernel,
make installkernel, reboot β #1: Mon Sep 7 07:47:17 UTC 2026.
PoC fixes vs the seed
No seed existed (new finding). Iterations that mattered: (1) even-length
ISO names need the pad byte before the SUSP area or the walker starts one
byte into the first field (cd9660_rrip.c:484-486); (2) the dirent that the
hijacked uiomove copies is built from the NM-chain bytes, not the ISO name
(the ISO name is consumed by the OOB tail smash); (3) the record's first
name byte must not be 0/1 β cd9660_rrip_getname (:652-657) treats such
records as "."/"..", skips the NM table row and calls defname at the base
(no OOB); (4) d_type/d_unused2 of the dirent header are stale heap
bytes, so the sysent alignment must keep the 16-byte header on dead fields.
Recommended fix
fix.diff (in this pack): rewind ana->outbuf -= *ana->outlen;
*ana->outlen = 0; at the top of cd9660_rrip_defname() β the fallback
always rebuilds the name at the caller's buffer base; the deltas are 0 on
every legitimate path that reaches it. Defense-in-depth (not required for
correctness): have cd9660_rrip_loop reset the output state whenever the
walk terminates with ISO_SUSP_ALTNAME still pending.
Interactive root shell (2026-10-16 maintenance pass, run_shell.log)
The exploit now has a --shell mode (or DF3156_SHELL=1): after the same
credential-zeroing syscall(71) and the rootproof read it
execl("/bin/sh","sh") into a real interactive # shell β captured under
script(1) on a pty in run_shell.log/run_shell.raw: tty-echoed commands,
id β uid=0(root) gid=0(wheel) groups=0(wheel) inside the shell, rootproof
re-read, touch /tmp/DF3156_OWNED landing 0:0-owned (verified from the ssh
root context after exit), rc=0, guest stable. Two latent PoC defects were
fixed to make the ending work: (1) the ring0 stub wrote cr_caps = ~0, but
cr_caps is a restriction bitmap (sys/sys/caps.h: "negatives, i.e.
restrictions") β ~0 is maximally restricted and made every post-surgery
execve fail EACCES (the original run.log's exec'd id never printed for
exactly this reason); the stub now writes 0 (unrestricted), after which
setgid(0)/setuid(0) also run and exec works (run.2.log now shows the full
uid=0(root) ... groups=0(wheel) id output in default mode too). (2) the
kernel constants are build-specific: on the current with-src snapshot
kernel (a later fix-validation rebuild, sysent=0xffffffff810cb880) the
write lands 0x3f68 below the real sysent, the syscall(71) probe SIGSYSes, and
the misdirected 152-byte write corrupts unrelated static data β reproducibly
panicking at exit (funsetfd_locked+0x28, type 12); on the stock
clean-install kernel (sysent=0xffffffff810c7900) every constant matches and
the chain works first-try. Reproduce on the clean-install snapshot
(vm.sh reset, not with-src) and re-derive constants from
nm /boot/kernel/kernel when the kernel changes. One exploit run per fresh
boot+mount remains the reliable pattern: a repeat run risks the OOB spill
(the 131-byte name writes 66 bytes past the 880-byte isoreaddir into an
adjacent kmalloc slot) hitting a live neighbor β observed once as a
funsetfd_locked trap on process exit. The interactive-shell ending changes
nothing about the finding or its fix: it is a userspace epilogue after the
same verified primitive, so the validated fix.diff kernel stops it at
stage 1 identically (the Sep 7 fix kernel #1 no longer exists on the current
guest image β its snapshot was replaced by the with-src rebuild β so no new
fix-kernel contrast run was made this pass; the original fix validation in
fix_run_exploit.log stands).
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
fixedpatch -p1 < fix.diff; make -j8 nativekernel && make installkernel; reboot into #1. Baseline (#0): exploit => uid0, lstat/dents => trap-9 panics. Patched (#1): exploit degrades to a clean fallback name (namlen=131 name=A) and syscall(71) SIGSYSes from the stock nosys slot, uid stays 65534; lstat and dents SURVIVED with correct names; guest stable.
['fix_run_exploit.log', 'fix_build.log', 'fix.diff']
Confirmed kernel references
- sys/vfs/isofs/cd9660/cd9660_rrip.c:276-277
- sys/vfs/isofs/cd9660/cd9660_rrip.c:279-283
- sys/vfs/isofs/cd9660/cd9660_rrip.c:581-584
- sys/vfs/isofs/cd9660/cd9660_rrip.c:286-304
- sys/vfs/isofs/cd9660/cd9660_lookup.c:109
- sys/vfs/isofs/cd9660/cd9660_lookup.c:261
- sys/vfs/isofs/cd9660/cd9660_vnops.c:542
- sys/vfs/isofs/cd9660/cd9660_vnops.c:343-367
- sys/kern/kern_subr.c:96-160
Detail
Exploit chain
mount crafted RRIP ISO (root setup) -> unpriv getdents on the mount -> defname OOB write smashes isoreaddir tail (uio ptr -> fake uio in userland, cookies=0, curroff=huge for clean loop exit) -> iso_uiodir uiomove bcopy(dirent, &sysent[71]-16, 152) = arbitrary kernel write -> sysent[71].sy_call = ring0 stub (adjacent live entries munmap/mprotect/madvise restored to original values in the same write) -> unpriv syscall(71) -> stub: gs:0 -> gd_curthread+8 -> td_proc+168 -> p_ucred+16 -> cr_uid/cr_ruid/cr_svuid=0, cr_caps=~0 -> normal syscall return -> uid=0 process reads root-only file
Evidence (decisive lines)
["run.log: 'uid after: 0 euid: 0' + SECRET-ROOT-ONLY-DF3156 root-file contents as nobody, fresh-reset boot", 'panic_lstat.txt: frame pointer = 0x444342415a595857 (cycling A..Z pattern), Stopped at cd9660_lookup+0x461: ret', 'panic_dents_serial.log: Fatal trap 9 iso_uiodir+0x25 cmpq %rax,0x18(%r8) (smashed idp->uio)', 'fix_run_exploit.log: patched kernel #1 -- poison entry ships as namlen=131 name=A (fallback at base), syscall(71) -> SIGSYS from stock nosys, uid 65534, lstat/dents SURVIVED', 'fix_build.log / fix.diff: validated 2-line fix (rewind ana->outbuf/*ana->outlen in cd9660_rrip_defname)']
PoC changes
new finding, no seed. Key iterations: even-length ISO names need the pad byte before the SUSP area (rrip.c:484-486) or the walker starts one byte into the first field; the dirent copied by the hijacked uiomove is built from the NM-chain bytes while the ISO name supplies only the OOB tail smash; first name byte must be non-0/1 (getname :652-657 treats such records as ./.. and skips the NM row); dirent header d_type/d_unused2 are stale heap bytes so the sysent alignment keeps the 16-byte header on dead fields (sstk entry).
Verified recommended fix
rewind ana->outbuf/ana->outlen to the caller's buffer base at the top of cd9660_rrip_defname() (no-op on every legitimate path): ana->outbuf -= ana->outlen; *ana->outlen = 0;
Verdict
Unprivileged uid=0 on the stock INVARIANTS kernel #0. A dangling RRIP NM-CONTINUE chain (final NM fragment in a CE continuation area, no terminating fragment) leaves ana->outbuf advanced by up to 255 bytes; cd9660_rrip_loop's default fallback then runs cd9660_rrip_defname, isofntrans-ing up to 183 attacker-chosen name bytes at base+255 -- past altname[NAME_MAX] on the cd9660_lookup stack (measured saved-RBP at OOB+22, saved-RIP at OOB+30; panic_lstat.txt) and past the dirent name in the kmalloc'd isoreaddir on the readdir path (panic in iso_uiodir+0x25 dereferencing the smashed idp->uio). The heap variant was weaponized: idp->uio redirected to a fake struct uio/iovec in the unprivileged process (no SMAP) turns iso_uiodir's uiomove into an arbitrary 152-byte kernel bcopy; one getdents writes the dirent+NM-chain bytes over &sysent[71]-16, hijacking the obsolete syscall 71 sy_call to a ring0 stub at a fixed user address (no SMEP) while restoring every adjacent live sysent entry; syscall(71) executes the stub which zeroes cr_uid/cr_ruid/cr_svuid, sets cr_ngroups=1 and cr_caps=~0 via %gs:0->gd_curthread->td_proc->p_ucred and returns through the intact syscall path. run.log: 'uid after: 0 euid: 0' as nobody plus the contents of mode-0400 /root/df3156_rootproof, guest stays up. All fragment lengths are individually valid (>=5, each accumulation <= NAME_MAX) -- distinct root cause from DF-3146 (negative-wlen underflow) and DF-0878 (entry-length OOB reads). fix.diff (2-line rewind in cd9660_rrip_defname) built as kernel #1 and validated: both triggers become clean fallback names, no panic, no escalation, uid stays 65534.
No comments yet.