Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'hwmon-for-v6.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon fixes from Guenter Roeck:

- ltc4282: Avoid repeated register write operation

- occ: Fix unaligned accesses, and rework attribute registration to
reduce stack usage

- ftsteutates: Fix TOCTOU race

* tag 'hwmon-for-v6.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
hwmon: (ltc4282) avoid repeated register write
hwmon: (occ) fix unaligned accesses
hwmon: (occ) Rework attribute registration for stack usage
hwmon: (ftsteutates) Fix TOCTOU race in fts_read()

+103 -151
+6 -3
drivers/hwmon/ftsteutates.c
··· 423 423 break; 424 424 case hwmon_pwm: 425 425 switch (attr) { 426 - case hwmon_pwm_auto_channels_temp: 427 - if (data->fan_source[channel] == FTS_FAN_SOURCE_INVALID) 426 + case hwmon_pwm_auto_channels_temp: { 427 + u8 fan_source = data->fan_source[channel]; 428 + 429 + if (fan_source == FTS_FAN_SOURCE_INVALID || fan_source >= BITS_PER_LONG) 428 430 *val = 0; 429 431 else 430 - *val = BIT(data->fan_source[channel]); 432 + *val = BIT(fan_source); 431 433 432 434 return 0; 435 + } 433 436 default: 434 437 break; 435 438 }
-7
drivers/hwmon/ltc4282.c
··· 1512 1512 } 1513 1513 1514 1514 if (device_property_read_bool(dev, "adi,fault-log-enable")) { 1515 - ret = regmap_set_bits(st->map, LTC4282_ADC_CTRL, 1516 - LTC4282_FAULT_LOG_EN_MASK); 1517 - if (ret) 1518 - return ret; 1519 - } 1520 - 1521 - if (device_property_read_bool(dev, "adi,fault-log-enable")) { 1522 1515 ret = regmap_set_bits(st->map, LTC4282_ADC_CTRL, LTC4282_FAULT_LOG_EN_MASK); 1523 1516 if (ret) 1524 1517 return ret;
+97 -141
drivers/hwmon/occ/common.c
··· 459 459 return sysfs_emit(buf, "%llu\n", val); 460 460 } 461 461 462 - static u64 occ_get_powr_avg(u64 *accum, u32 *samples) 462 + static u64 occ_get_powr_avg(u64 accum, u32 samples) 463 463 { 464 - u64 divisor = get_unaligned_be32(samples); 465 - 466 - return (divisor == 0) ? 0 : 467 - div64_u64(get_unaligned_be64(accum) * 1000000ULL, divisor); 464 + return (samples == 0) ? 0 : 465 + mul_u64_u32_div(accum, 1000000UL, samples); 468 466 } 469 467 470 468 static ssize_t occ_show_power_2(struct device *dev, ··· 487 489 get_unaligned_be32(&power->sensor_id), 488 490 power->function_id, power->apss_channel); 489 491 case 1: 490 - val = occ_get_powr_avg(&power->accumulator, 491 - &power->update_tag); 492 + val = occ_get_powr_avg(get_unaligned_be64(&power->accumulator), 493 + get_unaligned_be32(&power->update_tag)); 492 494 break; 493 495 case 2: 494 496 val = (u64)get_unaligned_be32(&power->update_tag) * ··· 525 527 return sysfs_emit(buf, "%u_system\n", 526 528 get_unaligned_be32(&power->sensor_id)); 527 529 case 1: 528 - val = occ_get_powr_avg(&power->system.accumulator, 529 - &power->system.update_tag); 530 + val = occ_get_powr_avg(get_unaligned_be64(&power->system.accumulator), 531 + get_unaligned_be32(&power->system.update_tag)); 530 532 break; 531 533 case 2: 532 534 val = (u64)get_unaligned_be32(&power->system.update_tag) * ··· 539 541 return sysfs_emit(buf, "%u_proc\n", 540 542 get_unaligned_be32(&power->sensor_id)); 541 543 case 5: 542 - val = occ_get_powr_avg(&power->proc.accumulator, 543 - &power->proc.update_tag); 544 + val = occ_get_powr_avg(get_unaligned_be64(&power->proc.accumulator), 545 + get_unaligned_be32(&power->proc.update_tag)); 544 546 break; 545 547 case 6: 546 548 val = (u64)get_unaligned_be32(&power->proc.update_tag) * ··· 553 555 return sysfs_emit(buf, "%u_vdd\n", 554 556 get_unaligned_be32(&power->sensor_id)); 555 557 case 9: 556 - val = occ_get_powr_avg(&power->vdd.accumulator, 557 - &power->vdd.update_tag); 558 + val = occ_get_powr_avg(get_unaligned_be64(&power->vdd.accumulator), 559 + get_unaligned_be32(&power->vdd.update_tag)); 558 560 break; 559 561 case 10: 560 562 val = (u64)get_unaligned_be32(&power->vdd.update_tag) * ··· 567 569 return sysfs_emit(buf, "%u_vdn\n", 568 570 get_unaligned_be32(&power->sensor_id)); 569 571 case 13: 570 - val = occ_get_powr_avg(&power->vdn.accumulator, 571 - &power->vdn.update_tag); 572 + val = occ_get_powr_avg(get_unaligned_be64(&power->vdn.accumulator), 573 + get_unaligned_be32(&power->vdn.update_tag)); 572 574 break; 573 575 case 14: 574 576 val = (u64)get_unaligned_be32(&power->vdn.update_tag) * ··· 745 747 } 746 748 747 749 /* 748 - * Some helper macros to make it easier to define an occ_attribute. Since these 749 - * are dynamically allocated, we shouldn't use the existing kernel macros which 750 + * A helper to make it easier to define an occ_attribute. Since these 751 + * are dynamically allocated, we cannot use the existing kernel macros which 750 752 * stringify the name argument. 751 753 */ 752 - #define ATTR_OCC(_name, _mode, _show, _store) { \ 753 - .attr = { \ 754 - .name = _name, \ 755 - .mode = VERIFY_OCTAL_PERMISSIONS(_mode), \ 756 - }, \ 757 - .show = _show, \ 758 - .store = _store, \ 759 - } 754 + static void occ_init_attribute(struct occ_attribute *attr, int mode, 755 + ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf), 756 + ssize_t (*store)(struct device *dev, struct device_attribute *attr, 757 + const char *buf, size_t count), 758 + int nr, int index, const char *fmt, ...) 759 + { 760 + va_list args; 760 761 761 - #define SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index) { \ 762 - .dev_attr = ATTR_OCC(_name, _mode, _show, _store), \ 763 - .index = _index, \ 764 - .nr = _nr, \ 765 - } 762 + va_start(args, fmt); 763 + vsnprintf(attr->name, sizeof(attr->name), fmt, args); 764 + va_end(args); 766 765 767 - #define OCC_INIT_ATTR(_name, _mode, _show, _store, _nr, _index) \ 768 - ((struct sensor_device_attribute_2) \ 769 - SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index)) 766 + attr->sensor.dev_attr.attr.name = attr->name; 767 + attr->sensor.dev_attr.attr.mode = mode; 768 + attr->sensor.dev_attr.show = show; 769 + attr->sensor.dev_attr.store = store; 770 + attr->sensor.index = index; 771 + attr->sensor.nr = nr; 772 + } 770 773 771 774 /* 772 775 * Allocate and instatiate sensor_device_attribute_2s. It's most efficient to ··· 854 855 sensors->extended.num_sensors = 0; 855 856 } 856 857 857 - occ->attrs = devm_kzalloc(dev, sizeof(*occ->attrs) * num_attrs, 858 + occ->attrs = devm_kcalloc(dev, num_attrs, sizeof(*occ->attrs), 858 859 GFP_KERNEL); 859 860 if (!occ->attrs) 860 861 return -ENOMEM; 861 862 862 863 /* null-terminated list */ 863 - occ->group.attrs = devm_kzalloc(dev, sizeof(*occ->group.attrs) * 864 - num_attrs + 1, GFP_KERNEL); 864 + occ->group.attrs = devm_kcalloc(dev, num_attrs + 1, 865 + sizeof(*occ->group.attrs), 866 + GFP_KERNEL); 865 867 if (!occ->group.attrs) 866 868 return -ENOMEM; 867 869 ··· 872 872 s = i + 1; 873 873 temp = ((struct temp_sensor_2 *)sensors->temp.data) + i; 874 874 875 - snprintf(attr->name, sizeof(attr->name), "temp%d_label", s); 876 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL, 877 - 0, i); 875 + occ_init_attribute(attr, 0444, show_temp, NULL, 876 + 0, i, "temp%d_label", s); 878 877 attr++; 879 878 880 879 if (sensors->temp.version == 2 && 881 880 temp->fru_type == OCC_FRU_TYPE_VRM) { 882 - snprintf(attr->name, sizeof(attr->name), 883 - "temp%d_alarm", s); 881 + occ_init_attribute(attr, 0444, show_temp, NULL, 882 + 1, i, "temp%d_alarm", s); 884 883 } else { 885 - snprintf(attr->name, sizeof(attr->name), 886 - "temp%d_input", s); 884 + occ_init_attribute(attr, 0444, show_temp, NULL, 885 + 1, i, "temp%d_input", s); 887 886 } 888 887 889 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL, 890 - 1, i); 891 888 attr++; 892 889 893 890 if (sensors->temp.version > 1) { 894 - snprintf(attr->name, sizeof(attr->name), 895 - "temp%d_fru_type", s); 896 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 897 - show_temp, NULL, 2, i); 891 + occ_init_attribute(attr, 0444, show_temp, NULL, 892 + 2, i, "temp%d_fru_type", s); 898 893 attr++; 899 894 900 - snprintf(attr->name, sizeof(attr->name), 901 - "temp%d_fault", s); 902 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 903 - show_temp, NULL, 3, i); 895 + occ_init_attribute(attr, 0444, show_temp, NULL, 896 + 3, i, "temp%d_fault", s); 904 897 attr++; 905 898 906 899 if (sensors->temp.version == 0x10) { 907 - snprintf(attr->name, sizeof(attr->name), 908 - "temp%d_max", s); 909 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 910 - show_temp, NULL, 911 - 4, i); 900 + occ_init_attribute(attr, 0444, show_temp, NULL, 901 + 4, i, "temp%d_max", s); 912 902 attr++; 913 903 } 914 904 } ··· 907 917 for (i = 0; i < sensors->freq.num_sensors; ++i) { 908 918 s = i + 1; 909 919 910 - snprintf(attr->name, sizeof(attr->name), "freq%d_label", s); 911 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL, 912 - 0, i); 920 + occ_init_attribute(attr, 0444, show_freq, NULL, 921 + 0, i, "freq%d_label", s); 913 922 attr++; 914 923 915 - snprintf(attr->name, sizeof(attr->name), "freq%d_input", s); 916 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL, 917 - 1, i); 924 + occ_init_attribute(attr, 0444, show_freq, NULL, 925 + 1, i, "freq%d_input", s); 918 926 attr++; 919 927 } 920 928 ··· 928 940 s = (i * 4) + 1; 929 941 930 942 for (j = 0; j < 4; ++j) { 931 - snprintf(attr->name, sizeof(attr->name), 932 - "power%d_label", s); 933 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 934 - show_power, NULL, 935 - nr++, i); 943 + occ_init_attribute(attr, 0444, show_power, 944 + NULL, nr++, i, 945 + "power%d_label", s); 936 946 attr++; 937 947 938 - snprintf(attr->name, sizeof(attr->name), 939 - "power%d_average", s); 940 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 941 - show_power, NULL, 942 - nr++, i); 948 + occ_init_attribute(attr, 0444, show_power, 949 + NULL, nr++, i, 950 + "power%d_average", s); 943 951 attr++; 944 952 945 - snprintf(attr->name, sizeof(attr->name), 946 - "power%d_average_interval", s); 947 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 948 - show_power, NULL, 949 - nr++, i); 953 + occ_init_attribute(attr, 0444, show_power, 954 + NULL, nr++, i, 955 + "power%d_average_interval", s); 950 956 attr++; 951 957 952 - snprintf(attr->name, sizeof(attr->name), 953 - "power%d_input", s); 954 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 955 - show_power, NULL, 956 - nr++, i); 958 + occ_init_attribute(attr, 0444, show_power, 959 + NULL, nr++, i, 960 + "power%d_input", s); 957 961 attr++; 958 962 959 963 s++; ··· 957 977 for (i = 0; i < sensors->power.num_sensors; ++i) { 958 978 s = i + 1; 959 979 960 - snprintf(attr->name, sizeof(attr->name), 961 - "power%d_label", s); 962 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 963 - show_power, NULL, 0, i); 980 + occ_init_attribute(attr, 0444, show_power, NULL, 981 + 0, i, "power%d_label", s); 964 982 attr++; 965 983 966 - snprintf(attr->name, sizeof(attr->name), 967 - "power%d_average", s); 968 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 969 - show_power, NULL, 1, i); 984 + occ_init_attribute(attr, 0444, show_power, NULL, 985 + 1, i, "power%d_average", s); 970 986 attr++; 971 987 972 - snprintf(attr->name, sizeof(attr->name), 973 - "power%d_average_interval", s); 974 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 975 - show_power, NULL, 2, i); 988 + occ_init_attribute(attr, 0444, show_power, NULL, 989 + 2, i, "power%d_average_interval", s); 976 990 attr++; 977 991 978 - snprintf(attr->name, sizeof(attr->name), 979 - "power%d_input", s); 980 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 981 - show_power, NULL, 3, i); 992 + occ_init_attribute(attr, 0444, show_power, NULL, 993 + 3, i, "power%d_input", s); 982 994 attr++; 983 995 } 984 996 ··· 978 1006 } 979 1007 980 1008 if (sensors->caps.num_sensors >= 1) { 981 - snprintf(attr->name, sizeof(attr->name), "power%d_label", s); 982 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, 983 - 0, 0); 1009 + occ_init_attribute(attr, 0444, show_caps, NULL, 1010 + 0, 0, "power%d_label", s); 984 1011 attr++; 985 1012 986 - snprintf(attr->name, sizeof(attr->name), "power%d_cap", s); 987 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, 988 - 1, 0); 1013 + occ_init_attribute(attr, 0444, show_caps, NULL, 1014 + 1, 0, "power%d_cap", s); 989 1015 attr++; 990 1016 991 - snprintf(attr->name, sizeof(attr->name), "power%d_input", s); 992 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, 993 - 2, 0); 1017 + occ_init_attribute(attr, 0444, show_caps, NULL, 1018 + 2, 0, "power%d_input", s); 994 1019 attr++; 995 1020 996 - snprintf(attr->name, sizeof(attr->name), 997 - "power%d_cap_not_redundant", s); 998 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, 999 - 3, 0); 1021 + occ_init_attribute(attr, 0444, show_caps, NULL, 1022 + 3, 0, "power%d_cap_not_redundant", s); 1000 1023 attr++; 1001 1024 1002 - snprintf(attr->name, sizeof(attr->name), "power%d_cap_max", s); 1003 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, 1004 - 4, 0); 1025 + occ_init_attribute(attr, 0444, show_caps, NULL, 1026 + 4, 0, "power%d_cap_max", s); 1005 1027 attr++; 1006 1028 1007 - snprintf(attr->name, sizeof(attr->name), "power%d_cap_min", s); 1008 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, 1009 - 5, 0); 1029 + occ_init_attribute(attr, 0444, show_caps, NULL, 1030 + 5, 0, "power%d_cap_min", s); 1010 1031 attr++; 1011 1032 1012 - snprintf(attr->name, sizeof(attr->name), "power%d_cap_user", 1013 - s); 1014 - attr->sensor = OCC_INIT_ATTR(attr->name, 0644, show_caps, 1015 - occ_store_caps_user, 6, 0); 1033 + occ_init_attribute(attr, 0644, show_caps, occ_store_caps_user, 1034 + 6, 0, "power%d_cap_user", s); 1016 1035 attr++; 1017 1036 1018 1037 if (sensors->caps.version > 1) { 1019 - snprintf(attr->name, sizeof(attr->name), 1020 - "power%d_cap_user_source", s); 1021 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 1022 - show_caps, NULL, 7, 0); 1038 + occ_init_attribute(attr, 0444, show_caps, NULL, 1039 + 7, 0, "power%d_cap_user_source", s); 1023 1040 attr++; 1024 1041 1025 1042 if (sensors->caps.version > 2) { 1026 - snprintf(attr->name, sizeof(attr->name), 1027 - "power%d_cap_min_soft", s); 1028 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 1029 - show_caps, NULL, 1030 - 8, 0); 1043 + occ_init_attribute(attr, 0444, show_caps, NULL, 1044 + 8, 0, 1045 + "power%d_cap_min_soft", s); 1031 1046 attr++; 1032 1047 } 1033 1048 } ··· 1023 1064 for (i = 0; i < sensors->extended.num_sensors; ++i) { 1024 1065 s = i + 1; 1025 1066 1026 - snprintf(attr->name, sizeof(attr->name), "extn%d_label", s); 1027 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 1028 - occ_show_extended, NULL, 0, i); 1067 + occ_init_attribute(attr, 0444, occ_show_extended, NULL, 1068 + 0, i, "extn%d_label", s); 1029 1069 attr++; 1030 1070 1031 - snprintf(attr->name, sizeof(attr->name), "extn%d_flags", s); 1032 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 1033 - occ_show_extended, NULL, 1, i); 1071 + occ_init_attribute(attr, 0444, occ_show_extended, NULL, 1072 + 1, i, "extn%d_flags", s); 1034 1073 attr++; 1035 1074 1036 - snprintf(attr->name, sizeof(attr->name), "extn%d_input", s); 1037 - attr->sensor = OCC_INIT_ATTR(attr->name, 0444, 1038 - occ_show_extended, NULL, 2, i); 1075 + occ_init_attribute(attr, 0444, occ_show_extended, NULL, 1076 + 2, i, "extn%d_input", s); 1039 1077 attr++; 1040 1078 } 1041 1079