]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.297/pinctrl-avoid-unsafe-code-pattern-in-find_pinctrl.patch
6.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.19.297 / pinctrl-avoid-unsafe-code-pattern-in-find_pinctrl.patch
1 From c153a4edff6ab01370fcac8e46f9c89cca1060c2 Mon Sep 17 00:00:00 2001
2 From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
3 Date: Wed, 20 Sep 2023 11:09:10 -0700
4 Subject: pinctrl: avoid unsafe code pattern in find_pinctrl()
5
6 From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
7
8 commit c153a4edff6ab01370fcac8e46f9c89cca1060c2 upstream.
9
10 The code in find_pinctrl() takes a mutex and traverses a list of pinctrl
11 structures. Later the caller bumps up reference count on the found
12 structure. Such pattern is not safe as pinctrl that was found may get
13 deleted before the caller gets around to increasing the reference count.
14
15 Fix this by taking the reference count in find_pinctrl(), while it still
16 holds the mutex.
17
18 Cc: stable@vger.kernel.org
19 Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
20 Link: https://lore.kernel.org/r/ZQs1RgTKg6VJqmPs@google.com
21 Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
22 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23 ---
24 drivers/pinctrl/core.c | 16 +++++++++-------
25 1 file changed, 9 insertions(+), 7 deletions(-)
26
27 --- a/drivers/pinctrl/core.c
28 +++ b/drivers/pinctrl/core.c
29 @@ -1001,17 +1001,20 @@ static int add_setting(struct pinctrl *p
30
31 static struct pinctrl *find_pinctrl(struct device *dev)
32 {
33 - struct pinctrl *p;
34 + struct pinctrl *entry, *p = NULL;
35
36 mutex_lock(&pinctrl_list_mutex);
37 - list_for_each_entry(p, &pinctrl_list, node)
38 - if (p->dev == dev) {
39 - mutex_unlock(&pinctrl_list_mutex);
40 - return p;
41 +
42 + list_for_each_entry(entry, &pinctrl_list, node) {
43 + if (entry->dev == dev) {
44 + p = entry;
45 + kref_get(&p->users);
46 + break;
47 }
48 + }
49
50 mutex_unlock(&pinctrl_list_mutex);
51 - return NULL;
52 + return p;
53 }
54
55 static void pinctrl_free(struct pinctrl *p, bool inlist);
56 @@ -1120,7 +1123,6 @@ struct pinctrl *pinctrl_get(struct devic
57 p = find_pinctrl(dev);
58 if (p) {
59 dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
60 - kref_get(&p->users);
61 return p;
62 }
63