Re: [PATCH 3.10 11/41] net: unix: non blocking recvmsg() should not return -EINTR

From: Rainer Weikusat
Date: Fri Apr 11 2014 - 12:31:37 EST


Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> writes:
> 3.10-stable review patch. If anyone has any objections, please let me
> know.

Since there's apparently little hope that you kindly stop spamming me
with this any time soon: The objection to this is still that the
non-blocking call shouldn't ever block (and hence, maintain the undocumented
property whose loss apparently wasn't noticed by anyone in the last
three years(!) as a side effect). That's arguably at least partially my
fault because I didn't think about the implications for non-blocking
case in 2011. For an example how this should be implemented, have a
look at pipe.c (summary: lock uninterruptibly, check state, unlock, go
to sleep or return EAGAIN, relock after sleep [if applicable]).

However, if there are actually applications depending on this behaviour,
this workaround is surely sensible for dealing with them.

>
> ------------------
>
> From: Eric Dumazet <edumazet@xxxxxxxxxx>
>
> [ 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@xxxxxxxxxx>
> Cc: Rainer Weikusat <rweikusat@xxxxxxxxxxxxxxxxxxxxxxx>
> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> ---
> net/unix/af_unix.c | 17 ++++++++++++-----
> 1 file changed, 12 insertions(+), 5 deletions(-)
>
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -1792,8 +1792,11 @@ static int unix_dgram_recvmsg(struct kio
> 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 ki
> 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;
> @@ -1928,7 +1932,7 @@ static int unix_stream_recvmsg(struct ki
> 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 ki
> }
>
> 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;
> }
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/