DF-3664 / trigger.c
/* * DF-3664 โ bge(4) NVRAM arbitration lock leaked on error paths * * Trigger (HARDWARE REQUIRED โ cannot run on the audit guest): * * bge_nvram_getbyte() (sys/dev/netif/bge/if_bge.c:544-592) implements * the NVRAM software-arbitration handshake for BCM5906 (the only chip * for which bge_read_nvram proceeds, if_bge.c:603-604; reached at * attach time via bge_get_eaddr_nvram, if_bge.c:4977-4985): * * 551: CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1); <- REQ * 552: for (i = 0; i < 8000; i++) { if (GNT1) break; DELAY(20); } * 557: if (i == 8000) * 558: return (1); <- BUG #1: request bit still latched, * no BGE_NVRAMSWARB_CLR1 written * 561: access = CSR_READ_4(sc, BGE_NVRAM_ACCESS); * 562: CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access|BGE_NVRAMACC_ENABLE); * 566: for (i = 0; i < BGE_TIMEOUT*10; i++) { ... } * 574: if (i == BGE_TIMEOUT * 10) { * 575: if_printf(..., "nvram read timed out\n"); * 576: return (1); <- BUG #2: SWARB lock STILL HELD and * BGE_NVRAMACC_ENABLE left set; the * success path restores both * (584-589) * 585: CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access); <- paired * 588: CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1); <- paired * * Contrast with the bnx sibling DF-3640, whose reset path never * released the lock at all; bge pairs acquire/release on the success * path but leaks both the arbitration request and the access-enable * bit on its two timeout paths. * * Impact: after a single NVRAM read timeout (device already * malfunctioning), the driver holds the flash arbiter for its whole * lifetime and leaves the NVRAM access window enabled, locking the * ASF/management firmware (and other agents sharing the arbiter) out * of NVRAM. Device-side functional denial of service only โ no host * memory-safety impact. * * On real hardware the reproduction is: * 1. Attach a BCM5906-based NIC (bge0) whose NVRAM state machine * stalls (or force the read-complete bit to never assert). * 2. bge_get_eaddr_nvram -> bge_read_nvram -> bge_nvram_getbyte * times out and returns without releasing SWARB/ACCESS. * 3. Observe the management firmware can no longer arbitrate for * NVRAM (BGE_NVRAM_SWARB GNT never grants to other requesters). * * The audit QEMU guest has virtio-net only (run.log: NO_BROADCOM_ * DEVICE); bge is compiled into the kernel (kldstat -v: pci/if_bge) * but bge_attach/bge_nvram_getbyte are unreachable there, so this * trigger CANNOT be exercised on it. See VERDICT.md. */ #include <sys/types.h> #include <stdio.h> int main(void) { fprintf(stderr, "DF-3664: this trigger requires bge(4) hardware (BCM5906) with\n" "a stalling NVRAM state machine. On such a system, an attach-time\n" "eeprom/nvram read timeout leaves BGE_NVRAM_SWARB SET1 latched and\n" "BGE_NVRAMACC_ENABLE set forever; verify via the management\n" "firmware failing to arbitrate for NVRAM afterwards.\n"); return 0; } |