# DF-5658 VERDICT

**Status: reproduced (build-diff evidence class). Impact: none at runtime
today — no relocation or C consumer references the vanished exports; the
defect is a silently-broken C↔assembly contract at 21× the scale of the pc64
twin (DF-5596), on the platform whose link (plain userland `cc`) has the
weakest undefined-symbol gate. Confidence: certain.**

## The claim under test

Pass-2 task_log lead (2026-10-08): "vkernel64 global.s:65 has the identical
GD_CURRENTLDT dangle". Verified — and it is not alone: an exhaustive
used-vs-defined inventory over ALL assym.s consumers in the VKERNEL64 build
(global.s, locore.s, swtch.s, fork_tramp.s — plus in_cksum2.s/monitor.s/
bzeront.s which include assym.s but consume no macros) shows:

- `sys/platform/vkernel64/x86_64/global.s` consumes **26 distinct GD_\* macros**
  (lines 52-97) for its `.globl`/`.set` export block;
- `sys/platform/vkernel64/x86_64/genassym.c` defines only **5** of them
  (GD_CURTHREAD :77, GD_CPUID :78, GD_CPUMASK :79, GD_OTHER_CPUS :80,
  GD_NPXTHREAD :121);
- **21 dangle**, split by restorability into this finding (13) and DF-5659 (8):

  | macro | field exists? | location |
  |---|---|---|
  | GD_REQFLAGS | yes — mi.gd_reqflags | global.s:54 |
  | GD_NPXTHREAD | yes (defined) | global.s:53 |
  | GD_COMMON_TSSD | yes — globaldata.h:68 | global.s:61 |
  | GD_TSS_GDT | yes — globaldata.h:69 | global.s:62 |
  | GD_CURRENTLDT | yes — globaldata.h:78 | global.s:65 ← **the lead** |
  | GD_FPU_LOCK | yes — globaldata.h:73 | global.s:68 |
  | GD_SAVEFPU | yes — globaldata.h:72 | global.s:69 |
  | GD_SS_EFLAGS | yes — globaldata.h:83 | global.s:84 |
  | GD_INTR_NESTING_LEVEL | yes — mi.gd_intr_nesting_level | global.s:85 |
  | GD_FPENDING/GD_IPENDING/GD_SPENDING | yes — globaldata.h:74-76 | global.s:94-96 |
  | GD_CNT | yes — mi.gd_cnt | global.s:97 |
  | GD_PRV_CMAP1-3/PMAP1/CADDR1-3/PADDR1 | **NO — absent from vkernel64 struct privatespace** | global.s:77-78,86-93 → DF-5659 |

Every live displacement use in the real consumers resolves (swtch.o,
fork_tramp.o, locore.o: **zero** ASSYM-shaped undefined symbols — the
PCB_CR3/PCB_EXT/MSR_FSBASE/MSR_KGSBASE/PCB_USERLDT uses in swtch.s:348,369,
429,440,464 are all inside `#if 0` dead blocks). The entire defect class is
concentrated in global.s's `.set` export block, where gas resolves the missing
macro to an *undefined external symbol*: the alias and its `.globl` export
silently vanish, assembly exits 0, `-Werror` stays silent.

## Reproduction (guest, DragonFly 6.5-DEVELOPMENT #0, cc 8.3, 6 vCPU)

1. **Source identity.** All 9 involved files MD5-identical between audit tree
   and guest `/usr/src` (`env.txt`).
2. **Real-rule regen.** `config VKKERNEL64` → `/usr/src/sys/compile/VKERNEL64`;
   `make assym.s` via kern.post.mk:73-79 emitted exactly 44 defines
   (`assym.pristine.s`), regeneration byte-identical (determinism).
   `make global.o` (kern.post.mk .s rule, `-Werror`) → exit 0, and
   `nm global.o` (`nm_global_pristine.txt`): exactly 5 backed exports
   (gd_curthread=0x8, gd_cpuid=0x48, gd_cpumask=0x50, gd_npxthread=0x3a90,
   gd_other_cpus=0x70) + `U` for all 21 missing macros — **`U GD_CURRENTLDT`
   among them, the lead confirmed at the object level** — while gd_reqflags,
   gd_common_tss, gd_currentldt, … (the 21 `.globl` exports) are **absent
   from nm entirely**.
3. **End-to-end link.** The vkernel is linked as a *user program*
   (conf/Makefile:23-25: `cc -Wl,--export-dynamic … -pthread`, no `-T
   ldscript`). Linking all 547 SYSTEM_OBJS + vers.o that way
   (`link.log`/`final_binary_baseline.txt`) → **exit 0** with the 21 `U GD_*`
   riding into the final binary **with zero relocations**
   (`objdump -r`/`readelf -r` → 0 GD_* entries) — precisely why the
   userland link never fails on them.
4. **Fix.** `fix.diff` adds the 13 restorable ASSYM lines to genassym.c and
   deletes the 8 GD_PRV_* aliases from global.s (DF-5659). Rebuilt with the
   same rules (`fix_build.log`): assym.s 44→57 defines
   (`assym.fixed.s`); `global.o` now exports **18 gd_\* symbols with zero
   undefined ASSYM macros**; relinked final binary (`fix_run.log`,
   `final_binary_fixed.txt`): **0 `U GD_*`, 18 exports**, link exit 0.
   Every restored value matches the independent TU checker exactly, e.g.
   `gd_currentldt=0x3f14` — struct-consistent (gd_spending 0x3f0c +
   gd_sdelayed 0x3f10 + int → 0x3f14, globaldata.h:74-78).

## Contract-wide cross-checks (pass-2 checklist)

- **(b) offset-vs-struct correctness:** `offset_check.c` re-evaluates every
  one of the 44 emitted ASSYM expressions in a separate TU compiled with the
  exact genassym CFLAGS — **44/44 values match** `assym.s` (only the `0x`
  presentation differs). No stale offsets. Negative result, with evidence.
- **(c) used-vs-defined inventory:** every CAPS macro token extracted from
  all 4 platform .s consumers + 3 cpu/x86_64/misc .s consumers; the ONLY
  unmatched set is the 21 GD_* in global.s. swtch.s's MSR_FSBASE/MSR_KGSBASE
  uses are inside `#if 0` and additionally resolvable from specialreg.h
  (swtch.s includes <machine/pmap.h>/<machine/lock.h> chains).
- **(d) vkernel-specific fields:** `TD_SAVEFPU=0x628` verified ==
  `offsetof(struct thread, td_mach.mtd_savefpu)` (thread.h:43,49), consumed
  live by swtch.s:558,701 — correct. The DF-5655 TLS-aliasing chain
  (`td_tls` == `td_mach.mtd_savevext.vx_tls`, thread.h:50) is **C-side
  only**: `CHECK_td_tls=CHECK_mtd_savevext=0x630`, `CHECK_vx_tls=0`, and NO
  assembly consumer references it (swtch.s's TLS-restore block at :477-484
  is `#if 0`). No genassym exposure — negative result, chain documented.
- **DF-5597 twin (ioapic stride):** zero IOAPIC_* tokens in any vkernel64
  .s consumer — not applicable on this platform.

## Incidental discovery (out-of-file lead, task_log'd)

The full VKERNEL64 build **fails at link** on
`kern_mib.c:111/132 → undefined reference to '__build_id_start/__build_id_end'`
(`vkbuild.log`): kern.pre.mk's default SYSTEM_LD passes
`-Wl,-T,$S/platform/$P/conf/ldscript.$M` (which PROVIDEs both symbols,
vkernel64/conf/ldscript.x86_64:75), but vkernel64's conf/Makefile SYSTEM_LD
**override drops -T**, so the vkernel64 kernel has been unbuildable since the
build-id sysctl landed. This failure is also what empirically delimits the
DF-5596 mechanism on the vkernel link: the link DOES fail hard on
relocation-referenced undefined symbols (__build_id_* has relocations) while
tolerating the 21 zero-relocation GD_* dangles silently.

## Why it matters / impact ceiling

- Today: **zero runtime effect** — nothing references the vanished symbols by
  relocation; C code uses `mdcpu->` (and vkernel64's `set_user_ldt` panics,
  userldt.c:44 — no LDT support). The `.globl` exports that ddb/kgdb scripts
  and future assembly would rely on simply do not exist, on the platform
  whose debugger (in-process ddb) reads the vkernel's own symtab.
- Systemically: the genassym contract is the ONLY build-time guard for the
  C↔asm offset agreement (the silent memory-corruption class this audit
  family tracks — DF-5586/5335 lineage). This file shows the guard failing
  silently **21 ways at once** on the platform with the weakest link gate,
  and 8 of the 21 cannot even be "restored" (fields absent) — a maintainer
  attempting the obvious fix hits a compile error and is likely to abandon
  all 21.

## Classification

Reproduced: yes — object level (`nm global.o`), final-binary level (21 `U`,
0 relocations, link exit 0), and controlled fix (0 `U`, 18 exports, values
independent-TU verified). Exploit chain: none — build-time contract defect,
no attacker-reachable primitive. Recommended fix validated: `fix.diff`
(git-apply-clean against pristine sys/, never applied to the audit tree).

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