On 221015 1710, Chris Friedt wrote:
> From: Christopher Friedt <cfri...@meta.com>
> 
> In the case that size1 was zero, because of the explicit
> 'end1 > addr' check, the range check would fail and the error
> message would read as shown below. The correct comparison
> is 'end1 >= addr' (or 'addr <= end1').
> 
> EDU: DMA range 0x40000-0x3ffff out of bounds (0x40000-0x40fff)!
> 
> At the opposite end, in the case that size1 was 4096, within()
> would fail because of the non-inclusive check 'end1 < end2',
> which should have been 'end1 <= end2'. The error message would
> previously say
> 
> EDU: DMA range 0x40000-0x40fff out of bounds (0x40000-0x40fff)!
> 
> This change
> 1. renames local variables to be more less ambiguous
> 2. fixes the two off-by-one errors described above.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1254
> 
> Signed-off-by: Christopher Friedt <cfri...@meta.com>

Reviewed-by: Alexander Bulekov <alx...@bu.edu>

As a side-note, seems strange that edu_check_range will abort the entire
VM if the check fails, rather than handling the error more elegantly.
Maybe that's useful for students developing kernel drivers against the
device.

> ---
>  hw/misc/edu.c | 25 ++++++++++++-------------
>  1 file changed, 12 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/misc/edu.c b/hw/misc/edu.c
> index e935c418d4..52afbd792a 100644
> --- a/hw/misc/edu.c
> +++ b/hw/misc/edu.c
> @@ -103,25 +103,24 @@ static void edu_lower_irq(EduState *edu, uint32_t val)
>      }
>  }
>  
> -static bool within(uint64_t addr, uint64_t start, uint64_t end)
> +static void edu_check_range(uint64_t xfer_start, uint64_t xfer_size,
> +                uint64_t dma_start, uint64_t dma_size)
>  {
> -    return start <= addr && addr < end;
> -}
> -
> -static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start,
> -                uint64_t size2)
> -{
> -    uint64_t end1 = addr + size1;
> -    uint64_t end2 = start + size2;
> -
> -    if (within(addr, start, end2) &&
> -            end1 > addr && within(end1, start, end2)) {
> +    uint64_t xfer_end = xfer_start + xfer_size;
> +    uint64_t dma_end = dma_start + dma_size;
> +
> +    /*
> +     * 1. ensure we aren't overflowing
> +     * 2. ensure that xfer is within dma address range
> +     */
> +    if (dma_end >= dma_start && xfer_end >= xfer_start &&
> +        xfer_start >= dma_start && xfer_end <= dma_end) {
>          return;
>      }
>  
>      hw_error("EDU: DMA range 0x%016"PRIx64"-0x%016"PRIx64
>               " out of bounds (0x%016"PRIx64"-0x%016"PRIx64")!",
> -            addr, end1 - 1, start, end2 - 1);
> +            xfer_start, xfer_end - 1, dma_start, dma_end - 1);
>  }
>  
>  static dma_addr_t edu_clamp_addr(const EduState *edu, dma_addr_t addr)
> -- 
> 2.36.1
> 
> 

Reply via email to