diff options
author | jhb <jhb@FreeBSD.org> | 2013-04-08 19:03:01 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2013-04-08 19:03:01 +0000 |
commit | 4312ec3f0dd92a3dedf58a28ebc6f4ae3a1a7672 (patch) | |
tree | 13366d646862c52df55b1c45000dd9d3c0e08eed /sys | |
parent | 52f6f6d83eb2c4356b916617d45ecd58d775c3bd (diff) | |
download | FreeBSD-src-4312ec3f0dd92a3dedf58a28ebc6f4ae3a1a7672.zip FreeBSD-src-4312ec3f0dd92a3dedf58a28ebc6f4ae3a1a7672.tar.gz |
Fix a potential socket leak in the NFS server. If a client closes its
connection after it was accepted by the userland nfsd process but before
it was handled off to svc_vc_create() in the kernel, then svc_vc_create()
would see it as a new listen socket and try to listen on it leaving a
dangling reference to the socket. Instead, check for disconnected sockets
and treat them like a connected socket. The call to pru_getaddr() should
fail and cause svc_vc_create() to fail. Note that we need to lock the
socket to get a consistent snapshot of so_state since there is a window
in soisdisconnected() where both flags are clear.
Reviewed by: dfr, rmacklem
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/rpc/svc_vc.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index 80824ef..54fa546 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -146,7 +146,9 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, struct sockaddr* sa; int error; - if (so->so_state & SS_ISCONNECTED) { + SOCK_LOCK(so); + if (so->so_state & (SS_ISCONNECTED|SS_ISDISCONNECTED)) { + SOCK_UNLOCK(so); error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa); if (error) return (NULL); @@ -154,6 +156,7 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, free(sa, M_SONAME); return (xprt); } + SOCK_UNLOCK(so); xprt = svc_xprt_alloc(); sx_init(&xprt->xp_lock, "xprt->xp_lock"); |