diff mbox

[3.8.y.z,extended,stable] Patch "net: unix: non blocking recvmsg() should not return -EINTR" has been added to staging queue

Message ID 1397687866-16178-1-git-send-email-kamal@canonical.com
State New
Headers show

Commit Message

Kamal Mostafa April 16, 2014, 10:37 p.m. UTC
This is a note to let you know that I have just added a patch titled

    net: unix: non blocking recvmsg() should not return -EINTR

to the linux-3.8.y-queue branch of the 3.8.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.8.y-queue

This patch is scheduled to be released in version 3.8.13.22.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.8.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

------

From 2d315ae1293b71a58cba8d7d5a5adb5e39157fb6 Mon Sep 17 00:00:00 2001
From: Eric Dumazet <edumazet@google.com>
Date: Tue, 25 Mar 2014 18:42:27 -0700
Subject: net: unix: non blocking recvmsg() should not return -EINTR

[ Upstream commit de1443916791d75fdd26becb116898277bb0273f ]

Some applications didn't expect recvmsg() on a non blocking socket
could return -EINTR. This possibility was added as a side effect
of commit b3ca9b02b00704 ("net: fix multithreaded signal handling in
unix recv routines").

To hit this bug, you need to be a bit unlucky, as the u->readlock
mutex is usually held for very small periods.

Fixes: b3ca9b02b00704 ("net: fix multithreaded signal handling in unix recv routines")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[ kamal removed Cc: Rainer Weikusat per request ]
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
---
 net/unix/af_unix.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

--
1.8.3.2
diff mbox

Patch

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 72f4e97..3887f23 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1795,8 +1795,11 @@  static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 		goto out;

 	err = mutex_lock_interruptible(&u->readlock);
-	if (err) {
-		err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
+	if (unlikely(err)) {
+		/* recvmsg() in non blocking mode is supposed to return -EAGAIN
+		 * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+		 */
+		err = noblock ? -EAGAIN : -ERESTARTSYS;
 		goto out;
 	}

@@ -1918,6 +1921,7 @@  static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 	struct unix_sock *u = unix_sk(sk);
 	struct sockaddr_un *sunaddr = msg->msg_name;
 	int copied = 0;
+	int noblock = flags & MSG_DONTWAIT;
 	int check_creds = 0;
 	int target;
 	int err = 0;
@@ -1933,7 +1937,7 @@  static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 		goto out;

 	target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
-	timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
+	timeo = sock_rcvtimeo(sk, noblock);

 	/* Lock the socket to prevent queue disordering
 	 * while sleeps in memcpy_tomsg
@@ -1945,8 +1949,11 @@  static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 	}

 	err = mutex_lock_interruptible(&u->readlock);
-	if (err) {
-		err = sock_intr_errno(timeo);
+	if (unlikely(err)) {
+		/* recvmsg() in non blocking mode is supposed to return -EAGAIN
+		 * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+		 */
+		err = noblock ? -EAGAIN : -ERESTARTSYS;
 		goto out;
 	}