Re: [PATCH] Incremental: Fix possible memory and resource leaks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 8/26/21 5:40 AM, Mateusz Grzonka wrote:
> map allocated through map_by_uuid() is not freed if mdfd is invalid.
> It is also not freed at the end of Incremental_container().
> In addition mdfd is not closed, and mdinfo list is not
> freed too.
> Fix it.
> 
> Signed-off-by: Mateusz Grzonka <mateusz.grzonka@xxxxxxxxx>

Hi Mateusz,

Sorry for the late feedback.

Looking through this change, I would prefer to have had this done in
multiple patches that are easier to review individually. Like the first
close is obviously correct and the last change too, but they are
independent of the middle changes.

I also feel the second set of changes relying on doclose could be less
convoluted if we just check the return value from open_dev() and
create_mddev() immediately instead of trying to handle it in a catch all
case. This would help make the code easier to read.

Please see comments below.

Thoughts?

Thanks,
Jes


>  Incremental.c | 27 +++++++++++++++++++++------
>  1 file changed, 21 insertions(+), 6 deletions(-)
> 
> diff --git a/Incremental.c b/Incremental.c
> index cd9cc0fc..6678739b 100644
> --- a/Incremental.c
> +++ b/Incremental.c
> @@ -1416,6 +1416,7 @@ restart:
>  			}
>  			sysfs_free(sra);
>  		}
> +		close(mdfd);
>  	}
>  	map_free(mapl);
>  	return rv;
> @@ -1499,6 +1500,7 @@ static int Incremental_container(struct supertype *st, char *devname,
>  	}
>  	for (ra = list ; ra ; ra = ra->next) {
>  		int mdfd;
> +		int doclose = 0;
>  		char chosen_name[1024];
>  		struct map_ent *mp;
>  		struct mddev_ident *match = NULL;
> @@ -1513,6 +1515,7 @@ static int Incremental_container(struct supertype *st, char *devname,
>  
>  		if (mp) {
>  			mdfd = open_dev(mp->devnm);
> +			doclose = 1;

Check mdfd >= 0 here and jump to release.

>  			if (mp->path)
>  				strcpy(chosen_name, mp->path);
>  			else
> @@ -1572,22 +1575,30 @@ static int Incremental_container(struct supertype *st, char *devname,
>  					    c->autof,
>  					    trustworthy,
>  					    chosen_name, 0);
> +			doclose = 1;

Check mdfd >= 0 here and jump to release.

>  		}
> -		if (only && (!mp || strcmp(mp->devnm, only) != 0))
> -			continue;
>  
>  		if (mdfd < 0) {
>  			pr_err("failed to open %s: %s.\n",
>  				chosen_name, strerror(errno));
> -			return 2;
> +			rv = 2;
> +			goto release;
> +		}

We can then get rid of this block completely.

> +		if (only && (!mp || strcmp(mp->devnm, only) != 0)) {
> +			if (doclose)
> +				close(mdfd);
> +			continue;

And call close() here unconditionally.

>  		}
>  
>  		assemble_container_content(st, mdfd, ra, c,
>  					   chosen_name, &result);
>  		map_free(map);
>  		map = NULL;
> -		close(mdfd);
> +		if (doclose)
> +			close(mdfd);
>  	}

and get rid of the if() here
> +
>  	if (c->export && result) {
>  		char sep = '=';
>  		printf("MD_STARTED");
> @@ -1609,7 +1620,11 @@ static int Incremental_container(struct supertype *st, char *devname,
>  		}
>  		printf("\n");
>  	}
> -	return 0;
> +
> +release:
> +	map_free(map);
> +	sysfs_free(list);
> +	return rv;
>  }
>  
>  static void run_udisks(char *arg1, char *arg2)
> @@ -1701,7 +1716,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
>  		return 1;
>  	}
>  	mdfd = open_dev_excl(ent->devnm);
> -	if (mdfd > 0) {
> +	if (mdfd >= 0) {

This part is also independent and fine by itself.

>  		close(mdfd);
>  		if (sysfs_get_str(&mdi, NULL, "array_state",
>  				  buf, sizeof(buf)) > 0) {
> 




[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux