hwmon: (amc6821) Fix possible race condition bug
authorAxel Lin <axel.lin@ingics.com>
Thu, 31 Jul 2014 01:43:19 +0000 (09:43 +0800)
committerBen Hutchings <ben@decadent.org.uk>
Sat, 13 Sep 2014 22:41:41 +0000 (23:41 +0100)
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: Ben Hutchings <ben@decadent.org.uk>
drivers/hwmon/amc6821.c

index cd6bead..b7f3356 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;
 }
@@ -495,8 +498,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] = SENSORS_LIMIT(val / 1000, 0,
@@ -669,13 +673,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;