From c20fb959fe3849068550095e2004d8eea9bc1d7f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 31 Oct 2022 07:12:20 +0100 Subject: [PATCH] 6.0-stable patches added patches: fbdev-smscufx-fix-several-use-after-free-bugs.patch fbdev-stifb-fall-back-to-cfb_fillrect-on-32-bit-hcrx-cards.patch iio-adxl367-fix-unsafe-buffer-attributes.patch iio-adxl372-fix-unsafe-buffer-attributes.patch iio-light-tsl2583-fix-module-unloading.patch iio-temperature-ltc2983-allocate-iio-channels-once.patch tools-iio-iio_utils-fix-digit-calculation.patch --- ...cufx-fix-several-use-after-free-bugs.patch | 168 ++++++++++++++++++ ...to-cfb_fillrect-on-32-bit-hcrx-cards.patch | 34 ++++ ...adxl367-fix-unsafe-buffer-attributes.patch | 70 ++++++++ ...adxl372-fix-unsafe-buffer-attributes.patch | 70 ++++++++ ...o-light-tsl2583-fix-module-unloading.patch | 35 ++++ ...e-ltc2983-allocate-iio-channels-once.patch | 54 ++++++ queue-6.0/series | 7 + ...-iio-iio_utils-fix-digit-calculation.patch | 42 +++++ 8 files changed, 480 insertions(+) create mode 100644 queue-6.0/fbdev-smscufx-fix-several-use-after-free-bugs.patch create mode 100644 queue-6.0/fbdev-stifb-fall-back-to-cfb_fillrect-on-32-bit-hcrx-cards.patch create mode 100644 queue-6.0/iio-adxl367-fix-unsafe-buffer-attributes.patch create mode 100644 queue-6.0/iio-adxl372-fix-unsafe-buffer-attributes.patch create mode 100644 queue-6.0/iio-light-tsl2583-fix-module-unloading.patch create mode 100644 queue-6.0/iio-temperature-ltc2983-allocate-iio-channels-once.patch create mode 100644 queue-6.0/tools-iio-iio_utils-fix-digit-calculation.patch diff --git a/queue-6.0/fbdev-smscufx-fix-several-use-after-free-bugs.patch b/queue-6.0/fbdev-smscufx-fix-several-use-after-free-bugs.patch new file mode 100644 index 00000000000..e95d0408321 --- /dev/null +++ b/queue-6.0/fbdev-smscufx-fix-several-use-after-free-bugs.patch @@ -0,0 +1,168 @@ +From cc67482c9e5f2c80d62f623bcc347c29f9f648e1 Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Thu, 20 Oct 2022 18:15:44 -0700 +Subject: fbdev: smscufx: Fix several use-after-free bugs + +From: Hyunwoo Kim + +commit cc67482c9e5f2c80d62f623bcc347c29f9f648e1 upstream. + +Several types of UAFs can occur when physically removing a USB device. + +Adds ufx_ops_destroy() function to .fb_destroy of fb_ops, and +in this function, there is kref_put() that finally calls ufx_free(). + +This fix prevents multiple UAFs. + +Signed-off-by: Hyunwoo Kim +Link: https://lore.kernel.org/linux-fbdev/20221011153436.GA4446@ubuntu/ +Cc: +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/smscufx.c | 55 ++++++++++++++++++++++-------------------- + 1 file changed, 30 insertions(+), 25 deletions(-) + +--- a/drivers/video/fbdev/smscufx.c ++++ b/drivers/video/fbdev/smscufx.c +@@ -97,7 +97,6 @@ struct ufx_data { + struct kref kref; + int fb_count; + bool virtualized; /* true when physical usb device not present */ +- struct delayed_work free_framebuffer_work; + atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ + atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ + u8 *edid; /* null until we read edid from hw or get from sysfs */ +@@ -1117,15 +1116,24 @@ static void ufx_free(struct kref *kref) + { + struct ufx_data *dev = container_of(kref, struct ufx_data, kref); + +- /* this function will wait for all in-flight urbs to complete */ +- if (dev->urbs.count > 0) +- ufx_free_urb_list(dev); ++ kfree(dev); ++} + +- pr_debug("freeing ufx_data %p", dev); ++static void ufx_ops_destory(struct fb_info *info) ++{ ++ struct ufx_data *dev = info->par; ++ int node = info->node; + +- kfree(dev); ++ /* Assume info structure is freed after this point */ ++ framebuffer_release(info); ++ ++ pr_debug("fb_info for /dev/fb%d has been freed", node); ++ ++ /* release reference taken by kref_init in probe() */ ++ kref_put(&dev->kref, ufx_free); + } + ++ + static void ufx_release_urb_work(struct work_struct *work) + { + struct urb_node *unode = container_of(work, struct urb_node, +@@ -1134,14 +1142,9 @@ static void ufx_release_urb_work(struct + up(&unode->dev->urbs.limit_sem); + } + +-static void ufx_free_framebuffer_work(struct work_struct *work) ++static void ufx_free_framebuffer(struct ufx_data *dev) + { +- struct ufx_data *dev = container_of(work, struct ufx_data, +- free_framebuffer_work.work); + struct fb_info *info = dev->info; +- int node = info->node; +- +- unregister_framebuffer(info); + + if (info->cmap.len != 0) + fb_dealloc_cmap(&info->cmap); +@@ -1153,11 +1156,6 @@ static void ufx_free_framebuffer_work(st + + dev->info = NULL; + +- /* Assume info structure is freed after this point */ +- framebuffer_release(info); +- +- pr_debug("fb_info for /dev/fb%d has been freed", node); +- + /* ref taken in probe() as part of registering framebfufer */ + kref_put(&dev->kref, ufx_free); + } +@@ -1169,11 +1167,13 @@ static int ufx_ops_release(struct fb_inf + { + struct ufx_data *dev = info->par; + ++ mutex_lock(&disconnect_mutex); ++ + dev->fb_count--; + + /* We can't free fb_info here - fbmem will touch it when we return */ + if (dev->virtualized && (dev->fb_count == 0)) +- schedule_delayed_work(&dev->free_framebuffer_work, HZ); ++ ufx_free_framebuffer(dev); + + if ((dev->fb_count == 0) && (info->fbdefio)) { + fb_deferred_io_cleanup(info); +@@ -1186,6 +1186,8 @@ static int ufx_ops_release(struct fb_inf + + kref_put(&dev->kref, ufx_free); + ++ mutex_unlock(&disconnect_mutex); ++ + return 0; + } + +@@ -1292,6 +1294,7 @@ static const struct fb_ops ufx_ops = { + .fb_blank = ufx_ops_blank, + .fb_check_var = ufx_ops_check_var, + .fb_set_par = ufx_ops_set_par, ++ .fb_destroy = ufx_ops_destory, + }; + + /* Assumes &info->lock held by caller +@@ -1673,9 +1676,6 @@ static int ufx_usb_probe(struct usb_inte + goto destroy_modedb; + } + +- INIT_DELAYED_WORK(&dev->free_framebuffer_work, +- ufx_free_framebuffer_work); +- + retval = ufx_reg_read(dev, 0x3000, &id_rev); + check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval); + dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev); +@@ -1748,10 +1748,12 @@ e_nomem: + static void ufx_usb_disconnect(struct usb_interface *interface) + { + struct ufx_data *dev; ++ struct fb_info *info; + + mutex_lock(&disconnect_mutex); + + dev = usb_get_intfdata(interface); ++ info = dev->info; + + pr_debug("USB disconnect starting\n"); + +@@ -1765,12 +1767,15 @@ static void ufx_usb_disconnect(struct us + + /* if clients still have us open, will be freed on last close */ + if (dev->fb_count == 0) +- schedule_delayed_work(&dev->free_framebuffer_work, 0); ++ ufx_free_framebuffer(dev); + +- /* release reference taken by kref_init in probe() */ +- kref_put(&dev->kref, ufx_free); ++ /* this function will wait for all in-flight urbs to complete */ ++ if (dev->urbs.count > 0) ++ ufx_free_urb_list(dev); + +- /* consider ufx_data freed */ ++ pr_debug("freeing ufx_data %p", dev); ++ ++ unregister_framebuffer(info); + + mutex_unlock(&disconnect_mutex); + } diff --git a/queue-6.0/fbdev-stifb-fall-back-to-cfb_fillrect-on-32-bit-hcrx-cards.patch b/queue-6.0/fbdev-stifb-fall-back-to-cfb_fillrect-on-32-bit-hcrx-cards.patch new file mode 100644 index 00000000000..e1526dbc2fa --- /dev/null +++ b/queue-6.0/fbdev-stifb-fall-back-to-cfb_fillrect-on-32-bit-hcrx-cards.patch @@ -0,0 +1,34 @@ +From 776d875fd4cbb3884860ea7f63c3958f02b0c80e Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Fri, 14 Oct 2022 20:01:17 +0200 +Subject: fbdev: stifb: Fall back to cfb_fillrect() on 32-bit HCRX cards + +From: Helge Deller + +commit 776d875fd4cbb3884860ea7f63c3958f02b0c80e upstream. + +When the text console is scrolling text upwards it calls the fillrect() +function to empty the new line. The current implementation doesn't seem +to work correctly on HCRX cards in 32-bit mode and leave garbage in that +line instead. Fix it by falling back to standard cfb_fillrect() in that +case. + +Signed-off-by: Helge Deller +Cc: +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/stifb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/video/fbdev/stifb.c ++++ b/drivers/video/fbdev/stifb.c +@@ -1055,7 +1055,8 @@ stifb_fillrect(struct fb_info *info, con + { + struct stifb_info *fb = container_of(info, struct stifb_info, info); + +- if (rect->rop != ROP_COPY) ++ if (rect->rop != ROP_COPY || ++ (fb->id == S9000_ID_HCRX && fb->info.var.bits_per_pixel == 32)) + return cfb_fillrect(info, rect); + + SETUP_HW(fb); diff --git a/queue-6.0/iio-adxl367-fix-unsafe-buffer-attributes.patch b/queue-6.0/iio-adxl367-fix-unsafe-buffer-attributes.patch new file mode 100644 index 00000000000..2f5a4271cb4 --- /dev/null +++ b/queue-6.0/iio-adxl367-fix-unsafe-buffer-attributes.patch @@ -0,0 +1,70 @@ +From 5e23b33d1e84f04c80da6f1d89cbb3d3a3f81e01 Mon Sep 17 00:00:00 2001 +From: Matti Vaittinen +Date: Mon, 3 Oct 2022 11:10:29 +0300 +Subject: iio: adxl367: Fix unsafe buffer attributes + +From: Matti Vaittinen + +commit 5e23b33d1e84f04c80da6f1d89cbb3d3a3f81e01 upstream. + +The devm_iio_kfifo_buffer_setup_ext() was changed by +commit 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") +to silently expect that all attributes given in buffer_attrs array are +device-attributes. This expectation was not forced by the API - and some +drivers did register attributes created by IIO_CONST_ATTR(). + +The added attribute "wrapping" does not copy the pointer to stored +string constant and when the sysfs file is read the kernel will access +to invalid location. + +Change the IIO_CONST_ATTRs from the driver to IIO_DEVICE_ATTR in order +to prevent the invalid memory access. + +Signed-off-by: Matti Vaittinen +Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") +Cc: +Link: https://lore.kernel.org/r/2e2d9ec34fb1df8ab8e2749199822db8cc91d302.1664782676.git.mazziesaccount@gmail.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/accel/adxl367.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +--- a/drivers/iio/accel/adxl367.c ++++ b/drivers/iio/accel/adxl367.c +@@ -1185,17 +1185,30 @@ static ssize_t adxl367_get_fifo_watermar + return sysfs_emit(buf, "%d\n", fifo_watermark); + } + +-static IIO_CONST_ATTR(hwfifo_watermark_min, "1"); +-static IIO_CONST_ATTR(hwfifo_watermark_max, +- __stringify(ADXL367_FIFO_MAX_WATERMARK)); ++static ssize_t hwfifo_watermark_min_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return sysfs_emit(buf, "%s\n", "1"); ++} ++ ++static ssize_t hwfifo_watermark_max_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return sysfs_emit(buf, "%s\n", __stringify(ADXL367_FIFO_MAX_WATERMARK)); ++} ++ ++static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); ++static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); + static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, + adxl367_get_fifo_watermark, NULL, 0); + static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, + adxl367_get_fifo_enabled, NULL, 0); + + static const struct attribute *adxl367_fifo_attributes[] = { +- &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, +- &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark.dev_attr.attr, + &iio_dev_attr_hwfifo_enabled.dev_attr.attr, + NULL, diff --git a/queue-6.0/iio-adxl372-fix-unsafe-buffer-attributes.patch b/queue-6.0/iio-adxl372-fix-unsafe-buffer-attributes.patch new file mode 100644 index 00000000000..0b50cc64c74 --- /dev/null +++ b/queue-6.0/iio-adxl372-fix-unsafe-buffer-attributes.patch @@ -0,0 +1,70 @@ +From ab0ee36e90f611f32c3a53afe9dc743de48138e2 Mon Sep 17 00:00:00 2001 +From: Matti Vaittinen +Date: Mon, 3 Oct 2022 11:10:51 +0300 +Subject: iio: adxl372: Fix unsafe buffer attributes + +From: Matti Vaittinen + +commit ab0ee36e90f611f32c3a53afe9dc743de48138e2 upstream. + +The iio_triggered_buffer_setup_ext() was changed by +commit 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") +to silently expect that all attributes given in buffer_attrs array are +device-attributes. This expectation was not forced by the API - and some +drivers did register attributes created by IIO_CONST_ATTR(). + +The added attribute "wrapping" does not copy the pointer to stored +string constant and when the sysfs file is read the kernel will access +to invalid location. + +Change the IIO_CONST_ATTRs from the driver to IIO_DEVICE_ATTR in order +to prevent the invalid memory access. + +Signed-off-by: Matti Vaittinen +Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") +Cc: +Link: https://lore.kernel.org/r/19158499623cdf7f9c5efae1f13c9f1a918ff75f.1664782676.git.mazziesaccount@gmail.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/accel/adxl372.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +--- a/drivers/iio/accel/adxl372.c ++++ b/drivers/iio/accel/adxl372.c +@@ -998,17 +998,30 @@ static ssize_t adxl372_get_fifo_watermar + return sprintf(buf, "%d\n", st->watermark); + } + +-static IIO_CONST_ATTR(hwfifo_watermark_min, "1"); +-static IIO_CONST_ATTR(hwfifo_watermark_max, +- __stringify(ADXL372_FIFO_SIZE)); ++static ssize_t hwfifo_watermark_min_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return sysfs_emit(buf, "%s\n", "1"); ++} ++ ++static ssize_t hwfifo_watermark_max_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return sysfs_emit(buf, "%s\n", __stringify(ADXL372_FIFO_SIZE)); ++} ++ ++static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); ++static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); + static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, + adxl372_get_fifo_watermark, NULL, 0); + static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, + adxl372_get_fifo_enabled, NULL, 0); + + static const struct attribute *adxl372_fifo_attributes[] = { +- &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, +- &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr, ++ &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark.dev_attr.attr, + &iio_dev_attr_hwfifo_enabled.dev_attr.attr, + NULL, diff --git a/queue-6.0/iio-light-tsl2583-fix-module-unloading.patch b/queue-6.0/iio-light-tsl2583-fix-module-unloading.patch new file mode 100644 index 00000000000..6f2a3abf93c --- /dev/null +++ b/queue-6.0/iio-light-tsl2583-fix-module-unloading.patch @@ -0,0 +1,35 @@ +From 0dec4d2f2636b9e54d9d29f17afc7687c5407f78 Mon Sep 17 00:00:00 2001 +From: Shreeya Patel +Date: Fri, 26 Aug 2022 17:53:52 +0530 +Subject: iio: light: tsl2583: Fix module unloading + +From: Shreeya Patel + +commit 0dec4d2f2636b9e54d9d29f17afc7687c5407f78 upstream. + +tsl2583 probe() uses devm_iio_device_register() and calling +iio_device_unregister() causes the unregister to occur twice. s +Switch to iio_device_register() instead of devm_iio_device_register() +in probe to avoid the device managed cleanup. + +Fixes: 371894f5d1a0 ("iio: tsl2583: add runtime power management support") +Signed-off-by: Shreeya Patel +Link: https://lore.kernel.org/r/20220826122352.288438-1-shreeya.patel@collabora.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/light/tsl2583.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/light/tsl2583.c ++++ b/drivers/iio/light/tsl2583.c +@@ -858,7 +858,7 @@ static int tsl2583_probe(struct i2c_clie + TSL2583_POWER_OFF_DELAY_MS); + pm_runtime_use_autosuspend(&clientp->dev); + +- ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); ++ ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&clientp->dev, "%s: iio registration failed\n", + __func__); diff --git a/queue-6.0/iio-temperature-ltc2983-allocate-iio-channels-once.patch b/queue-6.0/iio-temperature-ltc2983-allocate-iio-channels-once.patch new file mode 100644 index 00000000000..5ab88316c4a --- /dev/null +++ b/queue-6.0/iio-temperature-ltc2983-allocate-iio-channels-once.patch @@ -0,0 +1,54 @@ +From 4132f19173211856d35180958d2754f5c56d520a Mon Sep 17 00:00:00 2001 +From: Cosmin Tanislav +Date: Fri, 14 Oct 2022 15:37:22 +0300 +Subject: iio: temperature: ltc2983: allocate iio channels once + +From: Cosmin Tanislav + +commit 4132f19173211856d35180958d2754f5c56d520a upstream. + +Currently, every time the device wakes up from sleep, the +iio_chan array is reallocated, leaking the previous one +until the device is removed (basically never). + +Move the allocation to the probe function to avoid this. + +Signed-off-by: Cosmin Tanislav +Fixes: f110f3188e563 ("iio: temperature: Add support for LTC2983") +Cc: +Link: https://lore.kernel.org/r/20221014123724.1401011-2-demonsingur@gmail.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/temperature/ltc2983.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/iio/temperature/ltc2983.c ++++ b/drivers/iio/temperature/ltc2983.c +@@ -1385,13 +1385,6 @@ static int ltc2983_setup(struct ltc2983_ + return ret; + } + +- st->iio_chan = devm_kzalloc(&st->spi->dev, +- st->iio_channels * sizeof(*st->iio_chan), +- GFP_KERNEL); +- +- if (!st->iio_chan) +- return -ENOMEM; +- + ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG, + LTC2983_NOTCH_FREQ_MASK, + LTC2983_NOTCH_FREQ(st->filter_notch_freq)); +@@ -1514,6 +1507,12 @@ static int ltc2983_probe(struct spi_devi + gpiod_set_value_cansleep(gpio, 0); + } + ++ st->iio_chan = devm_kzalloc(&spi->dev, ++ st->iio_channels * sizeof(*st->iio_chan), ++ GFP_KERNEL); ++ if (!st->iio_chan) ++ return -ENOMEM; ++ + ret = ltc2983_setup(st, true); + if (ret) + return ret; diff --git a/queue-6.0/series b/queue-6.0/series index 8a016c7ba3a..6985a6150f3 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -42,3 +42,10 @@ squashfs-fix-buffer-release-race-condition-in-readahead-code.patch xhci-add-quirk-to-reset-host-back-to-default-state-at-shutdown.patch xhci-pci-set-runtime-pm-as-default-policy-on-all-xhc-1.2-or-later-devices.patch xhci-remove-device-endpoints-from-bandwidth-list-when-freeing-the-device.patch +tools-iio-iio_utils-fix-digit-calculation.patch +iio-light-tsl2583-fix-module-unloading.patch +iio-temperature-ltc2983-allocate-iio-channels-once.patch +iio-adxl372-fix-unsafe-buffer-attributes.patch +iio-adxl367-fix-unsafe-buffer-attributes.patch +fbdev-stifb-fall-back-to-cfb_fillrect-on-32-bit-hcrx-cards.patch +fbdev-smscufx-fix-several-use-after-free-bugs.patch diff --git a/queue-6.0/tools-iio-iio_utils-fix-digit-calculation.patch b/queue-6.0/tools-iio-iio_utils-fix-digit-calculation.patch new file mode 100644 index 00000000000..c088e0388c4 --- /dev/null +++ b/queue-6.0/tools-iio-iio_utils-fix-digit-calculation.patch @@ -0,0 +1,42 @@ +From 72b2aa38191bcba28389b0e20bf6b4f15017ff2b Mon Sep 17 00:00:00 2001 +From: Matti Vaittinen +Date: Thu, 13 Oct 2022 15:04:04 +0300 +Subject: tools: iio: iio_utils: fix digit calculation + +From: Matti Vaittinen + +commit 72b2aa38191bcba28389b0e20bf6b4f15017ff2b upstream. + +The iio_utils uses a digit calculation in order to know length of the +file name containing a buffer number. The digit calculation does not +work for number 0. + +This leads to allocation of one character too small buffer for the +file-name when file name contains value '0'. (Eg. buffer0). + +Fix digit calculation by returning one digit to be present for number +'0'. + +Fixes: 096f9b862e60 ("tools:iio:iio_utils: implement digit calculation") +Signed-off-by: Matti Vaittinen +Link: https://lore.kernel.org/r/Y0f+tKCz+ZAIoroQ@dc75zzyyyyyyyyyyyyycy-3.rev.dnainternet.fi +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + tools/iio/iio_utils.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/tools/iio/iio_utils.c ++++ b/tools/iio/iio_utils.c +@@ -547,6 +547,10 @@ static int calc_digits(int num) + { + int count = 0; + ++ /* It takes a digit to represent zero */ ++ if (!num) ++ return 1; ++ + while (num != 0) { + num /= 10; + count++; -- 2.47.3