Skip to content
Snippets Groups Projects
Commit 93b384f1 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Frieder Schrempf
Browse files

pinctrl: avoid unsafe code pattern in find_pinctrl()


commit c153a4ed upstream.

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: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Link: https://lore.kernel.org/r/ZQs1RgTKg6VJqmPs@google.com


Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 882e3694
No related branches found
No related tags found
1 merge request!108🤖 Sync Bot: Update v5.4-ktn to Latest Stable Kernel (v5.4.259)
...@@ -1005,17 +1005,20 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev, ...@@ -1005,17 +1005,20 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev,
static struct pinctrl *find_pinctrl(struct device *dev) static struct pinctrl *find_pinctrl(struct device *dev)
{ {
struct pinctrl *p; struct pinctrl *entry, *p = NULL;
mutex_lock(&pinctrl_list_mutex); mutex_lock(&pinctrl_list_mutex);
list_for_each_entry(p, &pinctrl_list, node)
if (p->dev == dev) { list_for_each_entry(entry, &pinctrl_list, node) {
mutex_unlock(&pinctrl_list_mutex); if (entry->dev == dev) {
return p; p = entry;
kref_get(&p->users);
break;
} }
}
mutex_unlock(&pinctrl_list_mutex); mutex_unlock(&pinctrl_list_mutex);
return NULL; return p;
} }
static void pinctrl_free(struct pinctrl *p, bool inlist); static void pinctrl_free(struct pinctrl *p, bool inlist);
...@@ -1124,7 +1127,6 @@ struct pinctrl *pinctrl_get(struct device *dev) ...@@ -1124,7 +1127,6 @@ struct pinctrl *pinctrl_get(struct device *dev)
p = find_pinctrl(dev); p = find_pinctrl(dev);
if (p) { if (p) {
dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
kref_get(&p->users);
return p; return p;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment