AF_UNIX: Fix poll locking problem when reading from a stream socket
Subsystems (3)
PATCH 1/1 AF_UNIX: Fix poll locking problem when reading from a stream socket
poll() call may be locked by concurrent reading from the same stream socket.
--- net/unix/af_unix.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
net/unix/af_unix.c +4 -0
@@ -1957,6 +1957,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,if ((UNIXCB (skb).pid != siocb->scm->pid) || (UNIXCB (skb).cred != siocb->scm->cred)) {skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);break ; } }else {
@@ -1974,6 +1975,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, chunk = min_t(unsigned int, skb->len, size);if (memcpy_toiovec (msg->msg_iov, skb->data, chunk)) {skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);if (copied ==0 ) copied = -EFAULT ;break ;
@@ -1991,6 +1993,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,/* put the skb back if we didn't use it up.. */ if (skb->len) {skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);break ; }
@@ -2006,6 +2009,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,/* put message back and return */ skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);break ; } }while (size);
Signature · 1 line
1.7.2.5
Quoted 37 lines · Alexey Moiseytsev
poll()call may be locked by concurrent reading from the same stream socket.Signed-off-by Alexey Moiseytsev <[email protected]>--- net/unix/af_unix.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)net/unix/af_unix.c +3
-0@@ -1957,6 +1957,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,if ((UNIXCB (skb).pid != siocb->scm->pid) || (UNIXCB (skb).cred != siocb->scm->cred)) {skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);break ; } }else {@@ -1974,6 +1975,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, chunk = min_t(unsigned int, skb->len, size);if (memcpy_toiovec (msg->msg_iov, skb->data, chunk)) {skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);if (copied ==0 ) copied = -EFAULT ;break ;@@ -1991,6 +1993,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,/* put the skb back if we didn't use it up.. */ if (skb->len) {skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);break ; }
net/unix/af_unix.c static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, · line 2015
Quoted 7 lines
net/unix/af_unix.c +1
-0@@ -2006,6 +2009,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,/* put message back and return */ skb_queue_head (&sk->sk_receive_queue, skb); + sk->sk_data_ready (sk, skb->len);break ; } }while (size);
Fine, the fix is technically correct since we own u->readlock mutex, another thread cannot consume the just requeued skb.
Small note : the words "locking" and "locked" are more used to describe the action of taking a spinlock/mutex/rwlock or something, while the bug you fixed is more about poll() system call being blocked/frozen forever.
Thanks !
From: Eric Dumazet <[email protected]>
Date: Tue, 22 Nov 2011 06:23:01 +0100
Quoted 5 lines · Alexey Moiseytsev
Quoted 4 lines
poll()call may be locked by concurrent reading from the same stream socket.Signed-off-by Alexey Moiseytsev <[email protected]>
..
Quoted 10 lines
Fine, the fix is technically correct since we own
u->readlockmutex, another thread cannot consume the just requeued skb.Small note : the words "locking" and "locked" are more used to describe the action of taking a spinlock/mutex/rwlock or something, while the bug you fixed is more about
poll()system call being blocked/frozen forever.Thanks !
Acked-by Eric Dumazet <[email protected]>
Applied, with 'lock{ing,ed}' adjusted to 'block{ing,ed}'.