diff options
author | NeilBrown <neilb@suse.de> | 2010-11-15 03:27:01 +0300 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-12-17 23:48:19 +0300 |
commit | 3942302ea9e1dffa933021b20bf1642046e7641b (patch) | |
tree | c6b878198ab33ee5893f24b7366b9c209d71a2dc /net/sunrpc/svcsock.c | |
parent | 7c96aef75949a56ec427fc6a2522dace2af33605 (diff) | |
download | linux-3942302ea9e1dffa933021b20bf1642046e7641b.tar.xz |
sunrpc: svc_sock_names should hold ref to socket being closed.
Currently svc_sock_names calls svc_close_xprt on a svc_sock to
which it does not own a reference.
As soon as svc_close_xprt sets XPT_CLOSE, the socket could be
freed by a separate thread (though this is a very unlikely race).
It is safer to hold a reference while calling svc_close_xprt.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 07919e16be3e..52bd1130e83a 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -324,19 +324,21 @@ int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, len = onelen; break; } - if (toclose && strcmp(toclose, buf + len) == 0) + if (toclose && strcmp(toclose, buf + len) == 0) { closesk = svsk; - else + svc_xprt_get(&closesk->sk_xprt); + } else len += onelen; } spin_unlock_bh(&serv->sv_lock); - if (closesk) + if (closesk) { /* Should unregister with portmap, but you cannot * unregister just one protocol... */ svc_close_xprt(&closesk->sk_xprt); - else if (toclose) + svc_xprt_put(&closesk->sk_xprt); + } else if (toclose) return -ENOENT; return len; } |