| From 7042669301766ade7e932f24a5656c4ef0a13376 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 23 Jul 2021 09:25:34 +0700 |
| Subject: tipc: fix sleeping in tipc accept routine |
| |
| From: Hoang Le <hoang.h.le@dektech.com.au> |
| |
| [ Upstream commit d237a7f11719ff9320721be5818352e48071aab6 ] |
| |
| The release_sock() is blocking function, it would change the state |
| after sleeping. In order to evaluate the stated condition outside |
| the socket lock context, switch to use wait_woken() instead. |
| |
| Fixes: 6398e23cdb1d8 ("tipc: standardize accept routine") |
| Acked-by: Jon Maloy <jmaloy@redhat.com> |
| Signed-off-by: Hoang Le <hoang.h.le@dektech.com.au> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/tipc/socket.c | 9 ++++----- |
| 1 file changed, 4 insertions(+), 5 deletions(-) |
| |
| diff --git a/net/tipc/socket.c b/net/tipc/socket.c |
| index 694c432b9710..4f9bd95b4eee 100644 |
| --- a/net/tipc/socket.c |
| +++ b/net/tipc/socket.c |
| @@ -2650,7 +2650,7 @@ static int tipc_listen(struct socket *sock, int len) |
| static int tipc_wait_for_accept(struct socket *sock, long timeo) |
| { |
| struct sock *sk = sock->sk; |
| - DEFINE_WAIT(wait); |
| + DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| int err; |
| |
| /* True wake-one mechanism for incoming connections: only |
| @@ -2659,12 +2659,12 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo) |
| * anymore, the common case will execute the loop only once. |
| */ |
| for (;;) { |
| - prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
| - TASK_INTERRUPTIBLE); |
| if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
| + add_wait_queue(sk_sleep(sk), &wait); |
| release_sock(sk); |
| - timeo = schedule_timeout(timeo); |
| + timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); |
| lock_sock(sk); |
| + remove_wait_queue(sk_sleep(sk), &wait); |
| } |
| err = 0; |
| if (!skb_queue_empty(&sk->sk_receive_queue)) |
| @@ -2676,7 +2676,6 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo) |
| if (signal_pending(current)) |
| break; |
| } |
| - finish_wait(sk_sleep(sk), &wait); |
| return err; |
| } |
| |
| -- |
| 2.30.2 |
| |