# DF-3124 — cd9660 kiconv mount: ignored iconv_open() failure → convchr(NULL) kernel panic

## What

`iso_mountfs()` (sys/vfs/isofs/cd9660/cd9660_vfsops.c:491-499) ignores the
return value of both `cd9660_iconv->open()` calls. When the charset pair
cannot be opened (empty, unregistered, or unavailable charset names —
`iconv_open()` returns ENOENT), `isomp->im_d2l` / `isomp->im_l2d` stay NULL
while `im_flags` still carries `ISOFSMNT_KICONV`. The first pathname lookup
or readdir on the mount then does:

```
namei -> cd9660_lookup -> isofncmp(..., imp->im_l2d) -> sgetrune()
      -> cd9660_iconv->convchr(NULL, ...)          (cd9660_util.c sgetrune)
      -> iconv_convchr(NULL) -> KOBJ dispatch reads ops through NULL
      -> kernel page fault at VA 0 -> panic
```

`cd9660_unmount()` (cd9660_vfsops.c:584-589) already NULL-checks both
handles before close — the NULL state is clearly anticipated; the consumers
were simply never made safe against it.

## Reproduce (on the QEMU guest, as root)

```
# 1. stage files (from the pack): poc.iso (minimal crafted ISO9660 image),
#    trigger.c
scp poc.iso trigger.c dfbsd:/root/

# 2. in the guest:
vnconfig -c -S 2048 /dev/vn0 /root/poc.iso
kldload libiconv
kldload cd9660_iconv
cc -O -o /root/trigger /root/trigger.c -I/usr/src/sys
mkdir -p /mnt/poc
/root/trigger          # mounts with ISOFSMNT_KICONV + empty charsets, then stat()s
```

## Expected

```
[+] mount succeeded with ISOFSMNT_KICONV and failed iconv_open (im_d2l == im_l2d == NULL)
[+] triggering namei under the mount ...
```
…then the console shows:
```
Fatal user address access from kernel mode from trigger at ...
Fatal trap 12: page fault while in kernel mode
fault virtual address    = 0x0
Stopped at      iconv_convchr+0x27:     movq    (%rdi),%rsi
```

## Baseline

The same image mounted without `-o kiconv` (`mount_cd9660 /dev/vn0 /mnt/poc`)
mounts cleanly; lookups return ENOENT; unmount works. The panic is specific
to the KICONV flag with a failed charset open.

## Impact

NULL-deref kernel panic (local DoS). The deref target is fixed address 0 —
no control over the faulting pointer, no escalation primitive. Mounting
requires root / SYSCAP_RESTRICTEDROOT (`get_fscap("cd9660")`), but the
*panic trigger* is any namei under the mount, i.e. any local user after an
admin has made such a mount.
