spoof: class-bound nvme PCI vendor:device (extend 0018)

Override the qemu-nvme controller vendor:device (Red Hat 1b36:0010) to a real NVMe
vendor matched to the spoofed model brand (Samsung/WD/Kioxia/Kingston/Intel/SMI/
hynix/Micron/Phison), with a coherent subsystem. Safe: NVMe binds by class code,
not id, and this runs before nvme_init_ctrl so the IDENTIFY vid/ssvid stay aligned.
virtio/GPU vendor:device untouched (load-bearing). Inert without a seed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-11 22:35:47 +03:00
parent 9b17bdfa33
commit 3268fe11e1
4 changed files with 69 additions and 25 deletions
+26
View File
@@ -79,6 +79,20 @@ static uint64_t brand_oui(const char *m)
if (!strncmp(m, "CT", 2) || !strncmp(m, "Crucial", 7)) return 0x00A075; /* Micron */
return 0x0024E9;
}
/* Real NVMe controller PCI vendor:device, matched to the spoofed model's brand
* (the guest binds NVMe by class code, so this is safe to set on the QEMU ctrl). */
static void nvme_pci_id(const char *m, uint16_t *vid, uint16_t *did)
{
if (!strncmp(m, "Samsung", 7)) { *vid = 0x144d; *did = 0xa80a; } /* Samsung */
else if (!strncmp(m, "WD", 2)) { *vid = 0x15b7; *did = 0x5017; } /* WD/SanDisk */
else if (strstr(m, "TOSHIBA") || !strncmp(m, "KXG", 3)) { *vid = 0x1e0f; *did = 0x0001; } /* Kioxia */
else if (!strncmp(m, "KINGSTON", 8)){ *vid = 0x2646; *did = 0x5013; } /* Kingston */
else if (!strncmp(m, "INTEL", 5)) { *vid = 0x8086; *did = 0x390b; } /* Intel */
else if (!strncmp(m, "ADATA", 5)) { *vid = 0x126f; *did = 0x2263; } /* Silicon Motion */
else if (strstr(m, "Hynix")) { *vid = 0x1c5c; *did = 0x1d59; } /* SK hynix */
else if (!strncmp(m, "CT", 2) || !strncmp(m, "Micron", 6)) { *vid = 0x1344; *did = 0x5407; } /* Micron */
else { *vid = 0x1987; *did = 0x5012; } /* Phison */
}
static struct {
const char *model; char serial[24], fw[12]; uint64_t wwn; int rpm;
@@ -119,6 +133,18 @@ const char *spoof_nvme_model(const char *def) { if (!spoof_on()) return def; v_
const char *spoof_nvme_serial(const char *def) { if (!spoof_on()) return def; v_init(); return v.serial; }
const char *spoof_nvme_fw(const char *def) { if (!spoof_on()) return def; v_init(); return v.fw; }
uint64_t spoof_nvme_eui64(uint64_t def) { if (!spoof_on()) return def; v_init(); return v.eui64; }
uint16_t spoof_nvme_pci_vendor(uint16_t def)
{
if (!spoof_on()) return def;
v_init();
uint16_t vid, did; nvme_pci_id(v.model, &vid, &did); return vid;
}
uint16_t spoof_nvme_pci_device(uint16_t def)
{
if (!spoof_on()) return def;
v_init();
uint16_t vid, did; nvme_pci_id(v.model, &vid, &did); return did;
}
void spoof_nvme_nguid(uint8_t out[16])
{
+2
View File
@@ -92,6 +92,8 @@ const char *spoof_nvme_serial(const char *def);
const char *spoof_nvme_fw(const char *def); /* 8-char rev (fixes FR leak) */
uint64_t spoof_nvme_eui64(uint64_t def); /* OUI + vendor */
void spoof_nvme_nguid(uint8_t out[16]); /* filled iff enabled */
uint16_t spoof_nvme_pci_vendor(uint16_t def); /* class-bound: real NVMe vendor */
uint16_t spoof_nvme_pci_device(uint16_t def); /* brand-matched to the model */
const char *spoof_cdrom_model(const char *def);
int spoof_disk_rotation(int def); /* 1=SSD, else RPM (matches model) */