|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] xen: fix buffer over-read in bitmap_to_xenctl_bitmap()
On Thu, Apr 24, 2025 at 12:41:43PM +0100, Andrew Cooper wrote:
> 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.pau@xxxxxxxxxx>
>
> You ought to note that this is only not getting an XSA because
> 288c4641c80d isn't in a released Xen yet.
Yeah, I did explicitly check this wasn't backported to any stable
branches.
> > ---
> > 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.
bitmap_to_xenctl_bitmap() has just two callers, one passes nr_cpu_ids,
the other MAX_NUMNODES. I think there are no callers that pass 0,
much less from hypercall provided values.
> > +
> > 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's indeed a weird logic. The usage of last should be restricted to
nbits % 8 != 0, and the rest of the cases handled directly by the
copy_to_guest() call above this logic.
> It should all be inside a copy_bytes conditional as is done in
> xenctl_bitmap_to_bitmap().
I could do it like that, but seeing the values passed by the only two
callers it seemed less churn to add early check and assert.
Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |