diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2018-04-10 15:21:44 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-05-02 07:53:42 -0700 |
commit | 7488404d3bab4eccb590c80c8827520394444630 (patch) | |
tree | c6768aa71f7f094bfca44590fa11d7d558041951 /drivers/amba | |
parent | 0448fd9403b4d77bd4aebc4e892db871d74850c8 (diff) |
ARM: amba: Fix race condition with driver_override
commit 6a7228d90d42bcacfe38786756ba62762b91c20a upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/amba')
-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 8bf4d39b082b..13727fc250d5 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -68,8 +68,12 @@ static ssize_t driver_override_show(struct device *_dev, struct device_attribute *attr, char *buf) { struct amba_device *dev = to_amba_device(_dev); + ssize_t len; - return sprintf(buf, "%s\n", dev->driver_override); + device_lock(_dev); + len = sprintf(buf, "%s\n", dev->driver_override); + device_unlock(_dev); + return len; } static ssize_t driver_override_store(struct device *_dev, @@ -77,7 +81,7 @@ static ssize_t driver_override_store(struct device *_dev, const char *buf, size_t count) { struct amba_device *dev = to_amba_device(_dev); - char *driver_override, *old = dev->driver_override, *cp; + char *driver_override, *old, *cp; if (count > PATH_MAX) return -EINVAL; @@ -90,12 +94,15 @@ static ssize_t driver_override_store(struct device *_dev, if (cp) *cp = '\0'; + device_lock(_dev); + old = dev->driver_override; if (strlen(driver_override)) { dev->driver_override = driver_override; } else { kfree(driver_override); dev->driver_override = NULL; } + device_unlock(_dev); kfree(old); |