public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
@ 2020-09-23 13:53 Vadym Kochan
  2020-09-23 14:10 ` Srinivas Kandagatla
  0 siblings, 1 reply; 10+ messages in thread
From: Vadym Kochan @ 2020-09-23 13:53 UTC (permalink / raw)
  To: Srinivas Kandagatla, Greg Kroah-Hartman, linux-kernel; +Cc: Vadym Kochan

Fix missing 'kfree_const(cell->name)' when call to
nvmem_cell_info_to_nvmem_cell() in several places:

     * after nvmem_cell_info_to_nvmem_cell() failed during
       nvmem_add_cells()

     * during nvmem_device_cell_{read,write}. This is fixed by simply
       re-using info->name instead of duplicating it:

           cell->name = info->name

Because cell->name is not used except for error message printing in case
of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
was introduced.

Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
Signed-off-by: Vadym Kochan <vadym.kochan@plvision.eu>
---
v2:
    * remove not needed 'kfree_const(cell->name)' after nvmem_cell_info_to_nvmem_cell()
      failed.

 drivers/nvmem/core.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..e6d1bc414faf 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
 }
 
-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
-				   const struct nvmem_cell_info *info,
-				   struct nvmem_cell *cell)
+static int
+__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+				const struct nvmem_cell_info *info,
+				struct nvmem_cell *cell)
 {
 	cell->nvmem = nvmem;
 	cell->offset = info->offset;
 	cell->bytes = info->bytes;
-	cell->name = kstrdup_const(info->name, GFP_KERNEL);
-	if (!cell->name)
-		return -ENOMEM;
+	cell->name = info->name;
 
 	cell->bit_offset = info->bit_offset;
 	cell->nbits = info->nbits;
@@ -382,13 +381,31 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
 	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
 		dev_err(&nvmem->dev,
 			"cell %s unaligned to nvmem stride %d\n",
-			cell->name, nvmem->stride);
+			cell->name ?: "<unknown>", nvmem->stride);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
+static int
+nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+			      const struct nvmem_cell_info *info,
+			      struct nvmem_cell *cell)
+{
+	int err;
+
+	err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
+	if (err)
+		return err;
+
+	cell->name = kstrdup_const(info->name, GFP_KERNEL);
+	if (!cell->name)
+		return -ENOMEM;
+
+	return 0;
+}
+
 /**
  * nvmem_add_cells() - Add cell information to an nvmem device
  *
@@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
 	if (!nvmem)
 		return -EINVAL;
 
-	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
 	if (rc)
 		return rc;
 
@@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
 	if (!nvmem)
 		return -EINVAL;
 
-	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
 	if (rc)
 		return rc;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 13:53 [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell() Vadym Kochan
@ 2020-09-23 14:10 ` Srinivas Kandagatla
  2020-09-23 14:13   ` Vadym Kochan
  0 siblings, 1 reply; 10+ messages in thread
From: Srinivas Kandagatla @ 2020-09-23 14:10 UTC (permalink / raw)
  To: Vadym Kochan, Greg Kroah-Hartman, linux-kernel



On 23/09/2020 14:53, Vadym Kochan wrote:
> Fix missing 'kfree_const(cell->name)' when call to
> nvmem_cell_info_to_nvmem_cell() in several places:
> 
>       * after nvmem_cell_info_to_nvmem_cell() failed during
>         nvmem_add_cells()
> 
>       * during nvmem_device_cell_{read,write}. This is fixed by simply
>         re-using info->name instead of duplicating it:
> 
>             cell->name = info->name
> 
> Because cell->name is not used except for error message printing in case
> of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
> was introduced.
> 
> Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
> Signed-off-by: Vadym Kochan <vadym.kochan@plvision.eu>
> ---
> v2:
>      * remove not needed 'kfree_const(cell->name)' after nvmem_cell_info_to_nvmem_cell()
>        failed.
> 
>   drivers/nvmem/core.c | 35 ++++++++++++++++++++++++++---------
>   1 file changed, 26 insertions(+), 9 deletions(-)



Really :-)


Below change should just fix this the reported issue!
------------------------>cut<---------------------------

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..9fb9112fe75d 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct 
nvmem_device *nvmem,
                 dev_err(&nvmem->dev,
                         "cell %s unaligned to nvmem stride %d\n",
                         cell->name, nvmem->stride);
+               kfree_const(cell->name);
                 return -EINVAL;
         }

------------------------>cut<---------------------------

I don't see a point in the way your patch try to fix this!!


--srini

> 
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index 6cd3edb2eaf6..e6d1bc414faf 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
>   	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
>   }
>   
> -static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> -				   const struct nvmem_cell_info *info,
> -				   struct nvmem_cell *cell)
> +static int
> +__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> +				const struct nvmem_cell_info *info,
> +				struct nvmem_cell *cell)
>   {
>   	cell->nvmem = nvmem;
>   	cell->offset = info->offset;
>   	cell->bytes = info->bytes;
> -	cell->name = kstrdup_const(info->name, GFP_KERNEL);
> -	if (!cell->name)
> -		return -ENOMEM;
> +	cell->name = info->name;
>   
>   	cell->bit_offset = info->bit_offset;
>   	cell->nbits = info->nbits;
> @@ -382,13 +381,31 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
>   	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
>   		dev_err(&nvmem->dev,
>   			"cell %s unaligned to nvmem stride %d\n",
> -			cell->name, nvmem->stride);
> +			cell->name ?: "<unknown>", nvmem->stride);
>   		return -EINVAL;
>   	}
>   
>   	return 0;
>   }
>   
> +static int
> +nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> +			      const struct nvmem_cell_info *info,
> +			      struct nvmem_cell *cell)
> +{
> +	int err;
> +
> +	err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
> +	if (err)
> +		return err;
> +
> +	cell->name = kstrdup_const(info->name, GFP_KERNEL);
> +	if (!cell->name)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
>   /**
>    * nvmem_add_cells() - Add cell information to an nvmem device
>    *
> @@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
>   	if (!nvmem)
>   		return -EINVAL;
>   
> -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
>   	if (rc)
>   		return rc;
>   
> @@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
>   	if (!nvmem)
>   		return -EINVAL;
>   
> -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
>   	if (rc)
>   		return rc;
>   
> 

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 14:10 ` Srinivas Kandagatla
@ 2020-09-23 14:13   ` Vadym Kochan
  2020-09-23 14:47     ` Srinivas Kandagatla
  0 siblings, 1 reply; 10+ messages in thread
From: Vadym Kochan @ 2020-09-23 14:13 UTC (permalink / raw)
  To: Srinivas Kandagatla; +Cc: Greg Kroah-Hartman, linux-kernel

On Wed, Sep 23, 2020 at 03:10:36PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 14:53, Vadym Kochan wrote:
> > Fix missing 'kfree_const(cell->name)' when call to
> > nvmem_cell_info_to_nvmem_cell() in several places:
> > 
> >       * after nvmem_cell_info_to_nvmem_cell() failed during
> >         nvmem_add_cells()
> > 
> >       * during nvmem_device_cell_{read,write}. This is fixed by simply
> >         re-using info->name instead of duplicating it:
> > 
> >             cell->name = info->name
> > 
> > Because cell->name is not used except for error message printing in case
> > of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
> > was introduced.
> > 
> > Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
> > Signed-off-by: Vadym Kochan <vadym.kochan@plvision.eu>
> > ---
> > v2:
> >      * remove not needed 'kfree_const(cell->name)' after nvmem_cell_info_to_nvmem_cell()
> >        failed.
> > 
> >   drivers/nvmem/core.c | 35 ++++++++++++++++++++++++++---------
> >   1 file changed, 26 insertions(+), 9 deletions(-)
> 
> 
> 
> Really :-)
> 
But what about nvmem_device_cell_{read,write} case ?
In my understanding the cell is allocated on the stack but kstrdup() is
not freed in the end, or I missed something ?

> 
> Below change should just fix this the reported issue!
> ------------------------>cut<---------------------------
> 
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index 6cd3edb2eaf6..9fb9112fe75d 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct
> nvmem_device *nvmem,
>                 dev_err(&nvmem->dev,
>                         "cell %s unaligned to nvmem stride %d\n",
>                         cell->name, nvmem->stride);
> +               kfree_const(cell->name);
>                 return -EINVAL;
>         }
> 
> ------------------------>cut<---------------------------
> 
> I don't see a point in the way your patch try to fix this!!
> 
> 
> --srini
> 
> > 
> > diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> > index 6cd3edb2eaf6..e6d1bc414faf 100644
> > --- a/drivers/nvmem/core.c
> > +++ b/drivers/nvmem/core.c
> > @@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
> >   	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
> >   }
> > -static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > -				   const struct nvmem_cell_info *info,
> > -				   struct nvmem_cell *cell)
> > +static int
> > +__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > +				const struct nvmem_cell_info *info,
> > +				struct nvmem_cell *cell)
> >   {
> >   	cell->nvmem = nvmem;
> >   	cell->offset = info->offset;
> >   	cell->bytes = info->bytes;
> > -	cell->name = kstrdup_const(info->name, GFP_KERNEL);
> > -	if (!cell->name)
> > -		return -ENOMEM;
> > +	cell->name = info->name;
> >   	cell->bit_offset = info->bit_offset;
> >   	cell->nbits = info->nbits;
> > @@ -382,13 +381,31 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> >   	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
> >   		dev_err(&nvmem->dev,
> >   			"cell %s unaligned to nvmem stride %d\n",
> > -			cell->name, nvmem->stride);
> > +			cell->name ?: "<unknown>", nvmem->stride);
> >   		return -EINVAL;
> >   	}
> >   	return 0;
> >   }
> > +static int
> > +nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > +			      const struct nvmem_cell_info *info,
> > +			      struct nvmem_cell *cell)
> > +{
> > +	int err;
> > +
> > +	err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
> > +	if (err)
> > +		return err;
> > +
> > +	cell->name = kstrdup_const(info->name, GFP_KERNEL);
> > +	if (!cell->name)
> > +		return -ENOMEM;
> > +
> > +	return 0;
> > +}
> > +
> >   /**
> >    * nvmem_add_cells() - Add cell information to an nvmem device
> >    *
> > @@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
> >   	if (!nvmem)
> >   		return -EINVAL;
> > -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> > +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> >   	if (rc)
> >   		return rc;
> > @@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
> >   	if (!nvmem)
> >   		return -EINVAL;
> > -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> > +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> >   	if (rc)
> >   		return rc;
> > 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 14:13   ` Vadym Kochan
@ 2020-09-23 14:47     ` Srinivas Kandagatla
  2020-09-23 14:51       ` Vadym Kochan
  0 siblings, 1 reply; 10+ messages in thread
From: Srinivas Kandagatla @ 2020-09-23 14:47 UTC (permalink / raw)
  To: Vadym Kochan; +Cc: Greg Kroah-Hartman, linux-kernel



On 23/09/2020 15:13, Vadym Kochan wrote:
> On Wed, Sep 23, 2020 at 03:10:36PM +0100, Srinivas Kandagatla wrote:
>>
>>
>> On 23/09/2020 14:53, Vadym Kochan wrote:
>>> Fix missing 'kfree_const(cell->name)' when call to
>>> nvmem_cell_info_to_nvmem_cell() in several places:
>>>
>>>        * after nvmem_cell_info_to_nvmem_cell() failed during
>>>          nvmem_add_cells()
>>>
>>>        * during nvmem_device_cell_{read,write}. This is fixed by simply
>>>          re-using info->name instead of duplicating it:
>>>
>>>              cell->name = info->name
>>>
>>> Because cell->name is not used except for error message printing in case
>>> of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
>>> was introduced.
>>>
>>> Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
>>> Signed-off-by: Vadym Kochan <vadym.kochan@plvision.eu>
>>> ---
>>> v2:
>>>       * remove not needed 'kfree_const(cell->name)' after nvmem_cell_info_to_nvmem_cell()
>>>         failed.
>>>
>>>    drivers/nvmem/core.c | 35 ++++++++++++++++++++++++++---------
>>>    1 file changed, 26 insertions(+), 9 deletions(-)
>>
>>
>>
>> Really :-)
>>
> But what about nvmem_device_cell_{read,write} case ?
> In my understanding the cell is allocated on the stack but kstrdup() is
You are right!

That is the second issue where the caller outside would fail after 
successful call to nvmem_cell_info_to_nvmem_cell() .

Probably we cam free it in failure cases!
something like:

------------------------>cut<---------------------------
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 6cd3edb2eaf6..fb1e756adcee 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct 
nvmem_device *nvmem,
                 dev_err(&nvmem->dev,
                         "cell %s unaligned to nvmem stride %d\n",
                         cell->name, nvmem->stride);
+               kfree_const(cell->name);
                 return -EINVAL;
         }

@@ -1465,8 +1466,10 @@ ssize_t nvmem_device_cell_read(struct 
nvmem_device *nvmem,
                 return rc;

         rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
-       if (rc)
+       if (rc) {
+               kfree_const(cell->name);
                 return rc;
+       }

         return len;
  }
@@ -1494,7 +1497,11 @@ int nvmem_device_cell_write(struct nvmem_device 
*nvmem,
         if (rc)
                 return rc;

-       return nvmem_cell_write(&cell, buf, cell.bytes);
+       rc = nvmem_cell_write(&cell, buf, cell.bytes);
+       if (rc)
+               kfree_const(cell->name);
+
+       return rc;
  }
  EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
  ------------------------>cut<---------------------------

--srini

> not freed in the end, or I missed something ?
> 
>>
>> Below change should just fix this the reported issue!
>> ------------------------>cut<---------------------------
>>
>> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
>> index 6cd3edb2eaf6..9fb9112fe75d 100644
>> --- a/drivers/nvmem/core.c
>> +++ b/drivers/nvmem/core.c
>> @@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct
>> nvmem_device *nvmem,
>>                  dev_err(&nvmem->dev,
>>                          "cell %s unaligned to nvmem stride %d\n",
>>                          cell->name, nvmem->stride);
>> +               kfree_const(cell->name);
>>                  return -EINVAL;
>>          }
>>
>> ------------------------>cut<---------------------------
>>
>> I don't see a point in the way your patch try to fix this!!
>>
>>
>> --srini
>>
>>>
>>> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
>>> index 6cd3edb2eaf6..e6d1bc414faf 100644
>>> --- a/drivers/nvmem/core.c
>>> +++ b/drivers/nvmem/core.c
>>> @@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
>>>    	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
>>>    }
>>> -static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
>>> -				   const struct nvmem_cell_info *info,
>>> -				   struct nvmem_cell *cell)
>>> +static int
>>> +__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
>>> +				const struct nvmem_cell_info *info,
>>> +				struct nvmem_cell *cell)
>>>    {
>>>    	cell->nvmem = nvmem;
>>>    	cell->offset = info->offset;
>>>    	cell->bytes = info->bytes;
>>> -	cell->name = kstrdup_const(info->name, GFP_KERNEL);
>>> -	if (!cell->name)
>>> -		return -ENOMEM;
>>> +	cell->name = info->name;
>>>    	cell->bit_offset = info->bit_offset;
>>>    	cell->nbits = info->nbits;
>>> @@ -382,13 +381,31 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
>>>    	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
>>>    		dev_err(&nvmem->dev,
>>>    			"cell %s unaligned to nvmem stride %d\n",
>>> -			cell->name, nvmem->stride);
>>> +			cell->name ?: "<unknown>", nvmem->stride);
>>>    		return -EINVAL;
>>>    	}
>>>    	return 0;
>>>    }
>>> +static int
>>> +nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
>>> +			      const struct nvmem_cell_info *info,
>>> +			      struct nvmem_cell *cell)
>>> +{
>>> +	int err;
>>> +
>>> +	err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
>>> +	if (err)
>>> +		return err;
>>> +
>>> +	cell->name = kstrdup_const(info->name, GFP_KERNEL);
>>> +	if (!cell->name)
>>> +		return -ENOMEM;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>    /**
>>>     * nvmem_add_cells() - Add cell information to an nvmem device
>>>     *
>>> @@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
>>>    	if (!nvmem)
>>>    		return -EINVAL;
>>> -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
>>> +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
>>>    	if (rc)
>>>    		return rc;
>>> @@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
>>>    	if (!nvmem)
>>>    		return -EINVAL;
>>> -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
>>> +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
>>>    	if (rc)
>>>    		return rc;
>>>

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 14:47     ` Srinivas Kandagatla
@ 2020-09-23 14:51       ` Vadym Kochan
  2020-09-23 15:51         ` Srinivas Kandagatla
  0 siblings, 1 reply; 10+ messages in thread
From: Vadym Kochan @ 2020-09-23 14:51 UTC (permalink / raw)
  To: Srinivas Kandagatla; +Cc: Greg Kroah-Hartman, linux-kernel

On Wed, Sep 23, 2020 at 03:47:14PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 15:13, Vadym Kochan wrote:
> > On Wed, Sep 23, 2020 at 03:10:36PM +0100, Srinivas Kandagatla wrote:
> > > 
> > > 
> > > On 23/09/2020 14:53, Vadym Kochan wrote:
> > > > Fix missing 'kfree_const(cell->name)' when call to
> > > > nvmem_cell_info_to_nvmem_cell() in several places:
> > > > 
> > > >        * after nvmem_cell_info_to_nvmem_cell() failed during
> > > >          nvmem_add_cells()
> > > > 
> > > >        * during nvmem_device_cell_{read,write}. This is fixed by simply
> > > >          re-using info->name instead of duplicating it:
> > > > 
> > > >              cell->name = info->name
> > > > 
> > > > Because cell->name is not used except for error message printing in case
> > > > of un-aligned access, the new __nvmem_cell_info_to_nvmem_cell() helper
> > > > was introduced.
> > > > 
> > > > Fixes: e2a5402ec7c6 ("nvmem: Add nvmem_device based consumer apis.")
> > > > Signed-off-by: Vadym Kochan <vadym.kochan@plvision.eu>
> > > > ---
> > > > v2:
> > > >       * remove not needed 'kfree_const(cell->name)' after nvmem_cell_info_to_nvmem_cell()
> > > >         failed.
> > > > 
> > > >    drivers/nvmem/core.c | 35 ++++++++++++++++++++++++++---------
> > > >    1 file changed, 26 insertions(+), 9 deletions(-)
> > > 
> > > 
> > > 
> > > Really :-)
> > > 
> > But what about nvmem_device_cell_{read,write} case ?
> > In my understanding the cell is allocated on the stack but kstrdup() is
> You are right!
> 
> That is the second issue where the caller outside would fail after
> successful call to nvmem_cell_info_to_nvmem_cell() .
> 
> Probably we cam free it in failure cases!
> something like:
> 
> ------------------------>cut<---------------------------
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index 6cd3edb2eaf6..fb1e756adcee 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
> @@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct
> nvmem_device *nvmem,
>                 dev_err(&nvmem->dev,
>                         "cell %s unaligned to nvmem stride %d\n",
>                         cell->name, nvmem->stride);
> +               kfree_const(cell->name);
>                 return -EINVAL;
>         }
> 
> @@ -1465,8 +1466,10 @@ ssize_t nvmem_device_cell_read(struct nvmem_device
> *nvmem,
>                 return rc;
> 
>         rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
> -       if (rc)
> +       if (rc) {
> +               kfree_const(cell->name);
>                 return rc;
> +       }
> 
>         return len;
>  }
> @@ -1494,7 +1497,11 @@ int nvmem_device_cell_write(struct nvmem_device
> *nvmem,
>         if (rc)
>                 return rc;
> 
> -       return nvmem_cell_write(&cell, buf, cell.bytes);
> +       rc = nvmem_cell_write(&cell, buf, cell.bytes);
> +       if (rc)
> +               kfree_const(cell->name);
> +
> +       return rc;
>  }
>  EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
>  ------------------------>cut<---------------------------
> 
> --srini
> 

But is it really needed to kstrdup(cell->name) for nvmem_device_cell_{read,write} ?
It is used only for log error in case the unaligned access did not
pass the check.

> > not freed in the end, or I missed something ?
> > 
> > > 
> > > Below change should just fix this the reported issue!
> > > ------------------------>cut<---------------------------
> > > 
> > > diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> > > index 6cd3edb2eaf6..9fb9112fe75d 100644
> > > --- a/drivers/nvmem/core.c
> > > +++ b/drivers/nvmem/core.c
> > > @@ -383,6 +383,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct
> > > nvmem_device *nvmem,
> > >                  dev_err(&nvmem->dev,
> > >                          "cell %s unaligned to nvmem stride %d\n",
> > >                          cell->name, nvmem->stride);
> > > +               kfree_const(cell->name);
> > >                  return -EINVAL;
> > >          }
> > > 
> > > ------------------------>cut<---------------------------
> > > 
> > > I don't see a point in the way your patch try to fix this!!
> > > 
> > > 
> > > --srini
> > > 
> > > > 
> > > > diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> > > > index 6cd3edb2eaf6..e6d1bc414faf 100644
> > > > --- a/drivers/nvmem/core.c
> > > > +++ b/drivers/nvmem/core.c
> > > > @@ -361,16 +361,15 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
> > > >    	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
> > > >    }
> > > > -static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > > > -				   const struct nvmem_cell_info *info,
> > > > -				   struct nvmem_cell *cell)
> > > > +static int
> > > > +__nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > > > +				const struct nvmem_cell_info *info,
> > > > +				struct nvmem_cell *cell)
> > > >    {
> > > >    	cell->nvmem = nvmem;
> > > >    	cell->offset = info->offset;
> > > >    	cell->bytes = info->bytes;
> > > > -	cell->name = kstrdup_const(info->name, GFP_KERNEL);
> > > > -	if (!cell->name)
> > > > -		return -ENOMEM;
> > > > +	cell->name = info->name;
> > > >    	cell->bit_offset = info->bit_offset;
> > > >    	cell->nbits = info->nbits;
> > > > @@ -382,13 +381,31 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > > >    	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
> > > >    		dev_err(&nvmem->dev,
> > > >    			"cell %s unaligned to nvmem stride %d\n",
> > > > -			cell->name, nvmem->stride);
> > > > +			cell->name ?: "<unknown>", nvmem->stride);
> > > >    		return -EINVAL;
> > > >    	}
> > > >    	return 0;
> > > >    }
> > > > +static int
> > > > +nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
> > > > +			      const struct nvmem_cell_info *info,
> > > > +			      struct nvmem_cell *cell)
> > > > +{
> > > > +	int err;
> > > > +
> > > > +	err = __nvmem_cell_info_to_nvmem_cell(nvmem, info, cell);
> > > > +	if (err)
> > > > +		return err;
> > > > +
> > > > +	cell->name = kstrdup_const(info->name, GFP_KERNEL);
> > > > +	if (!cell->name)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > >    /**
> > > >     * nvmem_add_cells() - Add cell information to an nvmem device
> > > >     *
> > > > @@ -1460,7 +1477,7 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
> > > >    	if (!nvmem)
> > > >    		return -EINVAL;
> > > > -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> > > > +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> > > >    	if (rc)
> > > >    		return rc;
> > > > @@ -1490,7 +1507,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
> > > >    	if (!nvmem)
> > > >    		return -EINVAL;
> > > > -	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> > > > +	rc = __nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
> > > >    	if (rc)
> > > >    		return rc;
> > > > 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 14:51       ` Vadym Kochan
@ 2020-09-23 15:51         ` Srinivas Kandagatla
  2020-09-23 16:02           ` Vadym Kochan
  2020-09-23 16:23           ` Vadym Kochan
  0 siblings, 2 replies; 10+ messages in thread
From: Srinivas Kandagatla @ 2020-09-23 15:51 UTC (permalink / raw)
  To: Vadym Kochan; +Cc: Greg Kroah-Hartman, linux-kernel



On 23/09/2020 15:51, Vadym Kochan wrote:
>> -       return nvmem_cell_write(&cell, buf, cell.bytes);
>> +       rc = nvmem_cell_write(&cell, buf, cell.bytes);
>> +       if (rc)
>> +               kfree_const(cell->name);
>> +
>> +       return rc;
>>   }
>>   EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
>>   ------------------------>cut<---------------------------
>>
>> --srini
>>
> But is it really needed to kstrdup(cell->name) for nvmem_device_cell_{read,write} ?
This boils down to if we want to use same api to parse nvmem_cell_info 
or not!

If we want to keep this simple, we can either explicitly add free for 
successful caller to nvmem_cell_info_to_nvmem_cell()!

Or

use something like what you did, but new api needs more clarity!
May be renaming __nvmem_cell_info_to_nvmem_cell to 
nvmem_cell_info_to_nvmem_cell_no_alloc would clarify that a bit!

Also can you make sure that linewrapping on function names be inline 
with existing code.

Please send v3 with that changes!


--srini
> It is used only for log error in case the unaligned access did not
> pass the check

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 15:51         ` Srinivas Kandagatla
@ 2020-09-23 16:02           ` Vadym Kochan
  2020-09-23 16:03             ` Srinivas Kandagatla
  2020-09-23 16:23           ` Vadym Kochan
  1 sibling, 1 reply; 10+ messages in thread
From: Vadym Kochan @ 2020-09-23 16:02 UTC (permalink / raw)
  To: Srinivas Kandagatla; +Cc: Greg Kroah-Hartman, linux-kernel

On Wed, Sep 23, 2020 at 04:51:06PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 15:51, Vadym Kochan wrote:
> > > -       return nvmem_cell_write(&cell, buf, cell.bytes);
> > > +       rc = nvmem_cell_write(&cell, buf, cell.bytes);
> > > +       if (rc)
> > > +               kfree_const(cell->name);
> > > +
> > > +       return rc;
> > >   }
> > >   EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
> > >   ------------------------>cut<---------------------------
> > > 
> > > --srini
> > > 
> > But is it really needed to kstrdup(cell->name) for nvmem_device_cell_{read,write} ?
> This boils down to if we want to use same api to parse nvmem_cell_info or
> not!
> 
> If we want to keep this simple, we can either explicitly add free for
> successful caller to nvmem_cell_info_to_nvmem_cell()!
> 

I think that such additional kfree_const(cell->name) handling adds more
complexity for error handling, also to my understanding usually
resource allocation should be done in the called func in case of error
was returned.

> Or
> 
> use something like what you did, but new api needs more clarity!
> May be renaming __nvmem_cell_info_to_nvmem_cell to
> nvmem_cell_info_to_nvmem_cell_no_alloc would clarify that a bit!
> 

Yes, I agree that naming should be better, actually "__" already points
to it's unsafety (no kstrdup() is used), but of course additional suffix
would be better.

> Also can you make sure that linewrapping on function names be inline with
> existing code.

You mean do not do such func attributes breaking as I did (moved them
line upper) ?

> 
> Please send v3 with that changes!
> 
> 
> --srini
> > It is used only for log error in case the unaligned access did not
> > pass the check

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 16:02           ` Vadym Kochan
@ 2020-09-23 16:03             ` Srinivas Kandagatla
  0 siblings, 0 replies; 10+ messages in thread
From: Srinivas Kandagatla @ 2020-09-23 16:03 UTC (permalink / raw)
  To: Vadym Kochan; +Cc: Greg Kroah-Hartman, linux-kernel



On 23/09/2020 17:02, Vadym Kochan wrote:
> You mean do not do such func attributes breaking as I did (moved them
> line upper) ?
yes, for consistency reasons!

--srini
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 15:51         ` Srinivas Kandagatla
  2020-09-23 16:02           ` Vadym Kochan
@ 2020-09-23 16:23           ` Vadym Kochan
  2020-09-23 16:25             ` Srinivas Kandagatla
  1 sibling, 1 reply; 10+ messages in thread
From: Vadym Kochan @ 2020-09-23 16:23 UTC (permalink / raw)
  To: Srinivas Kandagatla; +Cc: Greg Kroah-Hartman, linux-kernel

On Wed, Sep 23, 2020 at 04:51:06PM +0100, Srinivas Kandagatla wrote:
> 
> 
> On 23/09/2020 15:51, Vadym Kochan wrote:
> > > -       return nvmem_cell_write(&cell, buf, cell.bytes);
> > > +       rc = nvmem_cell_write(&cell, buf, cell.bytes);
> > > +       if (rc)
> > > +               kfree_const(cell->name);
> > > +
> > > +       return rc;
> > >   }
> > >   EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
> > >   ------------------------>cut<---------------------------
> > > 
> > > --srini
> > > 
> > But is it really needed to kstrdup(cell->name) for nvmem_device_cell_{read,write} ?
> This boils down to if we want to use same api to parse nvmem_cell_info or
> not!
> 
> If we want to keep this simple, we can either explicitly add free for
> successful caller to nvmem_cell_info_to_nvmem_cell()!
> 
> Or
> 
> use something like what you did, but new api needs more clarity!
> May be renaming __nvmem_cell_info_to_nvmem_cell to
> nvmem_cell_info_to_nvmem_cell_no_alloc would clarify that a bit!
> 

Naming is most difficult thing, what about __nvmem_cell_info_to_nvmem_cell_{unsafe,nodup}() ?
At least this is an indication to be carefully here.

> Also can you make sure that linewrapping on function names be inline with
> existing code.
> 
> Please send v3 with that changes!
> 
> 
> --srini
> > It is used only for log error in case the unaligned access did not
> > pass the check

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
  2020-09-23 16:23           ` Vadym Kochan
@ 2020-09-23 16:25             ` Srinivas Kandagatla
  0 siblings, 0 replies; 10+ messages in thread
From: Srinivas Kandagatla @ 2020-09-23 16:25 UTC (permalink / raw)
  To: Vadym Kochan; +Cc: Greg Kroah-Hartman, linux-kernel



On 23/09/2020 17:23, Vadym Kochan wrote:
> On Wed, Sep 23, 2020 at 04:51:06PM +0100, Srinivas Kandagatla wrote:
>>
>>
>> On 23/09/2020 15:51, Vadym Kochan wrote:
>>>> -       return nvmem_cell_write(&cell, buf, cell.bytes);
>>>> +       rc = nvmem_cell_write(&cell, buf, cell.bytes);
>>>> +       if (rc)
>>>> +               kfree_const(cell->name);
>>>> +
>>>> +       return rc;
>>>>    }
>>>>    EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
>>>>    ------------------------>cut<---------------------------
>>>>
>>>> --srini
>>>>
>>> But is it really needed to kstrdup(cell->name) for nvmem_device_cell_{read,write} ?
>> This boils down to if we want to use same api to parse nvmem_cell_info or
>> not!
>>
>> If we want to keep this simple, we can either explicitly add free for
>> successful caller to nvmem_cell_info_to_nvmem_cell()!
>>
>> Or
>>
>> use something like what you did, but new api needs more clarity!
>> May be renaming __nvmem_cell_info_to_nvmem_cell to
>> nvmem_cell_info_to_nvmem_cell_no_alloc would clarify that a bit!
>>
> 
> Naming is most difficult thing, what about __nvmem_cell_info_to_nvmem_cell_{unsafe,nodup}() ?
> At least this is an indication to be carefully here.

nvmem_cell_info_to_nvmem_cell_nodup() should be good!

--srini
> 
>> Also can you make sure that linewrapping on function names be inline with
>> existing code.
>>
>> Please send v3 with that changes!
>>
>>
>> --srini
>>> It is used only for log error in case the unaligned access did not
>>> pass the check

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-09-23 16:25 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-09-23 13:53 [PATCH v2] nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell() Vadym Kochan
2020-09-23 14:10 ` Srinivas Kandagatla
2020-09-23 14:13   ` Vadym Kochan
2020-09-23 14:47     ` Srinivas Kandagatla
2020-09-23 14:51       ` Vadym Kochan
2020-09-23 15:51         ` Srinivas Kandagatla
2020-09-23 16:02           ` Vadym Kochan
2020-09-23 16:03             ` Srinivas Kandagatla
2020-09-23 16:23           ` Vadym Kochan
2020-09-23 16:25             ` Srinivas Kandagatla

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox