On 24/04/2025 11:38 am, Roger Pau Monne wrote:
> There's an off-by-one when calculating the last byte in the input array to
> bitmap_to_xenctl_bitmap(), which leads to bitmaps with sizes multiple of 8
> to over-read and incorrectly use a byte past the end of the array.

/sigh

> While there also ensure that bitmap_to_xenctl_bitmap() is not called with a
> bitmap of 0 length.
>
> Fixes: 288c4641c80d ('xen: simplify bitmap_to_xenctl_bitmap for little 
> endian')
> Signed-off-by: Roger Pau Monné <roger....@citrix.com>

You ought to note that this is only not getting an XSA because
288c4641c80d isn't in a released Xen yet.

> ---
>  xen/common/bitmap.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/xen/common/bitmap.c b/xen/common/bitmap.c
> index bf1a7fd91e36..415d6bc074f6 100644
> --- a/xen/common/bitmap.c
> +++ b/xen/common/bitmap.c
> @@ -369,6 +369,12 @@ int bitmap_to_xenctl_bitmap(struct xenctl_bitmap 
> *xenctl_bitmap,
>      const uint8_t *bytemap;
>      uint8_t last, *buf = NULL;
>  
> +    if ( !nbits )
> +    {
> +     ASSERT_UNREACHABLE();
> +     return -EILSEQ;
> +    }

I don't see any hypercalls performing a bits==0 check, so I expect this
is reachable.

> +
>      if ( !IS_ENABLED(LITTLE_ENDIAN) )
>      {
>          buf = xmalloc_array(uint8_t, xen_bytes);
> @@ -396,7 +402,7 @@ int bitmap_to_xenctl_bitmap(struct xenctl_bitmap 
> *xenctl_bitmap,
>       * their loops to 8 bits. Ensure we clear those left over bits so as to
>       * prevent surprises.
>       */
> -    last = bytemap[nbits / 8];
> +    last = bytemap[(nbits - 1) / 8];
>      if ( nbits % 8 )
>          last &= (1U << (nbits % 8)) - 1;
>  

This (preexisting) logic is mad.  The overwhelming majority of cases are
going to be a multiple of 8, and as you notice, the 0 case can't be
fixed like this.

It should all be inside a copy_bytes conditional as is done in
xenctl_bitmap_to_bitmap().

~Andrew

Reply via email to