diff options
author | NeilBrown <neilb@suse.de> | 2010-11-16 16:55:19 +1100 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2011-02-09 22:15:38 +0100 |
commit | 346ecec0ebc9c048df93f3b710716407120c8267 (patch) | |
tree | d23b4cc23704a4253e302e8ca41513c3acd8cca0 /fs/read_write.h | |
parent | 446f4ee822fd7c7979917fb118abead424da7952 (diff) | |
download | linux-stable-346ecec0ebc9c048df93f3b710716407120c8267.tar.gz |
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: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Diffstat (limited to 'fs/read_write.h')
0 files changed, 0 insertions, 0 deletions