Reviewed-by: Lyude Paul <[email protected]>

On Sun, 2026-07-12 at 14:36 +0200, Francesco Magazzu wrote:
> nvkm_pstate_prog() walks clk->states looking for the entry at index
> 'pstatei' and then keeps using the list_for_each_entry cursor after
> the
> loop.  This is not triggerable today: every caller clamps the index
> against clk->state_nr before calling, so the loop always breaks on a
> real
> entry.  It is safe by virtue of what the callers happen to do, not by
> anything the function itself checks.
> 
> Should a caller ever pass an index that is not on the list, the
> cursor
> would point at the list head rather than at a pstate, and the
> pstate->base.domain[] and pstate->fanspeed accesses that follow would
> read
> past it.  Rather than leave that trap in place for the next caller,
> track
> whether the entry was found and return -EINVAL if it was not.
> 
> No functional change.
> 
> Signed-off-by: Francesco Magazzu <[email protected]>
> ---
>  drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
> b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
> index 42f3709e0..4d546b07f 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
> @@ -270,13 +270,19 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int
> pstatei)
>       struct nvkm_fb *fb = subdev->device->fb;
>       struct nvkm_pci *pci = subdev->device->pci;
>       struct nvkm_pstate *pstate;
> +     bool found = false;
>       int ret, idx = 0;
>  
>       list_for_each_entry(pstate, &clk->states, head) {
> -             if (idx++ == pstatei)
> +             if (idx++ == pstatei) {
> +                     found = true;
>                       break;
> +             }
>       }
>  
> +     if (!found)
> +             return -EINVAL;
> +
>       nvkm_debug(subdev, "setting performance state %d\n",
> pstatei);
>       clk->pstate = pstatei;
>  

Reply via email to