[RHEL7,COMMIT] ms/make sock_alloc_file() do sock_release() on failures

Submitted by Vasily Averin on Dec. 3, 2020, 9:31 a.m.

Details

Message ID 202012030931.0B39VQZl006548@vz7build.vvs.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Vasily Averin Dec. 3, 2020, 9:31 a.m.
The commit is pushed to "branch-rh7-3.10.0-1160.6.1.vz7.171.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.6.1.vz7.171.1
------>
commit f369746f58e42de80794a189b83892fdedbcaf2b
Author: Al Viro <viro@ZenIV.linux.org.uk>
Date:   Thu Dec 3 12:31:25 2020 +0300

    ms/make sock_alloc_file() do sock_release() on failures
    
    This changes calling conventions (and simplifies the hell out
    or by sock_release() done by sock_alloc_file().  Either way
    the caller should not do sock_release() after that point.
    
    Reviewed-by: Eric Dumazet <edumazet@google.com>
    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    
    (cherry-picked from commit 8e1611e2357927b22892ecc062d65c99d0d89066)
    Backport changes: removed hooks in non-existing files
    	drivers/staging/lustre/lnet/lnet/lib-socket.c
    	net/kcm/kcmsock.c
    
    https://syzkaller.appspot.com/bug?id=23d0799f98b7c8c4bc3f5ecff7c28a87c64e40e8
    https://jira.sw.ru/browse/PSBM-123046
    Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
---
 net/9p/trans_fd.c |  1 -
 net/sctp/socket.c |  1 -
 net/socket.c      | 27 +++++++++------------------
 3 files changed, 9 insertions(+), 20 deletions(-)

Patch hide | download patch | download mbox

diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 02efb25..01cb566 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -807,7 +807,6 @@  static int p9_socket_open(struct p9_client *client, struct socket *csocket)
 	if (IS_ERR(file)) {
 		pr_err("%s (%d): failed to map fd\n",
 		       __func__, task_pid_nr(current));
-		sock_release(csocket);
 		kfree(p);
 		return PTR_ERR(file);
 	}
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 409fd92..67f0838 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4888,7 +4888,6 @@  static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t *p
 	*newfile = sock_alloc_file(newsock, 0, NULL);
 	if (IS_ERR(*newfile)) {
 		put_unused_fd(retval);
-		sock_release(newsock);
 		retval = PTR_ERR(*newfile);
 		*newfile = NULL;
 		return retval;
diff --git a/net/socket.c b/net/socket.c
index 6ea6b18..e720aa8 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -373,8 +373,10 @@  struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
 		name.len = strlen(name.name);
 	}
 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
-	if (unlikely(!path.dentry))
+	if (unlikely(!path.dentry)) {
+		sock_release(sock);
 		return ERR_PTR(-ENOMEM);
+	}
 	path.mnt = mntget(sock_mnt);
 
 	d_instantiate(path.dentry, SOCK_INODE(sock));
@@ -382,9 +384,11 @@  struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
 		  &socket_file_ops);
 	if (IS_ERR(file)) {
-		/* drop dentry, keep inode */
-		ihold(path.dentry->d_inode);
+		/* drop dentry, keep inode for a bit */
+		ihold(d_inode(path.dentry));
 		path_put(&path);
+		/* ... and now kill it properly */
+		sock_release(sock);
 		return file;
 	}
 
@@ -1476,19 +1480,9 @@  SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
 
 	retval = sock_create(family, type, protocol, &sock);
 	if (retval < 0)
-		goto out;
-
-	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
-	if (retval < 0)
-		goto out_release;
-
-out:
-	/* It may be already another descriptor 8) Not kernel problem. */
-	return retval;
+		return retval;
 
-out_release:
-	sock_release(sock);
-	return retval;
+	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
 }
 
 /*
@@ -1558,7 +1552,6 @@  SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
 	newfile1 = sock_alloc_file(sock1, flags, NULL);
 	if (IS_ERR(newfile1)) {
 		err = PTR_ERR(newfile1);
-		sock_release(sock1);
 		sock_release(sock2);
 		goto out;
 	}
@@ -1566,7 +1559,6 @@  SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
 	newfile2 = sock_alloc_file(sock2, flags, NULL);
 	if (IS_ERR(newfile2)) {
 		err = PTR_ERR(newfile2);
-		sock_release(sock2);
 		fput(newfile1);
 		goto out;
 	}
@@ -1695,7 +1687,6 @@  SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
 	if (IS_ERR(newfile)) {
 		err = PTR_ERR(newfile);
 		put_unused_fd(newfd);
-		sock_release(newsock);
 		goto out_put;
 	}