spi: spidev: prevent spidev->speed_hz from being zero
authorDan Carpenter <dan.carpenter@oracle.com>
Tue, 25 Jan 2022 06:52:02 +0000 (09:52 +0300)
committerMark Brown <broonie@kernel.org>
Tue, 8 Feb 2022 13:40:16 +0000 (13:40 +0000)
A zero value for spi->max_speed_hz or spidev->speed_hz does not make
sense and trying to set that can lead to divide by zero crashes in
a some of the drivers.

drivers/spi/spi-s3c64xx.c:874 s3c64xx_spi_setup() error: potential divide by zero bug '/ spi->max_speed_hz'.
drivers/spi/spi-fsl-dspi.c:613 hz_to_spi_baud() error: potential divide by zero bug '/ speed_hz'.
drivers/spi/spi-xlp.c:146 xlp_spi_setup() error: potential divide by zero bug '/ (spi->max_speed_hz)'.
drivers/spi/spi-orion.c:162 orion_spi_baudrate_set() error: potential divide by zero bug '/ speed'.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Link: https://lore.kernel.org/r/20220125065202.GA8807@kili
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spidev.c

index a5cceca8b82b6c61891346fbeeee41cb5474df3c..dd824db63fbe66d383928c445c4c7676b0f4d7a5 100644 (file)
@@ -453,22 +453,29 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                                dev_dbg(&spi->dev, "%d bits per word\n", tmp);
                }
                break;
-       case SPI_IOC_WR_MAX_SPEED_HZ:
+       case SPI_IOC_WR_MAX_SPEED_HZ: {
+               u32 save;
+
                retval = get_user(tmp, (__u32 __user *)arg);
-               if (retval == 0) {
-                       u32     save = spi->max_speed_hz;
+               if (retval)
+                       break;
+               if (tmp == 0) {
+                       retval = -EINVAL;
+                       break;
+               }
 
-                       spi->max_speed_hz = tmp;
-                       retval = spi_setup(spi);
-                       if (retval == 0) {
-                               spidev->speed_hz = tmp;
-                               dev_dbg(&spi->dev, "%d Hz (max)\n",
-                                       spidev->speed_hz);
-                       }
-                       spi->max_speed_hz = save;
+               save = spi->max_speed_hz;
+
+               spi->max_speed_hz = tmp;
+               retval = spi_setup(spi);
+               if (retval == 0) {
+                       spidev->speed_hz = tmp;
+                       dev_dbg(&spi->dev, "%d Hz (max)\n", spidev->speed_hz);
                }
-               break;
 
+               spi->max_speed_hz = save;
+               break;
+       }
        default:
                /* segmented and/or full-duplex I/O request */
                /* Check message and copy into scratch area */