There is a data race between the functions driver_override_show() and driver_override_store(). In the driver_override_store() function, the assignment to ret calls driver_set_override(), which frees the old value while writing the new value to dev. If a race occurs, it may cause a use-after-free (UAF) error in driver_override_show().
To fix this issue, we adopted a logic similar to the driver_override_show() function in vmbus_drv.c, where the dev is protected by a lock to prevent its value from changing.
This possible bug is found by an experimental static analysis tool developed by our team. This tool analyzes the locking APIs to extract function pairs that can be concurrently executed, and then analyzes the instructions in the paired functions to identify possible concurrency bugs including data races and atomicity violations.
Fixes: 1f86a00c1159 ("bus/fsl-mc: add support for 'driver_override' in the mc-bus") Cc: stable@vger.kernel.org Signed-off-by: Qiu-ji Chen chenqiuji666@gmail.com --- drivers/bus/fsl-mc/fsl-mc-bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 930d8a3ba722..62a9da88b4c9 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -201,8 +201,12 @@ static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + ssize_t len;
- return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); + device_lock(dev); + len = snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override); + device_unlock(dev); + return len; } static DEVICE_ATTR_RW(driver_override);