public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter@oracle.com>
To: Suganath Prabu S <suganath-prabu.subramani@broadcom.com>
Cc: linux-scsi@vger.kernel.org, Sathya.Prakash@broadcom.com,
	sreekanth.reddy@broadcom.com
Subject: Re: [PATCH] mpt3sas: Fix double free warnings
Date: Fri, 8 May 2020 14:36:22 +0300	[thread overview]
Message-ID: <20200508113622.GP1992@kadam> (raw)
In-Reply-To: <20200508091854.32748-1-suganath-prabu.subramani@broadcom.com>

On Fri, May 08, 2020 at 05:18:54AM -0400, Suganath Prabu S wrote:
> Fix below warnings from Smatch static analyser:
> drivers/scsi/mpt3sas/mpt3sas_base.c:5256 _base_allocate_memory_pools()
> warn: 'ioc->hpr_lookup' double freed
> 
> drivers/scsi/mpt3sas/mpt3sas_base.c:5256 _base_allocate_memory_pools()
> warn: 'ioc->internal_lookup' double freed
> 
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> Signed-off-by: Suganath Prabu <suganath-prabu.subramani@broadcom.com>
> ---
>  drivers/scsi/mpt3sas/mpt3sas_base.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
> index 7fa3bdb..a6dbc73 100644
> --- a/drivers/scsi/mpt3sas/mpt3sas_base.c
> +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
> @@ -4898,8 +4898,14 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
>  		    ioc->config_page, ioc->config_page_dma);
>  	}
>  
> -	kfree(ioc->hpr_lookup);
> -	kfree(ioc->internal_lookup);
> +	if (ioc->hpr_lookup) {
> +		kfree(ioc->hpr_lookup);
> +		ioc->hpr_lookup = NULL;
> +	}
> +	if (ioc->internal_lookup) {
> +		kfree(ioc->internal_lookup);
> +		ioc->internal_lookup = NULL;
> +	}


We could remove the if statements because kfree()ing a NULL is a no-op.
I think the build bots will automatically send a patch suggesting to do
that when they see this patch.

Really there is no way that these massive free everything in every
situation functions will ever work 100%.  There is a simple and correct
method to do error handling which is the "Free the most recent
allocation" method.

1) Every function cleans up it's own allocations.
2) Every allocation function has a mirrored free function.
3) Always use clear label names like "goto free_variable_x;"
4) The goto should free the most recent allocation.

The results of rule number 4 are:
1) You never free things which haven't been allocated.
2) The error handling is in the reverse/mirror order from the allocation
3) The error handling is simple because you only need to remember the
   most recent allocation.  Easy to audit.  No leaks.  No bugs.

It looks like this in practice.

int my_func(void)
{
	a = alloc();
	if (!a)
		return -ENOMEM;

	b = alloc();
	if (!b) {
		ret = -ENOMEM:
		goto free_a;
	}

	c = alloc();
	if (!c) {
		ret = -ENOMEM;
		goto free_b;
	}

	return 0;

free_b:
	free(b);
free_a:
	free(a);
	return ret;
}

Then cut and paste and add a free(c); to create the free function.

void my_free_func(void)
{
	free(c);
	free(b);
	free(a);
}

This method removes all the if statements in the error handling path but
it uses more labels so the number of lines is basically the same.  There
is one more rule for unwinding from loops and this code has a lot of
looped allocations:  Release the partial iteration before breaking
from the loop.

	for (i = 0; i < count; i++) {
		array[i].a = alloc();
		if (!array[i].a) {
			ret = -ENOMEM;
			goto unwind;
		}

		array[i].b = alloc();
		if (!array[i].b) {
			free(array[i].a);
			ret = -ENOMEM;
			goto unwind;
		}
	}

	...

unwind:
	while (--i >= 0) {
		free(array[i].b);
		free(array[i].a);
	}

The style here with a big _base_release_memory_pools() function that has
to handle partially allocated resources will never work 100% correctly.
Fortunately the remaining bugs are minor leaks and not crashing bugs so
that's probably as good as we can hope for.

regards,
dan carpenter


      parent reply	other threads:[~2020-05-08 11:38 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-08  9:18 [PATCH] mpt3sas: Fix double free warnings Suganath Prabu S
2020-05-08 10:42 ` Johannes Thumshirn
2020-05-08 11:36 ` Dan Carpenter [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200508113622.GP1992@kadam \
    --to=dan.carpenter@oracle.com \
    --cc=Sathya.Prakash@broadcom.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=sreekanth.reddy@broadcom.com \
    --cc=suganath-prabu.subramani@broadcom.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox