From: Geert Uytterhoeven geert+renesas@glider.be
stable inclusion from stable-v6.6.9 commit 11dfea080f65a712f9f6e453badf27aefa2f2ba4 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8SU2D
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 4a6756f56bcf8e64c87144a626ce53aea4899c0e ]
When obtaining one or more optional resets, non-existent resets are stored as NULL pointers, and all related error and cleanup paths need to take this into account.
Currently only reset_control_put() and reset_control_bulk_put() get this right. All of __reset_control_bulk_get(), of_reset_control_array_get(), and reset_control_array_put() lack the proper checking, causing NULL pointer dereferences on failure or release.
Fix this by moving the existing check from reset_control_bulk_put() to __reset_control_put_internal(), so it applies to all callers. The double check in reset_control_put() doesn't hurt.
Fixes: 17c82e206d2a3cd8 ("reset: Add APIs to manage array of resets") Fixes: 48d71395896d54ee ("reset: Add reset_control_bulk API") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Link: https://lore.kernel.org/r/2440edae7ca8534628cdbaf559ded288f2998178.170127680... Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/reset/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/reset/core.c b/drivers/reset/core.c index f0a076e94118..92cc13ef3e56 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -807,6 +807,9 @@ static void __reset_control_put_internal(struct reset_control *rstc) { lockdep_assert_held(&reset_list_mutex);
+ if (IS_ERR_OR_NULL(rstc)) + return; + kref_put(&rstc->refcnt, __reset_control_release); }
@@ -1017,11 +1020,8 @@ EXPORT_SYMBOL_GPL(reset_control_put); void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) { mutex_lock(&reset_list_mutex); - while (num_rstcs--) { - if (IS_ERR_OR_NULL(rstcs[num_rstcs].rstc)) - continue; + while (num_rstcs--) __reset_control_put_internal(rstcs[num_rstcs].rstc); - } mutex_unlock(&reset_list_mutex); } EXPORT_SYMBOL_GPL(reset_control_bulk_put);