SUNRPC: lock against ->sock changing during sysfs read

->sock can be set to NULL asynchronously unless ->recv_mutex is held.
So it is important to hold that mutex.  Otherwise a sysfs read can
trigger an oops.
Commit 17f09d3f61 ("SUNRPC: Check if the xprt is connected before
handling sysfs reads") appears to attempt to fix this problem, but it
only narrows the race window.

Fixes: 17f09d3f61 ("SUNRPC: Check if the xprt is connected before handling sysfs reads")
Fixes: a8482488a7 ("SUNRPC query transport's source port")
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
NeilBrown 2022-01-17 16:36:53 +11:00 committed by Anna Schumaker
parent 63db37e99a
commit b49ea673e1
2 changed files with 10 additions and 2 deletions

View File

@ -115,11 +115,14 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
} }
sock = container_of(xprt, struct sock_xprt, xprt); sock = container_of(xprt, struct sock_xprt, xprt);
if (kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0) mutex_lock(&sock->recv_mutex);
if (sock->sock == NULL ||
kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
goto out; goto out;
ret = sprintf(buf, "%pISc\n", &saddr); ret = sprintf(buf, "%pISc\n", &saddr);
out: out:
mutex_unlock(&sock->recv_mutex);
xprt_put(xprt); xprt_put(xprt);
return ret + 1; return ret + 1;
} }

View File

@ -1641,7 +1641,12 @@ static int xs_get_srcport(struct sock_xprt *transport)
unsigned short get_srcport(struct rpc_xprt *xprt) unsigned short get_srcport(struct rpc_xprt *xprt)
{ {
struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt); struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
return xs_sock_getport(sock->sock); unsigned short ret = 0;
mutex_lock(&sock->recv_mutex);
if (sock->sock)
ret = xs_sock_getport(sock->sock);
mutex_unlock(&sock->recv_mutex);
return ret;
} }
EXPORT_SYMBOL(get_srcport); EXPORT_SYMBOL(get_srcport);