Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de144391 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

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



Some applications didn't expect recvmsg() on a non blocking socket
could return -EINTR. This possibility was added as a side effect
of commit b3ca9b02 ("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: b3ca9b02 ("net: fix multithreaded signal handling in unix recv routines")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Rainer Weikusat <rweikusat@mobileactivedefense.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dc0fe58f
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -1787,8 +1787,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;
	}

@@ -1913,6 +1916,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
	struct unix_sock *u = unix_sk(sk);
	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
	int copied = 0;
	int noblock = flags & MSG_DONTWAIT;
	int check_creds = 0;
	int target;
	int err = 0;
@@ -1928,7 +1932,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
@@ -1940,8 +1944,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;
	}