Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clkdev: Hold clocks_mutex while iterating clocks list

We recently introduced a change to support devm clk lookups. That change
introduced a code-path that used clk_find() without holding the
'clocks_mutex'. Unfortunately, clk_find() iterates over the 'clocks'
list and so we need to prevent the list from being modified at the same
time. Do this by holding the mutex and checking to make sure it's held
while iterating the list.

Note, we don't really care if the lookup is freed after we find it with
clk_find() because we're just doing a pointer comparison, but if we did
care we would need to keep holding the mutex while we dereference the
clk_lookup pointer.

Fixes: 3eee6c7d119c ("clkdev: add managed clkdev lookup registration")
Cc: Miquel Raynal <miquel.raynal@bootlin.com>
Cc: Jerome Brunet <jbrunet@baylibre.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Jeffrey Hugo <jhugo@codeaurora.org>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Acked-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Tested-by: Jeffrey Hugo <jhugo@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

+5
+5
drivers/clk/clkdev.c
··· 46 46 if (con_id) 47 47 best_possible += 1; 48 48 49 + lockdep_assert_held(&clocks_mutex); 50 + 49 51 list_for_each_entry(p, &clocks, node) { 50 52 match = 0; 51 53 if (p->dev_id) { ··· 404 402 struct clk_lookup *cl; 405 403 int rval; 406 404 405 + mutex_lock(&clocks_mutex); 407 406 cl = clk_find(dev_id, con_id); 407 + mutex_unlock(&clocks_mutex); 408 + 408 409 WARN_ON(!cl); 409 410 rval = devres_release(dev, devm_clkdev_release, 410 411 devm_clk_match_clkdev, cl);