diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2018-04-10 09:21:44 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-04-26 04:35:04 -0400 |
commit | 6a7228d90d42bcacfe38786756ba62762b91c20a (patch) | |
tree | 16f072e45e22a3ccbc94ae82b9deafa9e28e0ea7 | |
parent | 5f53624662eaac89598641cee6cd54fc192572d9 (diff) |
ARM: amba: Fix race condition with driver_override
The driver_override implementation is susceptible to a race condition
when different threads are reading vs storing a different driver
override. Add locking to avoid this race condition.
Cfr. commits 6265539776a0810b ("driver core: platform: fix race
condition with driver_override") and 9561475db680f714 ("PCI: Fix race
condition with driver_override").
Fixes: 3cf385713460eb2b ("ARM: 8256/1: driver coamba: add device binding path 'driver_override'")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Todd Kjos <tkjos@google.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/amba/bus.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index f8c01fbef64d..4a3ac31c07d0 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -69,8 +69,12 @@ static ssize_t driver_override_show(struct device *_dev, | |||
69 | struct device_attribute *attr, char *buf) | 69 | struct device_attribute *attr, char *buf) |
70 | { | 70 | { |
71 | struct amba_device *dev = to_amba_device(_dev); | 71 | struct amba_device *dev = to_amba_device(_dev); |
72 | ssize_t len; | ||
72 | 73 | ||
73 | return sprintf(buf, "%s\n", dev->driver_override); | 74 | device_lock(_dev); |
75 | len = sprintf(buf, "%s\n", dev->driver_override); | ||
76 | device_unlock(_dev); | ||
77 | return len; | ||
74 | } | 78 | } |
75 | 79 | ||
76 | static ssize_t driver_override_store(struct device *_dev, | 80 | static ssize_t driver_override_store(struct device *_dev, |
@@ -78,7 +82,7 @@ static ssize_t driver_override_store(struct device *_dev, | |||
78 | const char *buf, size_t count) | 82 | const char *buf, size_t count) |
79 | { | 83 | { |
80 | struct amba_device *dev = to_amba_device(_dev); | 84 | struct amba_device *dev = to_amba_device(_dev); |
81 | char *driver_override, *old = dev->driver_override, *cp; | 85 | char *driver_override, *old, *cp; |
82 | 86 | ||
83 | /* We need to keep extra room for a newline */ | 87 | /* We need to keep extra room for a newline */ |
84 | if (count >= (PAGE_SIZE - 1)) | 88 | if (count >= (PAGE_SIZE - 1)) |
@@ -92,12 +96,15 @@ static ssize_t driver_override_store(struct device *_dev, | |||
92 | if (cp) | 96 | if (cp) |
93 | *cp = '\0'; | 97 | *cp = '\0'; |
94 | 98 | ||
99 | device_lock(_dev); | ||
100 | old = dev->driver_override; | ||
95 | if (strlen(driver_override)) { | 101 | if (strlen(driver_override)) { |
96 | dev->driver_override = driver_override; | 102 | dev->driver_override = driver_override; |
97 | } else { | 103 | } else { |
98 | kfree(driver_override); | 104 | kfree(driver_override); |
99 | dev->driver_override = NULL; | 105 | dev->driver_override = NULL; |
100 | } | 106 | } |
107 | device_unlock(_dev); | ||
101 | 108 | ||
102 | kfree(old); | 109 | kfree(old); |
103 | 110 | ||