hwmon: (amc6821) Fix possible race condition bug
authorAxel Lin <axel.lin@ingics.com>
Thu, 31 Jul 2014 01:43:19 +0000 (09:43 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 5 Sep 2014 23:34:14 +0000 (16:34 -0700)
commit cf44819c98db11163f58f08b822d626c7a8f5188 upstream.

Ensure mutex lock protects the read-modify-write period to prevent possible
race condition bug.
In additional, update data->valid should also be protected by the mutex lock.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/hwmon/amc6821.c

index 9f2be3d..8a67ec6 100644 (file)
@@ -360,11 +360,13 @@ static ssize_t set_pwm1_enable(
        if (config)
                return config;
 
+       mutex_lock(&data->update_lock);
        config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
        if (config < 0) {
                        dev_err(&client->dev,
                        "Error reading configuration register, aborting.\n");
-                       return config;
+                       count = config;
+                       goto unlock;
        }
 
        switch (val) {
@@ -381,14 +383,15 @@ static ssize_t set_pwm1_enable(
                config |= AMC6821_CONF1_FDRC1;
                break;
        default:
-               return -EINVAL;
+               count = -EINVAL;
+               goto unlock;
        }
-       mutex_lock(&data->update_lock);
        if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
                        dev_err(&client->dev,
                        "Configuration register write error, aborting.\n");
                        count = -EIO;
        }
+unlock:
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -493,8 +496,9 @@ static ssize_t set_temp_auto_point_temp(
                return -EINVAL;
        }
 
-       data->valid = 0;
        mutex_lock(&data->update_lock);
+       data->valid = 0;
+
        switch (ix) {
        case 0:
                ptemp[0] = clamp_val(val / 1000, 0,
@@ -658,13 +662,14 @@ static ssize_t set_fan1_div(
        if (config)
                return config;
 
+       mutex_lock(&data->update_lock);
        config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
        if (config < 0) {
                dev_err(&client->dev,
                        "Error reading configuration register, aborting.\n");
-               return config;
+               count = config;
+               goto EXIT;
        }
-       mutex_lock(&data->update_lock);
        switch (val) {
        case 2:
                config &= ~AMC6821_CONF4_PSPR;