Re: [PATCH 2/2] swiotlb: Enforce page alignment in swiotlb_alloc()

From: Will Deacon
Date: Mon Jan 29 2024 - 14:35:29 EST


On Fri, Jan 26, 2024 at 05:23:55PM +0100, Petr Tesařík wrote:
> On Fri, 26 Jan 2024 15:19:56 +0000
> Will Deacon <will@xxxxxxxxxx> wrote:
>
> > When allocating pages from a restricted DMA pool in swiotlb_alloc(),
> > the buffer address is blindly converted to a 'struct page *' that is
> > returned to the caller. In the unlikely event of an allocation bug,
> > page-unaligned addresses are not detected and slots can silently be
> > double-allocated.
> >
> > Add a simple check of the buffer alignment in swiotlb_alloc() to make
> > debugging a little easier if something has gone wonky.
> >
> > Cc: Christoph Hellwig <hch@xxxxxx>
> > Cc: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
> > Cc: Robin Murphy <robin.murphy@xxxxxxx>
> > Cc: Petr Tesarik <petr.tesarik1@xxxxxxxxxxxxxxxxxxx>
> > Cc: Dexuan Cui <decui@xxxxxxxxxxxxx>
> > Signed-off-by: Will Deacon <will@xxxxxxxxxx>
> > ---
> > kernel/dma/swiotlb.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
> > index 25febb9e670c..92433ea9f2d2 100644
> > --- a/kernel/dma/swiotlb.c
> > +++ b/kernel/dma/swiotlb.c
> > @@ -1647,6 +1647,12 @@ struct page *swiotlb_alloc(struct device *dev, size_t size)
> > return NULL;
> >
> > tlb_addr = slot_addr(pool->start, index);
> > + if (!PAGE_ALIGNED(tlb_addr)) {
> > + dev_WARN_ONCE(dev, 1, "Cannot return 'struct page *' for non page-aligned swiotlb addr 0x%pa.\n",
> > + &tlb_addr);
> > + swiotlb_release_slots(dev, tlb_addr);
> > + return NULL;
> > + }
>
> Is there a reason not to use BUG_ON()? If yes, I would at least go for:
>
> + if (unlikely(!PAGE_ALIGNED(tlb_addr))) {
>
> Other than that, yes, such cheap sanity checking looks like a good idea.

BUG_ON() is generally frowned upon unless there's really no way to proceed.
Since we can fail the allocation here, I think that's the best bet (and hope
that whoever wanted the buffer isn't all that important).

I'll add the unlikely() in v2, although it sounds like Christoph wants
this moving anyway.

Will