]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ARM: amba: Fix race condition with driver_override
authorGeert Uytterhoeven <geert+renesas@glider.be>
Tue, 10 Apr 2018 13:21:44 +0000 (15:21 +0200)
committerSasha Levin <alexander.levin@microsoft.com>
Wed, 23 May 2018 01:36:39 +0000 (21:36 -0400)
[ Upstream commit 6b614a87f3f477571e319281e84dba11e0ea0a76 ]

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: Sasha Levin <alexander.levin@microsoft.com>
drivers/amba/bus.c

index 8bf4d39b082b9496160f4318c01d49b9e2aeeeea..13727fc250d5ed13add3e202e942b7a34a56e295 100644 (file)
@@ -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);