]> git.baikalelectronics.ru Git - kernel.git/commitdiff
SUNRPC: lock against ->sock changing during sysfs read
authorNeilBrown <neilb@suse.de>
Mon, 17 Jan 2022 05:36:53 +0000 (16:36 +1100)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Tue, 8 Feb 2022 14:14:26 +0000 (09:14 -0500)
->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 9f759263746a ("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: 9f759263746a ("SUNRPC: Check if the xprt is connected before handling sysfs reads")
Fixes: ea56a96d4f9a ("SUNRPC query transport's source port")
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
net/sunrpc/sysfs.c
net/sunrpc/xprtsock.c

index b64a0286b18250b8befb980b905c253f85659414..05c758da6a92a44e064431c927b97a05504794e6 100644 (file)
@@ -115,11 +115,14 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
        }
 
        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;
 
        ret = sprintf(buf, "%pISc\n", &saddr);
 out:
+       mutex_unlock(&sock->recv_mutex);
        xprt_put(xprt);
        return ret + 1;
 }
index 69b6ee5a5fd11bfd618a3a0a15001bd5bc8bd552..0f39e08ee580e8f383b8a5fa6d7bd9ccc2cb0380 100644 (file)
@@ -1641,7 +1641,12 @@ static int xs_get_srcport(struct sock_xprt *transport)
 unsigned short get_srcport(struct rpc_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);