Skip to content

Commit

Permalink
pinctrl: avoid unsafe code pattern in find_pinctrl()
Browse files Browse the repository at this point in the history
commit c153a4e 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: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Link: https://lore.kernel.org/r/ZQs1RgTKg6VJqmPs@google.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
dtor authored and gregkh committed Oct 19, 2023
1 parent d67b5a2 commit 97306ab
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions drivers/pinctrl/core.c
Expand Up @@ -1007,17 +1007,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);
Expand Down Expand Up @@ -1126,7 +1129,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;
}

Expand Down

0 comments on commit 97306ab

Please sign in to comment.