dm-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
From: Martin Wilck <mwilck@suse.com>
To: Christophe Varoqui <christophe.varoqui@opensvc.com>,
	Benjamin Marzinski <bmarzins@redhat.com>,
	lixiaokeng@huawei.com, dm-devel@redhat.com
Subject: Re: [dm-devel] [PATCH v2 22/29] multipath: fix leaks in check_path_valid()
Date: Wed, 16 Dec 2020 18:34:05 +0100	[thread overview]
Message-ID: <7af8e4c39c11eae413c92beef97c62b793a08aa6.camel@suse.com> (raw)
In-Reply-To: <20201016104501.8700-23-mwilck@suse.com>

On Fri, 2020-10-16 at 12:44 +0200, mwilck@suse.com wrote:
> From: Martin Wilck <mwilck@suse.com>
> 
> There were two leaks in check_path_valid(): if path status was
> successfully determined before calling store_pathvec(), free_path()
> wasn't called. Also, if an error exit occured, neither cleanup
> function was called.
> 
> This patch fixes both, at the cost of using "static" for the pp and
> pathvec variables.

Looking at this again after 2 months, I think the on_exit() part of
this patch is wrong. First, we can't use on_exit() on every platform,
as e.g. musl libc doesn't have it. To replace this by the more portable
atexit(), we'd need to declare the two variables "pp" and "pathvec"
with file scope, which is very ugly. But more importantly, using static
variables here causes check_path_valid() to be non-reentrant. While it
doesn't have to be, it's still a coding pattern we haven't been using
anywhere else, just to avoid a "memory leak" for an irregular exit,
which isn't a real memory leak, actually.

One day we should remove the exit() calls somewhere deep down in our
libraries, and deal with the respective errors cleanly.

@lixiaokeng, I hope this is ok for you, as you brought the issue up
originally ("[QUESTION] memory leak in main (multipath)").

Regards
Martin

> 
> Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
>  multipath/main.c | 55 +++++++++++++++++++++++++++++++++++++---------
> --
>  1 file changed, 43 insertions(+), 12 deletions(-)
> 
> diff --git a/multipath/main.c b/multipath/main.c
> index 049a36f..9974993 100644
> --- a/multipath/main.c
> +++ b/multipath/main.c
> @@ -93,7 +93,7 @@ void rcu_register_thread_memb(void) {}
>  void rcu_unregister_thread_memb(void) {}
>  
>  static int
> -filter_pathvec (vector pathvec, char * refwwid)
> +filter_pathvec (vector pathvec, const char *refwwid)
>  {
>  	int i;
>  	struct path * pp;
> @@ -592,12 +592,37 @@ out:
>  	return r;
>  }
>  
> +static void cleanup_pathvec(__attribute__((unused)) int dummy, void
> *arg)
> +{
> +	vector *ppv = arg;
> +
> +	if (ppv && *ppv) {
> +		free_pathvec(*ppv, FREE_PATHS);
> +		*ppv = NULL;
> +	}
> +}
> +
> +static void cleanup_path(__attribute__((unused)) int dummy, void
> *arg)
> +{
> +	struct path **ppp = arg;
> +
> +	if (ppp && *ppp) {
> +		free_path(*ppp);
> +		*ppp = NULL;
> +	}
> +}
> +
>  static int
>  check_path_valid(const char *name, struct config *conf, bool
> is_uevent)
>  {
>  	int fd, r = PATH_IS_ERROR;
> -	struct path *pp = NULL;
> -	vector pathvec = NULL;
> +	static struct path *pp = NULL;
> +	static vector pathvec = NULL;
> +	const char *wwid;
> +
> +	/* register these as exit handlers in case we exit irregularly
> */
> +	on_exit(cleanup_path, &pp);
> +	on_exit(cleanup_pathvec, &pathvec);
>  
>  	pp = alloc_path();
>  	if (!pp)
> @@ -667,13 +692,17 @@ check_path_valid(const char *name, struct
> config *conf, bool is_uevent)
>  	if (store_path(pathvec, pp) != 0) {
>  		free_path(pp);
>  		goto fail;
> +	} else {
> +		/* make sure path isn't freed twice */
> +		wwid = pp->wwid;
> +		pp = NULL;
>  	}
>  
>  	/* For find_multipaths = SMART, if there is more than one path
>  	 * matching the refwwid, then the path is valid */
>  	if (path_discovery(pathvec, DI_SYSFS | DI_WWID) < 0)
>  		goto fail;
> -	filter_pathvec(pathvec, pp->wwid);
> +	filter_pathvec(pathvec, wwid);
>  	if (VECTOR_SIZE(pathvec) > 1)
>  		r = PATH_IS_VALID;
>  	else
> @@ -681,21 +710,23 @@ check_path_valid(const char *name, struct
> config *conf, bool is_uevent)
>  
>  out:
>  	r = print_cmd_valid(r, pathvec, conf);
> -	free_pathvec(pathvec, FREE_PATHS);
>  	/*
>  	 * multipath -u must exit with status 0, otherwise udev won't
>  	 * import its output.
>  	 */
>  	if (!is_uevent && r == PATH_IS_NOT_VALID)
> -		return RTVL_FAIL;
> -	return RTVL_OK;
> +		r = RTVL_FAIL;
> +	else
> +		r = RTVL_OK;
> +	goto cleanup;
>  
>  fail:
> -	if (pathvec)
> -		free_pathvec(pathvec, FREE_PATHS);
> -	else
> -		free_path(pp);
> -	return RTVL_FAIL;
> +	r = RTVL_FAIL;
> +
> +cleanup:
> +	cleanup_path(0, &pp);
> +	cleanup_pathvec(0, &pathvec);
> +	return r;
>  }
>  
>  static int


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel


  reply	other threads:[~2020-12-16 17:34 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-16 10:44 [dm-devel] [PATCH v2 00/29] libmultipath: improve cleanup on exit mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 01/29] multipathd: uxlsnr: avoid deadlock " mwilck
2020-10-20 19:04   ` Benjamin Marzinski
2020-10-16 10:44 ` [dm-devel] [PATCH v2 02/29] multipathd: Fix liburcu memory leak mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 03/29] multipathd: move handling of io_err_stat_attr into libmultipath mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 04/29] multipathd: move vecs desctruction into cleanup function mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 05/29] multipathd: make some globals static mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 06/29] multipathd: move threads destruction into separate function mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 07/29] multipathd: move conf " mwilck
2020-10-19 18:56   ` Benjamin Marzinski
2020-10-16 10:44 ` [dm-devel] [PATCH v2 08/29] multipathd: move pid " mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 09/29] multipathd: close pidfile on exit mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 10/29] multipathd: add helper for systemd notification at exit mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 11/29] multipathd: child(): call cleanups in failure case, too mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 12/29] multipathd: unwatch_all_dmevents: check if waiter is initialized mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 13/29] multipathd: print error message if config can't be loaded mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 14/29] libmultipath: add libmp_dm_exit() mwilck
2020-10-19 19:07   ` Benjamin Marzinski
2020-10-16 10:44 ` [dm-devel] [PATCH v2 15/29] multipathd: fixup libdm deinitialization mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 16/29] libmultipath: log_thread_stop(): check if logarea is initialized mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 17/29] multipathd: add cleanup_child() exit handler mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 18/29] libmultipath: fix log_thread startup and teardown mwilck
2020-10-19 20:00   ` Benjamin Marzinski
2020-10-26 13:58     ` Martin Wilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 19/29] multipathd: move cleanup_{prio, checkers, foreign} to libmultipath_exit mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 20/29] multipath: use atexit() for cleanup handlers mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 21/29] mpathpersist: " mwilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 22/29] multipath: fix leaks in check_path_valid() mwilck
2020-12-16 17:34   ` Martin Wilck [this message]
2020-12-16 22:41     ` Benjamin Marzinski
2020-10-16 10:44 ` [dm-devel] [PATCH v2 23/29] multipath-tools: mpath-tools.supp: file with valgrind suppressions mwilck
2020-10-19 20:01   ` Benjamin Marzinski
2020-10-16 10:44 ` [dm-devel] [PATCH v2 24/29] libmultipath: use libmp_verbosity to track verbosity mwilck
2020-10-19 20:38   ` Benjamin Marzinski
2020-10-26 14:47     ` Martin Wilck
2020-10-16 10:44 ` [dm-devel] [PATCH v2 25/29] libmultipath: introduce symbolic values for logsink mwilck
2020-10-16 20:13   ` Benjamin Marzinski
2020-10-16 10:44 ` [dm-devel] [PATCH v2 26/29] libmultipath: simplify dlog() mwilck
2020-10-19 21:07   ` Benjamin Marzinski
2020-10-16 10:44 ` [dm-devel] [PATCH v2 27/29] multipathd: common code for "-k" and command args mwilck
2020-10-19 21:51   ` Benjamin Marzinski
2020-10-16 10:45 ` [dm-devel] [PATCH v2 28/29] multipathd: sanitize uxsock_listen() mwilck
2020-10-19 23:33   ` Benjamin Marzinski
2020-10-26 13:54     ` Martin Wilck
2020-10-16 10:45 ` [dm-devel] [PATCH v2 29/29] libmultipath: fix race between log_safe and log_thread_stop() mwilck
2020-10-20  2:20   ` Benjamin Marzinski
2020-10-26 16:22     ` Martin Wilck
2020-10-26 17:24       ` Martin Wilck
2020-11-03  0:11         ` Benjamin Marzinski
2020-11-04 12:36           ` Martin Wilck
2020-11-04 15:46             ` Benjamin Marzinski

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=7af8e4c39c11eae413c92beef97c62b793a08aa6.camel@suse.com \
    --to=mwilck@suse.com \
    --cc=bmarzins@redhat.com \
    --cc=christophe.varoqui@opensvc.com \
    --cc=dm-devel@redhat.com \
    --cc=lixiaokeng@huawei.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;
as well as URLs for NNTP newsgroup(s).