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

Configure Feed

Select the types of activity you want to include in your feed.

iio: consumers: ensure read buffers for labels and ext_info are page aligned

Attributes of iio providers are exposed via sysfs. Typically, providers
pass attribute values to the iio core, which handles formatting and
printing to sysfs. However, some attributes, such as labels or extended
info, are directly formatted and printed to sysfs by provider drivers
using sysfs_emit() and sysfs_emit_at(). These helpers assume the read
buffer, allocated by sysfs fop, is page-aligned. When these attributes
are accessed by consumer drivers, the read buffer is allocated by the
consumer and may not be page-aligned, leading to failures in the
provider's callback that utilizes sysfs_emit*.

Add a check to ensure that read buffers for labels and external info
attributes are page-aligned. Update the prototype documentation as well.

Signed-off-by: Matteo Martelli <matteomartelli3@gmail.com>
Link: https://patch.msgid.link/20241202-iio-kmalloc-align-v1-1-aa9568c03937@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Matteo Martelli and committed by
Jonathan Cameron
22ccb0a1 ca569513

+13 -2
+11
drivers/iio/inkern.c
··· 7 7 #include <linux/err.h> 8 8 #include <linux/export.h> 9 9 #include <linux/minmax.h> 10 + #include <linux/mm.h> 10 11 #include <linux/mutex.h> 11 12 #include <linux/property.h> 12 13 #include <linux/slab.h> ··· 990 989 { 991 990 const struct iio_chan_spec_ext_info *ext_info; 992 991 992 + if (!buf || offset_in_page(buf)) { 993 + pr_err("iio: invalid ext_info read buffer\n"); 994 + return -EINVAL; 995 + } 996 + 993 997 ext_info = iio_lookup_ext_info(chan, attr); 994 998 if (!ext_info) 995 999 return -EINVAL; ··· 1020 1014 1021 1015 ssize_t iio_read_channel_label(struct iio_channel *chan, char *buf) 1022 1016 { 1017 + if (!buf || offset_in_page(buf)) { 1018 + pr_err("iio: invalid label read buffer\n"); 1019 + return -EINVAL; 1020 + } 1021 + 1023 1022 return do_iio_read_channel_label(chan->indio_dev, chan->channel, buf); 1024 1023 } 1025 1024 EXPORT_SYMBOL_GPL(iio_read_channel_label);
+2 -2
include/linux/iio/consumer.h
··· 418 418 * @chan: The channel being queried. 419 419 * @attr: The ext_info attribute to read. 420 420 * @buf: Where to store the attribute value. Assumed to hold 421 - * at least PAGE_SIZE bytes. 421 + * at least PAGE_SIZE bytes and to be aligned at PAGE_SIZE. 422 422 * 423 423 * Returns the number of bytes written to buf (perhaps w/o zero termination; 424 424 * it need not even be a string), or an error code. ··· 445 445 * iio_read_channel_label() - read label for a given channel 446 446 * @chan: The channel being queried. 447 447 * @buf: Where to store the attribute value. Assumed to hold 448 - * at least PAGE_SIZE bytes. 448 + * at least PAGE_SIZE bytes and to be aligned at PAGE_SIZE. 449 449 * 450 450 * Returns the number of bytes written to buf, or an error code. 451 451 */