w1: therm: Fix off-by-one buffer overflow in alarms_store

The sysfs buffer passed to alarms_store() is allocated with 'size + 1'
bytes and a NUL terminator is appended. However, the 'size' argument
does not account for this extra byte. The original code then allocated
'size' bytes and used strcpy() to copy 'buf', which always writes one
byte past the allocated buffer since strcpy() copies until the NUL
terminator at index 'size'.

Fix this by parsing the 'buf' parameter directly using simple_strtoll()
without allocating any intermediate memory or string copying. This
removes the overflow while simplifying the code.

Cc: stable@vger.kernel.org
Fixes: e2c94d6f5720 ("w1_therm: adding alarm sysfs entry")
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
Link: https://patch.msgid.link/20251216145007.44328-2-thorsten.blum@linux.dev
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>

authored by Thorsten Blum and committed by Krzysztof Kozlowski 761fcf46 8f0b4cce

+19 -41
+19 -41
drivers/w1/slaves/w1_therm.c
··· 1836 1836 struct w1_slave *sl = dev_to_w1_slave(device); 1837 1837 struct therm_info info; 1838 1838 u8 new_config_register[3]; /* array of data to be written */ 1839 - int temp, ret; 1840 - char *token = NULL; 1839 + long long temp; 1840 + int ret = 0; 1841 1841 s8 tl, th; /* 1 byte per value + temp ring order */ 1842 - char *p_args, *orig; 1842 + const char *p = buf; 1843 + char *endp; 1843 1844 1844 - p_args = orig = kmalloc(size, GFP_KERNEL); 1845 - /* Safe string copys as buf is const */ 1846 - if (!p_args) { 1847 - dev_warn(device, 1848 - "%s: error unable to allocate memory %d\n", 1849 - __func__, -ENOMEM); 1850 - return size; 1851 - } 1852 - strcpy(p_args, buf); 1853 - 1854 - /* Split string using space char */ 1855 - token = strsep(&p_args, " "); 1856 - 1857 - if (!token) { 1858 - dev_info(device, 1859 - "%s: error parsing args %d\n", __func__, -EINVAL); 1860 - goto free_m; 1861 - } 1862 - 1863 - /* Convert 1st entry to int */ 1864 - ret = kstrtoint (token, 10, &temp); 1845 + temp = simple_strtoll(p, &endp, 10); 1846 + if (p == endp || *endp != ' ') 1847 + ret = -EINVAL; 1848 + else if (temp < INT_MIN || temp > INT_MAX) 1849 + ret = -ERANGE; 1865 1850 if (ret) { 1866 1851 dev_info(device, 1867 1852 "%s: error parsing args %d\n", __func__, ret); 1868 - goto free_m; 1853 + return size; 1869 1854 } 1870 1855 1871 1856 tl = int_to_short(temp); 1872 1857 1873 - /* Split string using space char */ 1874 - token = strsep(&p_args, " "); 1875 - if (!token) { 1876 - dev_info(device, 1877 - "%s: error parsing args %d\n", __func__, -EINVAL); 1878 - goto free_m; 1879 - } 1880 - /* Convert 2nd entry to int */ 1881 - ret = kstrtoint (token, 10, &temp); 1858 + p = endp + 1; 1859 + temp = simple_strtoll(p, &endp, 10); 1860 + if (p == endp) 1861 + ret = -EINVAL; 1862 + else if (temp < INT_MIN || temp > INT_MAX) 1863 + ret = -ERANGE; 1882 1864 if (ret) { 1883 1865 dev_info(device, 1884 1866 "%s: error parsing args %d\n", __func__, ret); 1885 - goto free_m; 1867 + return size; 1886 1868 } 1887 1869 1888 1870 /* Prepare to cast to short by eliminating out of range values */ ··· 1887 1905 dev_info(device, 1888 1906 "%s: error reading from the slave device %d\n", 1889 1907 __func__, ret); 1890 - goto free_m; 1908 + return size; 1891 1909 } 1892 1910 1893 1911 /* Write data in the device RAM */ ··· 1895 1913 dev_info(device, 1896 1914 "%s: Device not supported by the driver %d\n", 1897 1915 __func__, -ENODEV); 1898 - goto free_m; 1916 + return size; 1899 1917 } 1900 1918 1901 1919 ret = SLAVE_SPECIFIC_FUNC(sl)->write_data(sl, new_config_register); ··· 1903 1921 dev_info(device, 1904 1922 "%s: error writing to the slave device %d\n", 1905 1923 __func__, ret); 1906 - 1907 - free_m: 1908 - /* free allocated memory */ 1909 - kfree(orig); 1910 1924 1911 1925 return size; 1912 1926 }