[PATCH] hw/pci-host/pnv_phb4: fix guest-triggerable abort on 8-byte config access

Nikhil Kumar Singh posted 1 patch 2 weeks, 5 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260805090530.1333997-1-nikhilks@linux.ibm.com
Maintainers: Nicholas Piggin <npiggin@gmail.com>, Aditya Gupta <adityag@linux.ibm.com>, Glenn Miles <milesg@linux.ibm.com>, Harsh Prateek Bora <harshpb@linux.ibm.com>
hw/pci-host/pnv_phb4.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
[PATCH] hw/pci-host/pnv_phb4: fix guest-triggerable abort on 8-byte config access
Posted by Nikhil Kumar Singh 2 weeks, 5 days ago
A guest-triggerable assertion crash (DoS) exists in pnv_phb4_config_write()
and pnv_phb4_config_read(). When a guest performs an 8-byte access to
PHB_CONFIG_DATA (offset 0x130), QEMU aborts because the switch(size)
statement in the config accessors only handles 1, 2, and 4-byte accesses,
hitting g_assert_not_reached() in the default case.

Since guest input is untrusted, an invalid access size should not crash
the host. Fix this by adding a size > 4 guard in pnv_phb4_reg_write() and
pnv_phb4_reg_read() before the config accessor calls, and by replacing
the g_assert_not_reached() in pnv_phb4_config_write() and
pnv_phb4_config_read() with phb_error() to cover any other callers.
Invalid reads now return ~0ull, maintaining PCI conventions.

Fixes: 4f9924c4d4cf ("ppc/pnv: Add models for POWER9 PHB4 PCIe Host bridge")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3591
Signed-off-by: Nikhil Kumar Singh <nikhilks@linux.ibm.com>
---
 hw/pci-host/pnv_phb4.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c
index 705a5bcf07..02ca2f978c 100644
--- a/hw/pci-host/pnv_phb4.c
+++ b/hw/pci-host/pnv_phb4.c
@@ -84,7 +84,9 @@ static void pnv_phb4_config_write(PnvPHB4 *phb, unsigned off,
         val = bswap32(val);
         break;
     default:
-        g_assert_not_reached();
+        phb_error(phb, "invalid config write size %u at offset 0x%x\n",
+                  size, off);
+        return;
     }
     pci_host_config_write_common(pdev, cfg_addr, limit, val, size);
 }
@@ -119,7 +121,9 @@ static uint64_t pnv_phb4_config_read(PnvPHB4 *phb, unsigned off,
     case 4:
         return bswap32(val);
     default:
-        g_assert_not_reached();
+        phb_error(phb, "invalid config read size %u at offset 0x%x\n",
+                  size, off);
+        return ~0ull;
     }
 }
 
@@ -507,6 +511,11 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
 
     /* Special case outbound configuration data */
     if ((off & 0xfffc) == PHB_CONFIG_DATA) {
+        if (size > 4) {
+            phb_error(phb, "invalid config write size %u at 0x%"PRIx64"\n",
+                      size, off);
+            return;
+        }
         pnv_phb4_config_write(phb, off & 0x3, size, val);
         return;
     }
@@ -644,6 +653,11 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
     uint64_t val;
 
     if ((off & 0xfffc) == PHB_CONFIG_DATA) {
+        if (size > 4) {
+            phb_error(phb, "invalid config read size %u at 0x%"PRIx64"\n",
+                      size, off);
+            return ~0ull;
+        }
         return pnv_phb4_config_read(phb, off & 0x3, size);
     }
 
-- 
2.54.0
Re: [PATCH] hw/pci-host/pnv_phb4: fix guest-triggerable abort on 8-byte config access
Posted by Philippe Mathieu-Daudé 2 weeks, 5 days ago
Hi,

On 5/8/26 11:05, Nikhil Kumar Singh wrote:
> A guest-triggerable assertion crash (DoS) exists in pnv_phb4_config_write()
> and pnv_phb4_config_read(). When a guest performs an 8-byte access to
> PHB_CONFIG_DATA (offset 0x130), QEMU aborts because the switch(size)
> statement in the config accessors only handles 1, 2, and 4-byte accesses,
> hitting g_assert_not_reached() in the default case.
> 
> Since guest input is untrusted, an invalid access size should not crash
> the host. Fix this by adding a size > 4 guard in pnv_phb4_reg_write() and
> pnv_phb4_reg_read() before the config accessor calls, and by replacing
> the g_assert_not_reached() in pnv_phb4_config_write() and
> pnv_phb4_config_read() with phb_error() to cover any other callers.
> Invalid reads now return ~0ull, maintaining PCI conventions.
> 
> Fixes: 4f9924c4d4cf ("ppc/pnv: Add models for POWER9 PHB4 PCIe Host bridge")
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3591
> Signed-off-by: Nikhil Kumar Singh <nikhilks@linux.ibm.com>
> ---
>   hw/pci-host/pnv_phb4.c | 18 ++++++++++++++++--
>   1 file changed, 16 insertions(+), 2 deletions(-)


> @@ -507,6 +511,11 @@ static void pnv_phb4_reg_write(void *opaque, hwaddr off, uint64_t val,
>   
>       /* Special case outbound configuration data */
>       if ((off & 0xfffc) == PHB_CONFIG_DATA) {
> +        if (size > 4) {
> +            phb_error(phb, "invalid config write size %u at 0x%"PRIx64"\n",
> +                      size, off);
> +            return;
> +        }
>           pnv_phb4_config_write(phb, off & 0x3, size, val);

Alternatively MIN(size, 4).

But without looking much at this model, I'd expect these regions to
be mapped as the usual "pci-conf-idx" / "pci-data-idx" ones (FYI see
pci_host_conf_le_ops and pci_host_data_le_ops).

Anyway my 2 cents, since this involves more of "silence that DoS".

>           return;
>       }
> @@ -644,6 +653,11 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size)
>       uint64_t val;
>   
>       if ((off & 0xfffc) == PHB_CONFIG_DATA) {
> +        if (size > 4) {
> +            phb_error(phb, "invalid config read size %u at 0x%"PRIx64"\n",
> +                      size, off);
> +            return ~0ull;
> +        }
>           return pnv_phb4_config_read(phb, off & 0x3, size);
>       }
>
Re: [PATCH] hw/pci-host/pnv_phb4: fix guest-triggerable abort on 8-byte config access
Posted by Nikhil Kumar Singh 2 weeks, 5 days ago
Hi Philippe,

Thanks for the review.

1. Regarding MIN(size, 4): I avoided this because silently truncating an 
8-byte guest read to 4 bytes leaves the upper 32 bits unpredictable, 
which might mask guest OS bugs. Returning ~0ull explicitly matches 
standard PCI behaviour for invalid reads and is safer.

2. Regarding pci_host_data_le_ops: I agree this is the right way to 
handle it. However, PHB_CONFIG_DATA is currently interleaved inside the 
larger big-endian PHB4 MMIO region. Moving it to generic little-endian 
ops requires a memory region refactor using overlays.

Since this patch addresses an immediate DoS crash, I kept the scope 
minimal. Memory region refactoring can be picked up as a separate 
follow-up patch.

Regards,
~ Nikhil
Re: [PATCH] hw/pci-host/pnv_phb4: fix guest-triggerable abort on 8-byte config access
Posted by Philippe Mathieu-Daudé 2 weeks, 5 days ago
On 5/8/26 15:53, Nikhil Kumar Singh wrote:
> Hi Philippe,
> 
> Thanks for the review.
> 
> 1. Regarding MIN(size, 4): I avoided this because silently truncating an 
> 8-byte guest read to 4 bytes leaves the upper 32 bits unpredictable, 
> which might mask guest OS bugs. Returning ~0ull explicitly matches 
> standard PCI behaviour for invalid reads and is safer.

OK.

> 2. Regarding pci_host_data_le_ops: I agree this is the right way to 
> handle it. However, PHB_CONFIG_DATA is currently interleaved inside the 
> larger big-endian PHB4 MMIO region. Moving it to generic little-endian 
> ops requires a memory region refactor using overlays.

Yeah, "if it ain't broke, don’t fix it", so let's keep maintaining
something old and different.

> Since this patch addresses an immediate DoS crash, I kept the scope 
> minimal.

OK, no objection to your patch, just my 2 cents ;)

> Memory region refactoring can be picked up as a separate 
> follow-up patch.
> 
> Regards,
> ~ Nikhil
> 


Re: [PATCH] hw/pci-host/pnv_phb4: fix guest-triggerable abort on 8-byte config access
Posted by Harsh Prateek Bora 1 day, 21 hours ago
+ Jishnu

Thanks Philippe for your inputs.

Hi Aditya,
Are we expecting a v2 or a follow-up patch here?
Needs your ack, thanks.

regards,
Harsh

On 05/08/26 9:23 pm, Philippe Mathieu-Daudé wrote:
> On 5/8/26 15:53, Nikhil Kumar Singh wrote:
>> Hi Philippe,
>>
>> Thanks for the review.
>>
>> 1. Regarding MIN(size, 4): I avoided this because silently truncating 
>> an 8-byte guest read to 4 bytes leaves the upper 32 bits 
>> unpredictable, which might mask guest OS bugs. Returning ~0ull 
>> explicitly matches standard PCI behaviour for invalid reads and is safer.
> 
> OK.
> 
>> 2. Regarding pci_host_data_le_ops: I agree this is the right way to 
>> handle it. However, PHB_CONFIG_DATA is currently interleaved inside 
>> the larger big-endian PHB4 MMIO region. Moving it to generic little- 
>> endian ops requires a memory region refactor using overlays.
> 
> Yeah, "if it ain't broke, don’t fix it", so let's keep maintaining
> something old and different.
> 
>> Since this patch addresses an immediate DoS crash, I kept the scope 
>> minimal.
> 
> OK, no objection to your patch, just my 2 cents ;)
> 
>> Memory region refactoring can be picked up as a separate follow-up patch.
>>
>> Regards,
>> ~ Nikhil
>>
>