[PATCH RFC] ALSA: Validate MMIO BARs before mapping

"syzbot" <[email protected]>
Newsgroups dev.linux.lists.syzbot
Message-ID <[email protected]>
The `snd_hda_intel` driver assumes PCI BAR 0 is a memory-mapped I/O (MMIO)
region, but it fails to verify this assumption before mapping and accessing
it. If a device with an I/O Port BAR at BAR 0 is bound to the driver (e.g.,
via the `new_id` sysfs interface), `pcim_iomap_region()` successfully maps
it and returns an I/O port cookie. The driver then attempts to read from
this address using MMIO accessors like `readw()`, which directly
dereferences the pointer. On x86, this results in a supervisor read access
page fault:

BUG: unable to handle page fault for address: 000000000001c094
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
RIP: 0010:readw arch/x86/include/asm/io.h:58 [inline]
RIP: 0010:snd_hdac_reg_readw include/sound/hdaudio.h:458 [inline]
RIP: 0010:snd_hdac_bus_parse_capabilities+0x47/0x750
sound/hda/core/controller.c:412
Call Trace:
 azx_first_init sound/hda/controllers/intel.c:1936 [inline]
 azx_probe_continue sound/hda/controllers/intel.c:2365 [inline]
 azx_probe_work+0x85e/0x2860 sound/hda/controllers/intel.c:1737

To fix this issue, verify that the BAR is an MMIO region using
`pci_resource_is_mem()` before attempting to map it. If the BAR is not an
MMIO region, log an error and abort the probe process with `-ENXIO`.

A subsystem-wide audit revealed that several other ALSA PCI drivers use
`pcim_iomap_region()` and subsequently use MMIO accessors on the returned
pointer without validating the resource type. To ensure comprehensive
protection, apply the same validation pattern to all vulnerable ALSA PCI
drivers, including `snd_ad1889`, `snd_atiixp`, `snd_atiixp_modem`,
`snd_au88x0`, `snd_aw2`, `snd_bt87x`, `snd_cs4281`, `snd_cs5530`,
`snd_lola`, `snd_hdspm`, and `loongson_i2s_pci`.

Fixes: 3fcaf24e5dce ("ALSA: hda: Allocate resources with device-managed APIs")
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=10cd2d1efe8eeb604bee
Link: https://syzkaller.appspot.com/ai_job?id=dd4258ea-3be3-4977-b597-0fc0910b0f51
To: "Mark Brown" <[email protected]>
To: "Clemens Ladisch" <[email protected]>
To: "Liam Girdwood" <[email protected]>
To: <[email protected]>
To: <[email protected]>
To: "Jaroslav Kysela" <[email protected]>
To: "Takashi Iwai" <[email protected]>
To: "Binbin Zhou" <[email protected]>
To: "Takashi Iwai" <[email protected]>
Cc: "Chandra Mohan Sundar" <[email protected]>
Cc: "Kai Vehmanen" <[email protected]>
Cc: "Kees Cook" <[email protected]>
Cc: <[email protected]>
Cc: "Peter Ujfalusi" <[email protected]>
Cc: "Philipp Stanner" <[email protected]>
Cc: "Thomas Gleixner" <[email protected]>
Cc: =?utf-8?b?VXdlIEtsZWluZS1Lw7ZuaWcgKFRoZSBDYXBhYmxlIEh1Yik=?= <[email protected]>
Cc: "Haotian Zhang" <[email protected]>

---
diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c
index 28c55c5a2..22c2b5b42 100644
--- a/sound/hda/controllers/intel.c
+++ b/sound/hda/controllers/intel.c
@@ -1926,6 +1926,11 @@ static int azx_first_init(struct azx *chip)
 	if (chip->driver_type == AZX_DRIVER_ZHAOXINHDMI)
 		bus->polling_mode = 1;
 
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	bus->remap_addr = pcim_iomap_region(pci, 0, "ICH HD audio");
 	if (IS_ERR(bus->remap_addr))
 		return PTR_ERR(bus->remap_addr);
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index f4ec404c0..4f208f962 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -803,6 +803,11 @@ snd_ad1889_create(struct snd_card *card, struct pci_dev *pci)
 	chip->pci = pci;
 	chip->irq = -1;
 
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	/* (1) PCI resource allocation */
 	chip->iobase = pcim_iomap_region(pci, 0, card->driver);
 	if (IS_ERR(chip->iobase))
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index b738295b4..9b346b9b0 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1531,6 +1531,12 @@ static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
+
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	chip->remap_addr = pcim_iomap_region(pci, 0, "ATI IXP AC97");
 	if (IS_ERR(chip->remap_addr))
 		return PTR_ERR(chip->remap_addr);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 8aaeb197c..32a80297a 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1163,6 +1163,12 @@ static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
+
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	chip->remap_addr = pcim_iomap_region(pci, 0, "ATI IXP MC97");
 	if (IS_ERR(chip->remap_addr))
 		return PTR_ERR(chip->remap_addr);
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index bb0294579..9b2c9361a 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -157,6 +157,11 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci)
 	chip->card = card;
 	chip->irq = -1;
 
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	// (1) PCI resource allocation
 	// Get MMIO area
 	//
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 60a87322e..c9c7129e4 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -223,6 +223,11 @@ static int snd_aw2_create(struct snd_card *card,
 	chip->pci = pci;
 	chip->irq = -1;
 
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	/* (1) PCI resource allocation */
 	chip->iobase_virt = pcim_iomap_region(pci, 0, "Audiowerk2");
 	if (IS_ERR(chip->iobase_virt))
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 383def1f2..e71fe10ce 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -690,6 +690,11 @@ static int snd_bt87x_create(struct snd_card *card,
 	chip->irq = -1;
 	spin_lock_init(&chip->reg_lock);
 
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	chip->mmio = pcim_iomap_region(pci, 0, "Bt87x audio");
 	if (IS_ERR(chip->mmio))
 		return PTR_ERR(chip->mmio);
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index f51f4bb63..792a63d36 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1298,6 +1298,11 @@ static int snd_cs4281_create(struct snd_card *card,
 	}
 	chip->dual_codec = dual_codec;
 
+	if (!pci_resource_is_mem(pci, 0) || !pci_resource_is_mem(pci, 1)) {
+		dev_err(card->dev, "Invalid PCI BARs: not MMIO regions\n");
+		return -ENXIO;
+	}
+
 	chip->ba0 = pcim_iomap_region(pci, 0, "CS4281");
 	if (IS_ERR(chip->ba0))
 		return PTR_ERR(chip->ba0);
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index 292b65aa7..dc5e30947 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -91,6 +91,11 @@ static int snd_cs5530_create(struct snd_card *card,
 	chip->card = card;
 	chip->pci = pci;
 
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	mem = pcim_iomap_region(pci, 0, "CS5530");
 	if (IS_ERR(mem))
 		return PTR_ERR(mem);
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 34a3ba17d..fdef79879 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -579,6 +579,11 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
 		chip->sample_rate_min = 16000;
 	}
 
+	if (!pci_resource_is_mem(pci, 0) || !pci_resource_is_mem(pci, 2)) {
+		dev_err(card->dev, "Invalid PCI BARs: not MMIO regions\n");
+		return -ENXIO;
+	}
+
 	iomem = pcim_iomap_region(pci, 0, DRVNAME);
 	if (IS_ERR(iomem))
 		return PTR_ERR(iomem);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index d8bbedbc8..344008ff7 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6456,6 +6456,11 @@ static int snd_hdspm_create(struct snd_card *card,
 	int err;
 	unsigned long io_extent;
 
+	if (!pci_resource_is_mem(pci, 0)) {
+		dev_err(card->dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	hdspm->irq = -1;
 	hdspm->card = card;
 
diff --git a/sound/soc/loongson/loongson_i2s_pci.c b/sound/soc/loongson/loongson_i2s_pci.c
index f5b560465..5e634d467 100644
--- a/sound/soc/loongson/loongson_i2s_pci.c
+++ b/sound/soc/loongson/loongson_i2s_pci.c
@@ -41,6 +41,11 @@ static int loongson_i2s_pci_probe(struct pci_dev *pdev,
 	i2s->dev = dev;
 	pci_set_drvdata(pdev, i2s);
 
+	if (!pci_resource_is_mem(pdev, 0)) {
+		dev_err(dev, "Invalid PCI BAR 0: not an MMIO region\n");
+		return -ENXIO;
+	}
+
 	i2s->reg_base = pcim_iomap_region(pdev, 0, DRIVER_NAME);
 	if (IS_ERR(i2s->reg_base)) {
 		dev_err(dev, "iomap_region failed\n");


base-commit: db2ddb87143519e20a95aa36c60b36107b736a58
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at [email protected].
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.