dmaengine: pxa_dma: Annotate struct pxad_desc_sw with __counted_by

Prepare for the coming implementation by GCC and Clang of the __counted_by
attribute. Flexible array members annotated with __counted_by can have
their accesses bounds-checked at run-time checking via CONFIG_UBSAN_BOUNDS
(for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family
functions).

To do so, the code needs a little shuffling related to how hw_desc is used
and nb_desc incremented.

The one by one increment is needed for the error handling path, calling
pxad_free_desc(), to work correctly.

So, add a new intermediate variable, desc, to store the result of the
dma_pool_alloc() call.

Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Reviewed-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/1c9ef22826f449a3756bb13a83494e9fe3e0be8b.1696676782.git.christophe.jaillet@wanadoo.fr
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Christophe JAILLET 2023-10-07 13:13:10 +02:00 committed by Vinod Koul
parent 83c761f568
commit 0481291f0c

View file

@ -91,7 +91,8 @@ struct pxad_desc_sw {
bool cyclic;
struct dma_pool *desc_pool; /* Channel's used allocator */
struct pxad_desc_hw *hw_desc[]; /* DMA coherent descriptors */
struct pxad_desc_hw *hw_desc[] __counted_by(nb_desc);
/* DMA coherent descriptors */
};
struct pxad_phy {
@ -739,6 +740,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
{
struct pxad_desc_sw *sw_desc;
dma_addr_t dma;
void *desc;
int i;
sw_desc = kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc),
@ -748,20 +750,21 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
sw_desc->desc_pool = chan->desc_pool;
for (i = 0; i < nb_hw_desc; i++) {
sw_desc->hw_desc[i] = dma_pool_alloc(sw_desc->desc_pool,
GFP_NOWAIT, &dma);
if (!sw_desc->hw_desc[i]) {
desc = dma_pool_alloc(sw_desc->desc_pool, GFP_NOWAIT, &dma);
if (!desc) {
dev_err(&chan->vc.chan.dev->device,
"%s(): Couldn't allocate the %dth hw_desc from dma_pool %p\n",
__func__, i, sw_desc->desc_pool);
goto err;
}
sw_desc->nb_desc++;
sw_desc->hw_desc[i] = desc;
if (i == 0)
sw_desc->first = dma;
else
sw_desc->hw_desc[i - 1]->ddadr = dma;
sw_desc->nb_desc++;
}
return sw_desc;