Stage K-5: xHCI Input Context allocated full size once per slot (FABRIC-3.10.8 §4.5)
- New XHCI_INPUT_CTX_BYTES (control ctx + slot + 31 EP contexts). Address Device allocates the Input Context at that size once per slot; Configure Endpoint reuses it (bounds-checked). It allocated a fresh one on every attach and never freed the old. - Probe (removed), identical on all three ISAs: after the standard sequence's attach/detach/re-attach, input-context allocations=2 (one per xHCI slot) against configure-endpoint=3. - Standard sequence on amd64/aarch64/riscv64: hash, G, ledger unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1166713cc9
commit
bfa876a0e2
@@ -600,3 +600,26 @@ The per-round growth halved, but about **3.4 KB is still retained per churned VM
|
||||
|
||||
- The G string and the ledger line (the K-3 baseline) are unchanged.
|
||||
- **K-4 closes MC-0d findings 2 and 3.** K-1's heap criterion carries on as K-8.
|
||||
|
||||
### 4.5 K-5 — the xHCI Input Context leak (2026-09-26)
|
||||
|
||||
**Change.**
|
||||
- New `XHCI_INPUT_CTX_BYTES` (xhci.h): the Input Control Context plus a Slot Context and all 31 Endpoint Contexts.
|
||||
- Address Device allocates the slot's Input Context at that full size, once per xHCI slot, mirroring the Output Device Context fix.
|
||||
- Configure Endpoint reuses it, bounds-checking its span. It used to allocate a new block on every attach and never free the old one.
|
||||
|
||||
**Evidence** (the named criterion, counted directly). Heap bytes would mix in the WIREBIND births that attach triggers, so a temporary counter recorded Input Context allocations against Configure Endpoint calls, read before and after the standard sequence:
|
||||
- at Hera's prompt, before the sequence: **1 allocation / 1 configure**, the Zuse thumbdrive attached at boot;
|
||||
- after the sequence (Bob's drive attached, detached and attached again): **2 allocations / 3 configures**, one per xHCI slot used. Before K-5 every configure allocated a fresh block.
|
||||
|
||||
The counts are identical on all three ISAs (probe logs: amd64 `logs/20260926-054615`, aarch64 `logs/20260926-055249`, riscv64 `logs/20260926-055939`).
|
||||
|
||||
**Standard sequence** (clean build, with the probe reverted; the tree is byte-identical to the saved stage diff).
|
||||
|
||||
| ISA | log | result |
|
||||
|---|---|---|
|
||||
| amd64 | `logs/20260926-060605` | hash `0x99b01134c3d3049c`, G A=40 B=40, all ok `3`, 0 B idle, 0 / 0 |
|
||||
| aarch64 | `logs/20260926-061840` | same |
|
||||
| riscv64 | `logs/20260926-063140` | same |
|
||||
|
||||
The ledger line is unchanged. **K-5 closes §8 defect 10.**
|
||||
|
||||
@@ -449,6 +449,11 @@ typedef struct {
|
||||
* -- the controller keeps the address it was given there. */
|
||||
#define XHCI_DEVICE_CTX_ENTRIES 32u
|
||||
#define XHCI_DEVICE_CTX_BYTES (XHCI_DEVICE_CTX_ENTRIES * sizeof(xhci_ep_ctx32_t))
|
||||
/* FABRIC-3.10.8 K-5: the full Input Context -- Input Control Context plus
|
||||
* a Slot Context and all 31 Endpoint Contexts. Allocated once per slot at
|
||||
* Address Device, like the Output Device Context, and reused by Configure
|
||||
* Endpoint (which used to allocate a new one per attach and leak the old). */
|
||||
#define XHCI_INPUT_CTX_BYTES (sizeof(xhci_input_ctrl_ctx32_t) + XHCI_DEVICE_CTX_BYTES)
|
||||
|
||||
#define XHCI_EP_CTX_TYPE_SHIFT 3
|
||||
#define XHCI_EP_CTX_TYPE_CONTROL_BIDI 4u /* EP0 */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+14
-17
@@ -484,9 +484,9 @@ int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
|
||||
* All three re-initialised fully below regardless of whether this is
|
||||
* the first call for this slot. */
|
||||
if (!ms->input_ctx) {
|
||||
ms->input_ctx = kmalloc_aligned(
|
||||
sizeof(xhci_input_ctrl_ctx32_t) + sizeof(xhci_slot_ctx32_t) +
|
||||
sizeof(xhci_ep_ctx32_t), 64);
|
||||
/* K-5: full size (XHCI_INPUT_CTX_BYTES), so Configure Endpoint can
|
||||
* reuse it for every DCI instead of allocating its own. */
|
||||
ms->input_ctx = kmalloc_aligned(XHCI_INPUT_CTX_BYTES, 64);
|
||||
if (!ms->input_ctx) return -1;
|
||||
}
|
||||
/* FABRIC-3.9.8 (found at Stage O-C, 2026-09-25): the Output Device
|
||||
@@ -622,22 +622,19 @@ int xhci_cmd_configure_endpoint(xhci_dev_t *dev, uint32_t slot_id)
|
||||
* put it. */
|
||||
if (max_dci >= XHCI_DEVICE_CTX_ENTRIES) return -1;
|
||||
|
||||
/* ms->input_ctx is reused from Address Device -- same allocation
|
||||
* (96 bytes: Input Control Ctx + Slot Ctx + one EP Ctx) is too small
|
||||
* to also hold two more EP Contexts. Configure Endpoint's Input
|
||||
* Context must span every DCI up to max_dci (xHCI 1.2 spec section
|
||||
* 6.2.5.1: "the Input Context data structure shall contain output
|
||||
* context data structures... up to the value of the Context Entries
|
||||
* field"), not just the ones actually being added -- unused slots
|
||||
* between EP0 (DCI 1) and the bulk endpoints are left zeroed
|
||||
* (Add/Drop flags for those DCIs are 0, so the controller ignores
|
||||
* their content). Reallocated here rather than growing the existing
|
||||
* 96-byte block in place. */
|
||||
/* Configure Endpoint's Input Context must span every DCI up to
|
||||
* max_dci (xHCI 1.2 spec section 6.2.5.1: "the Input Context data
|
||||
* structure shall contain output context data structures... up to the
|
||||
* value of the Context Entries field"), not just the ones actually
|
||||
* being added -- unused slots between EP0 (DCI 1) and the bulk
|
||||
* endpoints are left zeroed (Add/Drop flags for those DCIs are 0, so
|
||||
* the controller ignores their content). FABRIC-3.10.8 K-5: reuses
|
||||
* ms->input_ctx from Address Device, now allocated full size
|
||||
* (XHCI_INPUT_CTX_BYTES); this used to allocate a new one here on
|
||||
* every attach and never free the old. */
|
||||
size_t ctx_count = 1 /* Slot */ + max_dci; /* DCI 1..max_dci, one xhci_ep_ctx32_t each */
|
||||
size_t total = sizeof(xhci_input_ctrl_ctx32_t) + ctx_count * sizeof(xhci_ep_ctx32_t);
|
||||
void *new_input_ctx = kmalloc_aligned(total, 64);
|
||||
if (!new_input_ctx) return -1;
|
||||
ms->input_ctx = new_input_ctx;
|
||||
if (total > XHCI_INPUT_CTX_BYTES) return -1; /* max_dci < XHCI_DEVICE_CTX_ENTRIES above */
|
||||
|
||||
uint8_t *ictx = (uint8_t *)ms->input_ctx;
|
||||
for (size_t i = 0; i < total; i++) ictx[i] = 0;
|
||||
|
||||
Reference in New Issue
Block a user