diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2008-11-12 16:26:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-12 20:17:17 -0500 |
commit | 862343c4ea2ece307f25db1812637cff142d3263 (patch) | |
tree | 2a15fc50b2ff1b9542c6af34b2a864c678080344 | |
parent | 05a9bd46e49a9cbb09a0c61c901642a9911bf56e (diff) |
adt7473: check inputs from sysfs writes
Implement correct range checking for adt7470 to prevent userland from
writing impossible values into the chip, and cap out-of-range values per
standard hwmon conventions.
Implement correct rounding of input values per standard hwmon conventions.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/hwmon/adt7473.c | 89 |
1 files changed, 74 insertions, 15 deletions
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c index b9a8ea30c99c..18aa30866a6c 100644 --- a/drivers/hwmon/adt7473.c +++ b/drivers/hwmon/adt7473.c | |||
@@ -129,6 +129,8 @@ I2C_CLIENT_INSMOD_1(adt7473); | |||
129 | #define FAN_PERIOD_INVALID 65535 | 129 | #define FAN_PERIOD_INVALID 65535 |
130 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | 130 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) |
131 | 131 | ||
132 | #define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) | ||
133 | |||
132 | struct adt7473_data { | 134 | struct adt7473_data { |
133 | struct device *hwmon_dev; | 135 | struct device *hwmon_dev; |
134 | struct attribute_group attrs; | 136 | struct attribute_group attrs; |
@@ -357,7 +359,12 @@ static ssize_t set_volt_min(struct device *dev, | |||
357 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 359 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
358 | struct i2c_client *client = to_i2c_client(dev); | 360 | struct i2c_client *client = to_i2c_client(dev); |
359 | struct adt7473_data *data = i2c_get_clientdata(client); | 361 | struct adt7473_data *data = i2c_get_clientdata(client); |
360 | int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); | 362 | long volt; |
363 | |||
364 | if (strict_strtol(buf, 10, &volt)) | ||
365 | return -EINVAL; | ||
366 | |||
367 | volt = encode_volt(attr->index, volt); | ||
361 | 368 | ||
362 | mutex_lock(&data->lock); | 369 | mutex_lock(&data->lock); |
363 | data->volt_min[attr->index] = volt; | 370 | data->volt_min[attr->index] = volt; |
@@ -386,7 +393,12 @@ static ssize_t set_volt_max(struct device *dev, | |||
386 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 393 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
387 | struct i2c_client *client = to_i2c_client(dev); | 394 | struct i2c_client *client = to_i2c_client(dev); |
388 | struct adt7473_data *data = i2c_get_clientdata(client); | 395 | struct adt7473_data *data = i2c_get_clientdata(client); |
389 | int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); | 396 | long volt; |
397 | |||
398 | if (strict_strtol(buf, 10, &volt)) | ||
399 | return -EINVAL; | ||
400 | |||
401 | volt = encode_volt(attr->index, volt); | ||
390 | 402 | ||
391 | mutex_lock(&data->lock); | 403 | mutex_lock(&data->lock); |
392 | data->volt_max[attr->index] = volt; | 404 | data->volt_max[attr->index] = volt; |
@@ -419,7 +431,8 @@ static int decode_temp(u8 twos_complement, u8 raw) | |||
419 | 431 | ||
420 | static u8 encode_temp(u8 twos_complement, int cooked) | 432 | static u8 encode_temp(u8 twos_complement, int cooked) |
421 | { | 433 | { |
422 | return twos_complement ? cooked & 0xFF : cooked + 64; | 434 | u8 ret = twos_complement ? cooked & 0xFF : cooked + 64; |
435 | return SENSORS_LIMIT(ret, 0, 255); | ||
423 | } | 436 | } |
424 | 437 | ||
425 | static ssize_t show_temp_min(struct device *dev, | 438 | static ssize_t show_temp_min(struct device *dev, |
@@ -441,7 +454,12 @@ static ssize_t set_temp_min(struct device *dev, | |||
441 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 454 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
442 | struct i2c_client *client = to_i2c_client(dev); | 455 | struct i2c_client *client = to_i2c_client(dev); |
443 | struct adt7473_data *data = i2c_get_clientdata(client); | 456 | struct adt7473_data *data = i2c_get_clientdata(client); |
444 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 457 | long temp; |
458 | |||
459 | if (strict_strtol(buf, 10, &temp)) | ||
460 | return -EINVAL; | ||
461 | |||
462 | temp = ROUND_DIV(temp, 1000); | ||
445 | temp = encode_temp(data->temp_twos_complement, temp); | 463 | temp = encode_temp(data->temp_twos_complement, temp); |
446 | 464 | ||
447 | mutex_lock(&data->lock); | 465 | mutex_lock(&data->lock); |
@@ -472,7 +490,12 @@ static ssize_t set_temp_max(struct device *dev, | |||
472 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 490 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
473 | struct i2c_client *client = to_i2c_client(dev); | 491 | struct i2c_client *client = to_i2c_client(dev); |
474 | struct adt7473_data *data = i2c_get_clientdata(client); | 492 | struct adt7473_data *data = i2c_get_clientdata(client); |
475 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 493 | long temp; |
494 | |||
495 | if (strict_strtol(buf, 10, &temp)) | ||
496 | return -EINVAL; | ||
497 | |||
498 | temp = ROUND_DIV(temp, 1000); | ||
476 | temp = encode_temp(data->temp_twos_complement, temp); | 499 | temp = encode_temp(data->temp_twos_complement, temp); |
477 | 500 | ||
478 | mutex_lock(&data->lock); | 501 | mutex_lock(&data->lock); |
@@ -515,11 +538,13 @@ static ssize_t set_fan_min(struct device *dev, | |||
515 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 538 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
516 | struct i2c_client *client = to_i2c_client(dev); | 539 | struct i2c_client *client = to_i2c_client(dev); |
517 | struct adt7473_data *data = i2c_get_clientdata(client); | 540 | struct adt7473_data *data = i2c_get_clientdata(client); |
518 | int temp = simple_strtol(buf, NULL, 10); | 541 | long temp; |
519 | 542 | ||
520 | if (!temp) | 543 | if (strict_strtol(buf, 10, &temp) || !temp) |
521 | return -EINVAL; | 544 | return -EINVAL; |
545 | |||
522 | temp = FAN_RPM_TO_PERIOD(temp); | 546 | temp = FAN_RPM_TO_PERIOD(temp); |
547 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
523 | 548 | ||
524 | mutex_lock(&data->lock); | 549 | mutex_lock(&data->lock); |
525 | data->fan_min[attr->index] = temp; | 550 | data->fan_min[attr->index] = temp; |
@@ -558,7 +583,10 @@ static ssize_t set_max_duty_at_crit(struct device *dev, | |||
558 | u8 reg; | 583 | u8 reg; |
559 | struct i2c_client *client = to_i2c_client(dev); | 584 | struct i2c_client *client = to_i2c_client(dev); |
560 | struct adt7473_data *data = i2c_get_clientdata(client); | 585 | struct adt7473_data *data = i2c_get_clientdata(client); |
561 | int temp = simple_strtol(buf, NULL, 10); | 586 | long temp; |
587 | |||
588 | if (strict_strtol(buf, 10, &temp)) | ||
589 | return -EINVAL; | ||
562 | 590 | ||
563 | mutex_lock(&data->lock); | 591 | mutex_lock(&data->lock); |
564 | data->max_duty_at_overheat = !!temp; | 592 | data->max_duty_at_overheat = !!temp; |
@@ -587,7 +615,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | |||
587 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 615 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
588 | struct i2c_client *client = to_i2c_client(dev); | 616 | struct i2c_client *client = to_i2c_client(dev); |
589 | struct adt7473_data *data = i2c_get_clientdata(client); | 617 | struct adt7473_data *data = i2c_get_clientdata(client); |
590 | int temp = simple_strtol(buf, NULL, 10); | 618 | long temp; |
619 | |||
620 | if (strict_strtol(buf, 10, &temp)) | ||
621 | return -EINVAL; | ||
622 | |||
623 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
591 | 624 | ||
592 | mutex_lock(&data->lock); | 625 | mutex_lock(&data->lock); |
593 | data->pwm[attr->index] = temp; | 626 | data->pwm[attr->index] = temp; |
@@ -614,7 +647,12 @@ static ssize_t set_pwm_max(struct device *dev, | |||
614 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 647 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
615 | struct i2c_client *client = to_i2c_client(dev); | 648 | struct i2c_client *client = to_i2c_client(dev); |
616 | struct adt7473_data *data = i2c_get_clientdata(client); | 649 | struct adt7473_data *data = i2c_get_clientdata(client); |
617 | int temp = simple_strtol(buf, NULL, 10); | 650 | long temp; |
651 | |||
652 | if (strict_strtol(buf, 10, &temp)) | ||
653 | return -EINVAL; | ||
654 | |||
655 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
618 | 656 | ||
619 | mutex_lock(&data->lock); | 657 | mutex_lock(&data->lock); |
620 | data->pwm_max[attr->index] = temp; | 658 | data->pwm_max[attr->index] = temp; |
@@ -642,7 +680,12 @@ static ssize_t set_pwm_min(struct device *dev, | |||
642 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 680 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
643 | struct i2c_client *client = to_i2c_client(dev); | 681 | struct i2c_client *client = to_i2c_client(dev); |
644 | struct adt7473_data *data = i2c_get_clientdata(client); | 682 | struct adt7473_data *data = i2c_get_clientdata(client); |
645 | int temp = simple_strtol(buf, NULL, 10); | 683 | long temp; |
684 | |||
685 | if (strict_strtol(buf, 10, &temp)) | ||
686 | return -EINVAL; | ||
687 | |||
688 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
646 | 689 | ||
647 | mutex_lock(&data->lock); | 690 | mutex_lock(&data->lock); |
648 | data->pwm_min[attr->index] = temp; | 691 | data->pwm_min[attr->index] = temp; |
@@ -672,7 +715,12 @@ static ssize_t set_temp_tmax(struct device *dev, | |||
672 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 715 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
673 | struct i2c_client *client = to_i2c_client(dev); | 716 | struct i2c_client *client = to_i2c_client(dev); |
674 | struct adt7473_data *data = i2c_get_clientdata(client); | 717 | struct adt7473_data *data = i2c_get_clientdata(client); |
675 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 718 | long temp; |
719 | |||
720 | if (strict_strtol(buf, 10, &temp)) | ||
721 | return -EINVAL; | ||
722 | |||
723 | temp = ROUND_DIV(temp, 1000); | ||
676 | temp = encode_temp(data->temp_twos_complement, temp); | 724 | temp = encode_temp(data->temp_twos_complement, temp); |
677 | 725 | ||
678 | mutex_lock(&data->lock); | 726 | mutex_lock(&data->lock); |
@@ -703,7 +751,12 @@ static ssize_t set_temp_tmin(struct device *dev, | |||
703 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 751 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
704 | struct i2c_client *client = to_i2c_client(dev); | 752 | struct i2c_client *client = to_i2c_client(dev); |
705 | struct adt7473_data *data = i2c_get_clientdata(client); | 753 | struct adt7473_data *data = i2c_get_clientdata(client); |
706 | int temp = simple_strtol(buf, NULL, 10) / 1000; | 754 | long temp; |
755 | |||
756 | if (strict_strtol(buf, 10, &temp)) | ||
757 | return -EINVAL; | ||
758 | |||
759 | temp = ROUND_DIV(temp, 1000); | ||
707 | temp = encode_temp(data->temp_twos_complement, temp); | 760 | temp = encode_temp(data->temp_twos_complement, temp); |
708 | 761 | ||
709 | mutex_lock(&data->lock); | 762 | mutex_lock(&data->lock); |
@@ -741,7 +794,10 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
741 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 794 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
742 | struct i2c_client *client = to_i2c_client(dev); | 795 | struct i2c_client *client = to_i2c_client(dev); |
743 | struct adt7473_data *data = i2c_get_clientdata(client); | 796 | struct adt7473_data *data = i2c_get_clientdata(client); |
744 | int temp = simple_strtol(buf, NULL, 10); | 797 | long temp; |
798 | |||
799 | if (strict_strtol(buf, 10, &temp)) | ||
800 | return -EINVAL; | ||
745 | 801 | ||
746 | switch (temp) { | 802 | switch (temp) { |
747 | case 0: | 803 | case 0: |
@@ -805,7 +861,10 @@ static ssize_t set_pwm_auto_temp(struct device *dev, | |||
805 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 861 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
806 | struct i2c_client *client = to_i2c_client(dev); | 862 | struct i2c_client *client = to_i2c_client(dev); |
807 | struct adt7473_data *data = i2c_get_clientdata(client); | 863 | struct adt7473_data *data = i2c_get_clientdata(client); |
808 | int temp = simple_strtol(buf, NULL, 10); | 864 | long temp; |
865 | |||
866 | if (strict_strtol(buf, 10, &temp)) | ||
867 | return -EINVAL; | ||
809 | 868 | ||
810 | switch (temp) { | 869 | switch (temp) { |
811 | case 1: | 870 | case 1: |