Segfault in smbd: messaging_dgm_fde_active

Jeremy Allison jra at samba.org
Mon Jul 9 23:00:00 UTC 2018


On Mon, Jul 09, 2018 at 02:06:05PM +0200, Stefan Metzmacher via samba-technical wrote:
> Hi,
> 
> > Ping!
> > 
> > I know it is the crunch before the release but it would be good not to
> > forget this.
> 
> I looked at it and found the problem.
> 
> With auth_winbind as AD DC, smbd creates two temporary
> imessaging_context structures, both using messaging_dgm_ref()
> internally.
> 
> Then we free both of them when the authentication is done.
> So 'next' becomes a stale pointer in msg_dgm_ref_recv().
> 
> The attached patch fixes this. I'm currently running
> a private autobuild with it.
> 
> Please review and push:-)

OK, I'm reviewing this now, and I think I understand
it, but once I'm done I might ask you to add some
clarification to the commit message (or not, depending
on how easy this is to understand :-).

Cheers,

	Jeremy.

> From b4a5833fbd8a804822f2934f397d818302870a51 Mon Sep 17 00:00:00 2001
> From: Stefan Metzmacher <metze at samba.org>
> Date: Mon, 9 Jul 2018 12:33:34 +0200
> Subject: [PATCH] s3:messages: make the loop in msg_dgm_ref_recv() more robust
>  against stale pointers
> 
> The interaction between msg_dgm_ref_recv() and msg_dgm_ref_destructor()
> doesn't allow two references from messaging_dgm_ref() to be free'd
> during the loop in msg_dgm_ref_recv().
> 
> In addition to the global 'refs' list, we also need to
> have a global 'next_ref' pointer, which can be cleared in
> msg_dgm_ref_destructor().
> 
> As AD DC we hit this when using irpc in auth_winbind,
> which uses imessaging_client_init().
> In addition to the main messaging_dgm_ref() in smbd,
> source3/auth/auth_samba4.c: prepare_gensec() and
> make_auth4_context_s4() also generate a temporary
> imessaging_context for auth_context->msg_ctx from within
> auth_generic_prepare().
> 
> Bug: https://bugzilla.samba.org/show_bug.cgi?id=13514
> 
> Signed-off-by: Stefan Metzmacher <metze at samba.org>
> ---
>  source3/lib/messages_dgm_ref.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/source3/lib/messages_dgm_ref.c b/source3/lib/messages_dgm_ref.c
> index 39d22700740c..4cf80a789987 100644
> --- a/source3/lib/messages_dgm_ref.c
> +++ b/source3/lib/messages_dgm_ref.c
> @@ -35,6 +35,7 @@ struct msg_dgm_ref {
>  
>  static pid_t dgm_pid = 0;
>  static struct msg_dgm_ref *refs = NULL;
> +static struct msg_dgm_ref *next_ref = NULL;
>  
>  static int msg_dgm_ref_destructor(struct msg_dgm_ref *r);
>  static void msg_dgm_ref_recv(struct tevent_context *ev,
> @@ -121,16 +122,16 @@ static void msg_dgm_ref_recv(struct tevent_context *ev,
>  			     const uint8_t *msg, size_t msg_len,
>  			     int *fds, size_t num_fds, void *private_data)
>  {
> -	struct msg_dgm_ref *r, *next;
> +	struct msg_dgm_ref *r;
>  
>  	/*
>  	 * We have to broadcast incoming messages to all refs. The first ref
>  	 * that grabs the fd's will get them.
>  	 */
> -	for (r = refs; r != NULL; r = next) {
> +	for (r = refs; r != NULL; r = next_ref) {
>  		bool active;
>  
> -		next = r->next;
> +		next_ref = r->next;
>  
>  		active = messaging_dgm_fde_active(r->fde);
>  		if (!active) {
> @@ -152,6 +153,10 @@ static int msg_dgm_ref_destructor(struct msg_dgm_ref *r)
>  	}
>  	DLIST_REMOVE(refs, r);
>  
> +	if (r == next_ref) {
> +		next_ref = NULL;
> +	}
> +
>  	TALLOC_FREE(r->fde);
>  
>  	DBG_DEBUG("refs=%p\n", refs);
> -- 
> 2.17.1
> 







More information about the samba-technical mailing list