summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2023-09-20 11:09:10 -0700
committerLinus Walleij <linus.walleij@linaro.org>2023-09-25 15:29:26 +0200
commitc153a4edff6ab01370fcac8e46f9c89cca1060c2 (patch)
tree168e8a4030c9a649143f4fce5ec889c300d80c9b /drivers/pinctrl
parent64061b67335e958e6328bcb5bb2b5490d57f3f59 (diff)
downloadlinux-stable-c153a4edff6ab01370fcac8e46f9c89cca1060c2.tar.gz
linux-stable-c153a4edff6ab01370fcac8e46f9c89cca1060c2.tar.bz2
linux-stable-c153a4edff6ab01370fcac8e46f9c89cca1060c2.zip
pinctrl: avoid unsafe code pattern in find_pinctrl()
The code in find_pinctrl() takes a mutex and traverses a list of pinctrl structures. Later the caller bumps up reference count on the found structure. Such pattern is not safe as pinctrl that was found may get deleted before the caller gets around to increasing the reference count. Fix this by taking the reference count in find_pinctrl(), while it still holds the mutex. Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Link: https://lore.kernel.org/r/ZQs1RgTKg6VJqmPs@google.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/core.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index e9dc9638120a..e2f7519bef04 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1022,17 +1022,20 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev,
static struct pinctrl *find_pinctrl(struct device *dev)
{
- struct pinctrl *p;
+ struct pinctrl *entry, *p = NULL;
mutex_lock(&pinctrl_list_mutex);
- list_for_each_entry(p, &pinctrl_list, node)
- if (p->dev == dev) {
- mutex_unlock(&pinctrl_list_mutex);
- return p;
+
+ list_for_each_entry(entry, &pinctrl_list, node) {
+ if (entry->dev == dev) {
+ p = entry;
+ kref_get(&p->users);
+ break;
}
+ }
mutex_unlock(&pinctrl_list_mutex);
- return NULL;
+ return p;
}
static void pinctrl_free(struct pinctrl *p, bool inlist);
@@ -1140,7 +1143,6 @@ struct pinctrl *pinctrl_get(struct device *dev)
p = find_pinctrl(dev);
if (p) {
dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
- kref_get(&p->users);
return p;
}