Commit 319050d4 authored by Chuck Lever's avatar Chuck Lever
Browse files

SUNRPC: Fix error handling in svc_setup_socket()



Dan points out that sock_alloc_file() releases @sock on error, but
so do all of svc_setup_socket's callers, resulting in a double-
release if sock_alloc_file() returns an error.

Rather than allocating a struct file for all new sockets, allocate
one only for sockets created during a TCP accept. For the moment,
those are the only ones that will ever be used with RPC-with-TLS.

Reported-by: default avatarDan Carpenter <dan.carpenter@linaro.org>
Fixes: ae0d7770 ("SUNRPC: Ensure server-side sockets have a sock->file")
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 29cd2927
Loading
Loading
Loading
Loading
+4 −12
Original line number Diff line number Diff line
@@ -895,6 +895,9 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
		trace_svcsock_accept_err(xprt, serv->sv_name, err);
		return NULL;
	}
	if (IS_ERR(sock_alloc_file(newsock, O_NONBLOCK, NULL)))
		return NULL;

	set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags);

	err = kernel_getpeername(newsock, sin);
@@ -935,7 +938,7 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
	return &newsvsk->sk_xprt;

failed:
	sock_release(newsock);
	sockfd_put(newsock);
	return NULL;
}

@@ -1430,7 +1433,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
						struct socket *sock,
						int flags)
{
	struct file	*filp = NULL;
	struct svc_sock	*svsk;
	struct sock	*inet;
	int		pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
@@ -1439,14 +1441,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
	if (!svsk)
		return ERR_PTR(-ENOMEM);

	if (!sock->file) {
		filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
		if (IS_ERR(filp)) {
			kfree(svsk);
			return ERR_CAST(filp);
		}
	}

	inet = sock->sk;

	if (pmap_register) {
@@ -1456,8 +1450,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
				     inet->sk_protocol,
				     ntohs(inet_sk(inet)->inet_sport));
		if (err < 0) {
			if (filp)
				fput(filp);
			kfree(svsk);
			return ERR_PTR(err);
		}