> On Mar 24, 2022, at 5:33 PM, trondmy@xxxxxxxxxx wrote: > > From: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> > > Do not cast the struct xprt to a sock_xprt unless we know it is a UDP or > TCP transport. Otherwise the call to lock the mutex will scribble over > whatever structure is actually there. This has been seen to cause hard > system lockups when the underlying transport was RDMA. > > Fixes: e44773daf851 ("SUNRPC: Add srcaddr as a file in sysfs") > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> > --- > net/sunrpc/sysfs.c | 32 ++++++++++++++++++++++---------- > 1 file changed, 22 insertions(+), 10 deletions(-) > > diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c > index 05c758da6a92..8ce053f84421 100644 > --- a/net/sunrpc/sysfs.c > +++ b/net/sunrpc/sysfs.c > @@ -107,22 +107,34 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj, > struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); > struct sockaddr_storage saddr; > struct sock_xprt *sock; > + const char *fmt = "<closed>\n"; > ssize_t ret = -1; > > - if (!xprt || !xprt_connected(xprt)) { > - xprt_put(xprt); > - return -ENOTCONN; > - } > + if (!xprt || !xprt_connected(xprt)) > + goto out; > > - sock = container_of(xprt, struct sock_xprt, xprt); > - mutex_lock(&sock->recv_mutex); > - if (sock->sock == NULL || > - kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0) This would be a little nicer if it went through the transport switch instead. But isn't the socket address available in the rpc_xprt? > + switch (xprt->xprt_class->ident) { > + case XPRT_TRANSPORT_UDP: > + case XPRT_TRANSPORT_TCP: > + break; > + default: > + fmt = "<not a socket>\n"; > goto out; > + }; > > - ret = sprintf(buf, "%pISc\n", &saddr); > -out: > + sock = container_of(xprt, struct sock_xprt, xprt); > + mutex_lock(&sock->recv_mutex); > + if (sock->sock != NULL) { > + ret = kernel_getsockname(sock->sock, (struct sockaddr *)&saddr); > + if (ret >= 0) { > + ret = sprintf(buf, "%pISc\n", &saddr); > + fmt = NULL; > + } > + } > mutex_unlock(&sock->recv_mutex); > +out: > + if (fmt) > + ret = sprintf(buf, fmt); > xprt_put(xprt); > return ret + 1; > } > -- > 2.35.1 > -- Chuck Lever