diff mbox series

[v2,3/8] iio: core: Switch to krealloc_array()

Message ID 20230721170022.3461-4-andriy.shevchenko@linux.intel.com (mailing list archive)
State Superseded
Headers show
Series iio: core: A few code cleanups and documentation fixes | expand

Commit Message

Andy Shevchenko July 21, 2023, 5 p.m. UTC
Let the krealloc_array() copy the original data and
check for a multiplication overflow.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Nuno Sa <nuno.sa@analog.com>
---
 drivers/iio/industrialio-core.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

Comments

Jonathan Cameron July 22, 2023, 5:28 p.m. UTC | #1
On Fri, 21 Jul 2023 20:00:17 +0300
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:

> Let the krealloc_array() copy the original data and
> check for a multiplication overflow.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Reviewed-by: Nuno Sa <nuno.sa@analog.com>
> ---
>  drivers/iio/industrialio-core.c | 20 +++++++-------------
>  1 file changed, 7 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index 4e45740331ee..6e28c2a3d223 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -1465,7 +1465,7 @@ int iio_device_register_sysfs_group(struct iio_dev *indio_dev,
>  	const struct attribute_group **new, **old = iio_dev_opaque->groups;
>  	unsigned int cnt = iio_dev_opaque->groupcounter;
>  
> -	new = krealloc(old, sizeof(*new) * (cnt + 2), GFP_KERNEL);
> +	new = krealloc_array(old, cnt + 2, sizeof(*new), GFP_KERNEL);
>  	if (!new)
>  		return -ENOMEM;
>  
> @@ -1483,13 +1483,13 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
>  {
>  	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
>  	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
> +	struct attribute **attrs, **attr, *clk = NULL;
>  	struct iio_dev_attr *p;
> -	struct attribute **attr, *clk = NULL;
>  
>  	/* First count elements in any existing group */
> -	if (indio_dev->info->attrs) {
> -		attr = indio_dev->info->attrs->attrs;
> -		while (*attr++ != NULL)
> +	attrs = indio_dev->info->attrs ? indio_dev->info->attrs->attrs : NULL;
> +	if (attrs) {
> +		for (attr = attrs; *attr; attr++)
>  			attrcount_orig++;
>  	}
>  	attrcount = attrcount_orig;
> @@ -1521,20 +1521,14 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
>  	if (clk)
>  		attrcount++;
>  
> +	/* Copy across original attributes, and point to original binary attributes */
>  	iio_dev_opaque->chan_attr_group.attrs =
> -		kcalloc(attrcount + 1,
> -			sizeof(iio_dev_opaque->chan_attr_group.attrs[0]),
> -			GFP_KERNEL);
> +		krealloc_array(attrs, attrcount + 1, sizeof(*attrs), GFP_KERNEL);


I'm a little lost, but isn't this realloc()ing attrs, which should be provided
by drivers as constant if it is set to indio_dev->info->attrs->attrs? 

That seems unlikely to work correctly, but I may well have lost track of the
flow and attrs points somewhere else at this point.  I guess it might work
as the realloc code will detect it can't resize that array.

Feels wrong approach however.



>  	if (iio_dev_opaque->chan_attr_group.attrs == NULL) {
>  		ret = -ENOMEM;
>  		goto error_clear_attrs;
>  	}
> -	/* Copy across original attributes, and point to original binary attributes */
>  	if (indio_dev->info->attrs) {
> -		memcpy(iio_dev_opaque->chan_attr_group.attrs,
> -		       indio_dev->info->attrs->attrs,
> -		       sizeof(iio_dev_opaque->chan_attr_group.attrs[0])
> -		       *attrcount_orig);
>  		iio_dev_opaque->chan_attr_group.is_visible =
>  			indio_dev->info->attrs->is_visible;
>  		iio_dev_opaque->chan_attr_group.bin_attrs =
Andy Shevchenko July 24, 2023, 10:37 a.m. UTC | #2
On Sat, Jul 22, 2023 at 06:28:20PM +0100, Jonathan Cameron wrote:
> On Fri, 21 Jul 2023 20:00:17 +0300
> Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:

...

> > +		krealloc_array(attrs, attrcount + 1, sizeof(*attrs), GFP_KERNEL);
> 
> 
> I'm a little lost, but isn't this realloc()ing attrs, which should be provided
> by drivers as constant if it is set to indio_dev->info->attrs->attrs? 
> 
> That seems unlikely to work correctly, but I may well have lost track of the
> flow and attrs points somewhere else at this point.  I guess it might work
> as the realloc code will detect it can't resize that array.

Argh!

The attrs are defined without const. So, basically to prevent code like this
we have to make sure our local variables are defined as const.

I will drop this hunk from the next version, need to think if it makes sense
to refactor and if so, in which way.
diff mbox series

Patch

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 4e45740331ee..6e28c2a3d223 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1465,7 +1465,7 @@  int iio_device_register_sysfs_group(struct iio_dev *indio_dev,
 	const struct attribute_group **new, **old = iio_dev_opaque->groups;
 	unsigned int cnt = iio_dev_opaque->groupcounter;
 
-	new = krealloc(old, sizeof(*new) * (cnt + 2), GFP_KERNEL);
+	new = krealloc_array(old, cnt + 2, sizeof(*new), GFP_KERNEL);
 	if (!new)
 		return -ENOMEM;
 
@@ -1483,13 +1483,13 @@  static int iio_device_register_sysfs(struct iio_dev *indio_dev)
 {
 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
 	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
+	struct attribute **attrs, **attr, *clk = NULL;
 	struct iio_dev_attr *p;
-	struct attribute **attr, *clk = NULL;
 
 	/* First count elements in any existing group */
-	if (indio_dev->info->attrs) {
-		attr = indio_dev->info->attrs->attrs;
-		while (*attr++ != NULL)
+	attrs = indio_dev->info->attrs ? indio_dev->info->attrs->attrs : NULL;
+	if (attrs) {
+		for (attr = attrs; *attr; attr++)
 			attrcount_orig++;
 	}
 	attrcount = attrcount_orig;
@@ -1521,20 +1521,14 @@  static int iio_device_register_sysfs(struct iio_dev *indio_dev)
 	if (clk)
 		attrcount++;
 
+	/* Copy across original attributes, and point to original binary attributes */
 	iio_dev_opaque->chan_attr_group.attrs =
-		kcalloc(attrcount + 1,
-			sizeof(iio_dev_opaque->chan_attr_group.attrs[0]),
-			GFP_KERNEL);
+		krealloc_array(attrs, attrcount + 1, sizeof(*attrs), GFP_KERNEL);
 	if (iio_dev_opaque->chan_attr_group.attrs == NULL) {
 		ret = -ENOMEM;
 		goto error_clear_attrs;
 	}
-	/* Copy across original attributes, and point to original binary attributes */
 	if (indio_dev->info->attrs) {
-		memcpy(iio_dev_opaque->chan_attr_group.attrs,
-		       indio_dev->info->attrs->attrs,
-		       sizeof(iio_dev_opaque->chan_attr_group.attrs[0])
-		       *attrcount_orig);
 		iio_dev_opaque->chan_attr_group.is_visible =
 			indio_dev->info->attrs->is_visible;
 		iio_dev_opaque->chan_attr_group.bin_attrs =