Reviewed-by: Lyude Paul <[email protected]> Will push to drm-misc-fixes in just a moment, thank you for the fixes!
On Fri, 2026-09-18 at 15:16 +0200, Francesco Magazzu wrote: > From: Dan Carpenter <[email protected]> > > If list_for_each_entry() exits without hitting a break then "pstate" > is > not a valid pstate pointer. Introduce a "found" variable instead. > > The check is reachable from userspace: nvkm_clk_ustate_update() takes > the > pstate id straight from the 'pstate' debugfs file, so requesting an > id > that is not in clk->states - or any id at all when the perf tables > are > broken and the list is empty - makes the pstate->pstate != req test > dereference the list head cast to a struct nvkm_pstate, which is an > out-of-bounds read. > > Fixes: 7c8565220697 ("drm/nouveau/clk: implement power state and > engine clock control in core") > Signed-off-by: Dan Carpenter <[email protected]> > [Francesco: rebased on drm-misc-next, expanded the commit message] > Signed-off-by: Francesco Magazzu <[email protected]> > --- > This is Dan's 2022 patch, reposted with his authorship restored as > asked > in the review of v2. The diff is byte for byte what he sent; the > commit > message keeps his original two sentences and adds a paragraph on how > the > check is reached from userspace. > Link: https://lore.kernel.org/dri-devel/YvSkKAdk8Pe0g2K9@kili/ > > drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 7 +++++-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c > b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c > index 572e63846..5da82db71 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c > @@ -473,6 +473,7 @@ static int > nvkm_clk_ustate_update(struct nvkm_clk *clk, int req) > { > struct nvkm_pstate *pstate; > + bool found = false; > int i = 0; > > if (!clk->allow_reclock) > @@ -480,12 +481,14 @@ nvkm_clk_ustate_update(struct nvkm_clk *clk, > int req) > > if (req != -1 && req != -2) { > list_for_each_entry(pstate, &clk->states, head) { > - if (pstate->pstate == req) > + if (pstate->pstate == req) { > + found = true; > break; > + } > i++; > } > > - if (pstate->pstate != req) > + if (!found) > return -EINVAL; > req = i; > }
