Skip to contentSkip to conversation

AF_UNIX: Fix poll locking problem when reading from a stream socket

PATCH Applied Alexey Moiseytsev 3 participants 3 messages Nov 21, 2011 – Nov 26, 2011

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

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
index 466fbcc..b595a3d 100644
@@ -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
Acked-by on v1 1/1
#1 lore raw
Quoted 37 lines · Alexey Moiseytsev

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 +3 -0
index 466fbcc..b595a3d 100644
@@ -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 !

maintainer Applied
#2 lore raw

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.

..

Quoted 10 lines

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 !

Applied, with 'lock{ing,ed}' adjusted to 'block{ing,ed}'.