Re: [PATCH 1/2] SUNRPC: Do not dereference non-socket transports in sysfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> 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







[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux