]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dmaengine: pxa_dma: Annotate struct pxad_desc_sw with __counted_by
authorChristophe JAILLET <christophe.jaillet@wanadoo.fr>
Sat, 7 Oct 2023 11:13:10 +0000 (13:13 +0200)
committerVinod Koul <vkoul@kernel.org>
Mon, 9 Oct 2023 05:17:26 +0000 (10:47 +0530)
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>
drivers/dma/pxa_dma.c

index 94cef2905940f9a982abc519115229bdde2f775b..c6e2862896e317d22915f55f3714661d614de8b5 100644 (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;