]> git.karo-electronics.de Git - karo-tx-linux.git/commit
sunrpc: prevent use-after-free on clearing XPT_BUSY
authorNeilBrown <neilb@suse.de>
Tue, 16 Nov 2010 05:55:19 +0000 (16:55 +1100)
committerPaul Gortmaker <paul.gortmaker@windriver.com>
Sun, 17 Apr 2011 20:16:08 +0000 (16:16 -0400)
commit5fb592d3df35de794c8fcad3d0f8c6320301b516
treea2bce90c2ec85f845dbb4b7ea04761e3ab8f1183
parentc0430f6fd2c0c2a7fa794df1d041752f9bb938ef
sunrpc: prevent use-after-free on clearing XPT_BUSY

commit ed2849d3ecfa339435818eeff28f6c3424300cec upstream.

When an xprt is created, it has a refcount of 1, and XPT_BUSY is set.
The refcount is *not* owned by the thread that created the xprt
(as is clear from the fact that creators never put the reference).
Rather, it is owned by the absence of XPT_DEAD.  Once XPT_DEAD is set,
(And XPT_BUSY is clear) that initial reference is dropped and the xprt
can be freed.

So when a creator clears XPT_BUSY it is dropping its only reference and
so must not touch the xprt again.

However svc_recv, after calling ->xpo_accept (and so getting an XPT_BUSY
reference on a new xprt), calls svc_xprt_recieved.  This clears
XPT_BUSY and then svc_xprt_enqueue - this last without owning a reference.
This is dangerous and has been seen to leave svc_xprt_enqueue working
with an xprt containing garbage.

So we need to hold an extra counted reference over that call to
svc_xprt_received.

For safety, any time we clear XPT_BUSY and then use the xprt again, we
first get a reference, and the put it again afterwards.

Note that svc_close_all does not need this extra protection as there are
no threads running, and the final free can only be called asynchronously
from such a thread.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
net/sunrpc/svc_xprt.c