linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Yann Droneaud <ydroneaud@opteya.com>
To: David Miller <davem@davemloft.net>
Cc: Yann Droneaud <ydroneaud@opteya.com>,
	Al Viro <viro@ZenIV.linux.org.uk>,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	Al Viro <viro@ZenIV.linux.org.uk>
Subject: [PATCH v3] net: handle error more gracefully in socketpair()
Date: Mon,  9 Dec 2013 22:42:20 +0100	[thread overview]
Message-ID: <1386625340-8490-1-git-send-email-ydroneaud@opteya.com> (raw)
In-Reply-To: <20131206.121411.2205219888474731457.davem@davemloft.net>

This patch makes socketpair() use error paths which do not
rely on heavy-weight call to sys_close(): it's better to try
to push the file descriptor to userspace before installing
the socket file to the file descriptor, so that errors are
catched earlier and being easier to handle.

Using sys_close() seems to be the exception, while writing the
file descriptor before installing it look like it's more or less
the norm: eg. except for code used in init/, error handling
involve fput() and put_unused_fd(), but not sys_close().

This make socketpair() usage of sys_close() quite unusual.
So it deserves to be replaced by the common pattern relying on
fput() and put_unused_fd() just like, for example, the one used
in pipe(2) or recvmsg(2).

Three distinct error paths are still needed since calling
fput() on file structure returned by sock_alloc_file() will
implicitly call sock_release() on the associated socket
structure.

Cc: David S. Miller <davem@davemloft.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Yann Droneaud <ydroneaud@opteya.com>
Link: http://marc.info/?i=1385979146-13825-1-git-send-email-ydroneaud@opteya.com
---

Hi David,

Please find a patch which was discussed last week.

I've rework a bit the commit message to sum up our discussion
about the pattern to use when dealing with file descriptor when
it has to be copied to userspace.

Regards.

Changes from v2 [1]:

- rework a bit commit message

Changes from v1 [2]:

- use three different error path to handle file allocated through
  sock_alloc_file().

Regards.

[1] http://mid.gmane.org/1385979146-13825-1-git-send-email-ydroneaud@opteya.com

[2] http://mid.gmane.org/1385977019-12282-1-git-send-email-ydroneaud@opteya.com

 net/socket.c | 49 +++++++++++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index cd38a785f7d2..879933aaed4c 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1445,48 +1445,61 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
 		err = fd1;
 		goto out_release_both;
 	}
+
 	fd2 = get_unused_fd_flags(flags);
 	if (unlikely(fd2 < 0)) {
 		err = fd2;
-		put_unused_fd(fd1);
-		goto out_release_both;
+		goto out_put_unused_1;
 	}
 
 	newfile1 = sock_alloc_file(sock1, flags, NULL);
 	if (unlikely(IS_ERR(newfile1))) {
 		err = PTR_ERR(newfile1);
-		put_unused_fd(fd1);
-		put_unused_fd(fd2);
-		goto out_release_both;
+		goto out_put_unused_both;
 	}
 
 	newfile2 = sock_alloc_file(sock2, flags, NULL);
 	if (IS_ERR(newfile2)) {
 		err = PTR_ERR(newfile2);
-		fput(newfile1);
-		put_unused_fd(fd1);
-		put_unused_fd(fd2);
-		sock_release(sock2);
-		goto out;
+		goto out_fput_1;
 	}
 
+	err = put_user(fd1, &usockvec[0]);
+	if (err)
+		goto out_fput_both;
+
+	err = put_user(fd2, &usockvec[1]);
+	if (err)
+		goto out_fput_both;
+
 	audit_fd_pair(fd1, fd2);
+
 	fd_install(fd1, newfile1);
 	fd_install(fd2, newfile2);
 	/* fd1 and fd2 may be already another descriptors.
 	 * Not kernel problem.
 	 */
 
-	err = put_user(fd1, &usockvec[0]);
-	if (!err)
-		err = put_user(fd2, &usockvec[1]);
-	if (!err)
-		return 0;
+	return 0;
 
-	sys_close(fd2);
-	sys_close(fd1);
-	return err;
+out_fput_both:
+	fput(newfile2);
+	fput(newfile1);
+	put_unused_fd(fd2);
+	put_unused_fd(fd1);
+	goto out;
+
+out_fput_1:
+	fput(newfile1);
+	put_unused_fd(fd2);
+	put_unused_fd(fd1);
+	sock_release(sock2);
+	goto out;
 
+out_put_unused_both:
+	put_unused_fd(fd2);
+out_put_unused_1:
+	put_unused_fd(fd1);
 out_release_both:
 	sock_release(sock2);
 out_release_1:
-- 
1.8.4.2


  reply	other threads:[~2013-12-09 21:43 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-02  9:36 [PATCH] net: use a proper error path in socketpair() Yann Droneaud
2013-12-02 10:12 ` [PATCH v2] net: handle error more gracefully " Yann Droneaud
2013-12-05 21:23   ` David Miller
2013-12-05 23:15     ` Yann Droneaud
2013-12-06  0:43       ` David Miller
2013-12-06 10:10         ` Yann Droneaud
2013-12-06 10:48         ` Al Viro
2013-12-06 17:14           ` David Miller
2013-12-09 21:42             ` Yann Droneaud [this message]
2013-12-11  3:24               ` [PATCH v3] " David Miller
2013-12-11  9:32                 ` Yann Droneaud

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1386625340-8490-1-git-send-email-ydroneaud@opteya.com \
    --to=ydroneaud@opteya.com \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).