# DF-3199 — heap over-read in devfs_rule_create_link() disclosed as world-readable link names

## Root cause
`devfs_rule_create_link()` (`devfs_rules.c:237-253`) takes the wildcard branch
whenever `rule->name` ends in `'*'`, then strips

    len = strlen(pattern_basename) - 1

bytes from the NODE's name:

    ksnprintf(buf, sizeof(buf), "%s%s", rule->linkname, node->d_dir.d_name+len);

`devfs_WildCaseCmp` allows any number of leading `'*'`s, so a pattern of N
stars + `"null"` + trailing `'*'` full-matches the node `null` (4-char name)
while stripping N+4 bytes. `node->d_dir.d_name` is a separate
`kmalloc(namlen+1)` allocation (`devfs_core.c:253`) — 5 bytes for `"null"` —
so the read starts up to ~200 bytes PAST the chunk and copies adjacent
M_DEVFS heap contents into the new alias's name, visible to every user via
`ls /dev/lk`.

## Reproduced (3/3 runs, deterministic; plus a live unprivileged read)
```
=== strip offset +17 ===  LK17.urandom     <- stale "urandom" name chunk
=== strip offset +20 ===  LK20.ndom        <- same chunk, shifted +3
=== strip offset +24 ===  LK24.            <- landed on NUL
=== strip offset +33 ===  LK33.kpmap       <- another stale heap string
```
Identical across three runs (stable zone layout). Live check: unprivileged
user `maxx` listed `/dev/lk/LIVE17urandom` — kernel heap bytes (stale devfs
name allocations) disclosed into the filesystem namespace.

The suffix content is bounded by the first NUL; what leaks is the slack/adjacent
16-byte-zone chunks (previous device-name strings). Content disclosure is
modest, but the over-read itself is unbounded w.r.t. attacker-chosen offset
(17..1022) and the output is world-readable. On this kernel, star-heavy
variants (>~90 stars) instead crash via DF-3202 before creating the link.

## Fix
Clamp the strip to the node's actual name length (`fix.diff`):
`if (len > node->d_dir.d_namlen) len = node->d_dir.d_namlen;`
Validated: post-fix aliases carry no leaked suffix (`run.fixed.log`).

## Files
`leak_linkname.c`, `build.sh`, `run.sh`, `run.log`, `leak_sample.txt`,
`fix.diff`, `run.fixed.log`, `verdict.json`, `manifest.json`

## 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.
