Re: [PATCH 2/2] svcrpc: avoid memory-corruption on pool shutdown

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

 



On Thu, Dec 01, 2011 at 07:20:24AM -0500, Jeff Layton wrote:
> On Wed, 30 Nov 2011 18:40:09 -0500
> "J. Bruce Fields" <bfields@xxxxxxxxxxxx> wrote:
> >  void svc_close_all(struct svc_serv *serv)
> >  {
> > +	struct svc_pool *pool;
> > +	struct svc_xprt *xprt;
> > +	struct svc_xprt *tmp;
> > +	int i;
> > +
> >  	svc_close_list(&serv->sv_tempsocks);
> >  	svc_close_list(&serv->sv_permsocks);
> > +
> > +	for (i = 0; i < serv->sv_nrpools; i++) {
> > +		pool = &serv->sv_pools[i];
> > +
> > +		spin_lock_bh(&pool->sp_lock);
> > +		while (!list_empty(&pool->sp_sockets)) {
> > +			xprt = list_first_entry(&pool->sp_sockets, struct svc_xprt, xpt_ready);
> > +			list_del_init(&xprt->xpt_ready);
> > +		}
> > +		spin_unlock_bh(&pool->sp_lock);
> > +	}
> > +	/*
> > +	 * At this point the sp_sockets lists will stay empty, since
> > +	 * svc_enqueue will not add new entries without taking the
> > +	 * sp_lock and checking XPT_BUSY.
> > +	 */
> > +	list_for_each_entry_safe(xprt, tmp, &serv->sv_tempsocks, xpt_list)
> > +		svc_delete_xprt(xprt);
> > +	list_for_each_entry_safe(xprt, tmp, &serv->sv_permsocks, xpt_list)
> > +		svc_delete_xprt(xprt);
> > +
> 
> I'm always a little suspicious when I see walking and manipulating a
> list outside of any locking.

With good reason.

> Can you convince me as to why it's safe to do the above?

After entirely too much grepping....

The server keeps its listeners on sv_permsocks, and individual client
connections on sv_tempsocks.

The tempsocks list:
	- has a new xprt added when we accept a new connection.  This is
	  done by a server thread in svc_recv().  (Also
	  svc_check_conn_limits() may decide to remove an old connection
	  at the same time.)
	- has xprts removed by svc_age_temp_xprts, called from
	  sv_temptimer.

But svc_close_all() is called only after all server threads are gone
and after sv_temptimer has been stopped by a del_timer_sync().  So we're
safe from either of the above.

Great!  But:

The more irritating code is the code that's run on server startup and
configuration: svc_sock_update_bufs, nfsd_init_socks, svc_find_xprt,
svc_xprt_names, svc_create_xprt, svc_sock_names, and svc_addsock all
modify or traverse these two lists.  I believe the callers should all be
holding a mutex (normally nfsd_mutex, or nlmsvc_mutex or
nfs_callback_mutex as appropriate).  But not all of them are (e.g.
addfd, addxprt are fishy).

So, anyway: my inclination for now is to update this patch with a few
comments but leave it otherwise the same.

The remaining races look easier to avoid, as they'd only happen if
userspace was doing something odd like trying to give nfsd another
socket to listen on from one process while simultaneously shutting it
down from another.

But server startup and shutdown has always been fuzzy and kinda fragile.
And it will probably need a harder look anyway for containerization.  So
I'll take a harder look at that next....

--b.

> 
> list_for_each_entry_safe just makes it safe to remove "xprt" from the
> list essentially by preloading "tmp". What prevents another task from
> removing "tmp" while you're busy dealing with "xprt"? Or from putting a
> new socket onto the list at that point?
> 
> >  	BUG_ON(!list_empty(&serv->sv_permsocks));
> >  	BUG_ON(!list_empty(&serv->sv_tempsocks));
> > -
> >  }
> >  
> >  /*
> 
> 
> -- 
> Jeff Layton <jlayton@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux