summaryrefslogtreecommitdiffstats
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
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>
-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;
}