On Sat, Jul 11, 2026 at 11:06:28AM -0400, Michael Bommarito wrote:
> mana_hwc_init_event_handler() in hw_channel.c stores device-advertised
> HWC_INIT_DATA_MAX_REQUEST and HWC_INIT_DATA_MAX_RESPONSE values
> without bounds checking. mana_hwc_alloc_dma_buf() later computes the
> DMA buffer size as MANA_PAGE_ALIGN(q_depth * max_msg_size) in 32-bit
> arithmetic. A malicious device returning a large max_msg_size causes
> the product to wrap, allocating a small buffer while laying out
> q_depth request slots at the unwrapped stride, placing slots outside
> the allocation.

I don't think the described data flow actually
exists in the current tree, so the security framing looks inaccurate.
Please check the comment below.
> 
> Impact: a compromised hypervisor device model or malicious MANA PCI
> device can cause out-of-bounds DMA buffer writes during HWC channel
> initialization. A reproducer is available on request.
> 
> Clamp both values to HW_CHANNEL_MAX_REQUEST_SIZE (4096), consistent
> with the cap already applied at the channel-create callsite.
> 
> Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network 
> Adapter (MANA)")
> Cc: [email protected]
> Assisted-by: Claude:claude-opus-4-7
> Signed-off-by: Michael Bommarito <[email protected]>
> ---
>  drivers/net/ethernet/microsoft/mana/hw_channel.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c 
> b/drivers/net/ethernet/microsoft/mana/hw_channel.c
> index 48a9acea4ab6c..a0916b50cffce 100644
> --- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
> +++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
> @@ -152,10 +152,14 @@ static void mana_hwc_init_event_handler(void *ctx, 
> struct gdma_queue *q_self,
>                       break;
>  
>               case HWC_INIT_DATA_MAX_REQUEST:
> +                     if (val == 0 || val > HW_CHANNEL_MAX_REQUEST_SIZE)
> +                             val = HW_CHANNEL_MAX_REQUEST_SIZE;
>                       hwc->hwc_init_max_req_msg_size = val;
>                       break;
>  
>               case HWC_INIT_DATA_MAX_RESPONSE:
> +                     if (val == 0 || val > HW_CHANNEL_MAX_REQUEST_SIZE)
> +                             val = HW_CHANNEL_MAX_REQUEST_SIZE;
>                       hwc->hwc_init_max_resp_msg_size = val;
>                       break;
>  

The clamp is applied to hwc->hwc_init_max_req_msg_size and
hwc->hwc_init_max_resp_msg_size. Tracing where those two fields are
consumed:

  mana_hwc_init_event_handler()
        |
  mana_hwc_establish_channel() // copies them out to *max_req_msg_size
        |                          and *max_resp_msg_size
  mana_hwc_create_channel()    // passes those locals only to
        |                          mana_hwc_test_channel()
  mana_hwc_test_channel()      // passed as parameters but never
                                   used them

The DMA buffers that alloc_dma_buf() sizes are created from
mana_hwc_init_queues(), which is called with the compile-time constants:

    err = mana_hwc_init_queues(hwc, HW_CHANNEL_VF_BOOTSTRAP_QUEUE_DEPTH,
                   HW_CHANNEL_MAX_REQUEST_SIZE,
                   HW_CHANNEL_MAX_RESPONSE_SIZE);

Therefore, q_depth * max_msg_size cannot wrap from a device-controlled
value here.

Thanks,
Vennela
> -- 
> 2.53.0
> 

> 

Reply via email to