| From e06c26f449e7a7b7a0ac82108d4bf3686a30e129 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 14 Jul 2021 17:13:20 +0800 |
| Subject: net: decnet: Fix sleeping inside in af_decnet |
| |
| From: Yajun Deng <yajun.deng@linux.dev> |
| |
| [ Upstream commit 5f119ba1d5771bbf46d57cff7417dcd84d3084ba ] |
| |
| The release_sock() is blocking function, it would change the state |
| after sleeping. use wait_woken() instead. |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Signed-off-by: Yajun Deng <yajun.deng@linux.dev> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/decnet/af_decnet.c | 27 ++++++++++++--------------- |
| 1 file changed, 12 insertions(+), 15 deletions(-) |
| |
| diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c |
| index 5dbd45dc35ad..dc92a67baea3 100644 |
| --- a/net/decnet/af_decnet.c |
| +++ b/net/decnet/af_decnet.c |
| @@ -816,7 +816,7 @@ static int dn_auto_bind(struct socket *sock) |
| static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) |
| { |
| struct dn_scp *scp = DN_SK(sk); |
| - DEFINE_WAIT(wait); |
| + DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| int err; |
| |
| if (scp->state != DN_CR) |
| @@ -826,11 +826,11 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) |
| scp->segsize_loc = dst_metric_advmss(__sk_dst_get(sk)); |
| dn_send_conn_conf(sk, allocation); |
| |
| - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| + add_wait_queue(sk_sleep(sk), &wait); |
| for(;;) { |
| release_sock(sk); |
| if (scp->state == DN_CC) |
| - *timeo = schedule_timeout(*timeo); |
| + *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo); |
| lock_sock(sk); |
| err = 0; |
| if (scp->state == DN_RUN) |
| @@ -844,9 +844,8 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) |
| err = -EAGAIN; |
| if (!*timeo) |
| break; |
| - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| } |
| - finish_wait(sk_sleep(sk), &wait); |
| + remove_wait_queue(sk_sleep(sk), &wait); |
| if (err == 0) { |
| sk->sk_socket->state = SS_CONNECTED; |
| } else if (scp->state != DN_CC) { |
| @@ -858,7 +857,7 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) |
| static int dn_wait_run(struct sock *sk, long *timeo) |
| { |
| struct dn_scp *scp = DN_SK(sk); |
| - DEFINE_WAIT(wait); |
| + DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| int err = 0; |
| |
| if (scp->state == DN_RUN) |
| @@ -867,11 +866,11 @@ static int dn_wait_run(struct sock *sk, long *timeo) |
| if (!*timeo) |
| return -EALREADY; |
| |
| - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| + add_wait_queue(sk_sleep(sk), &wait); |
| for(;;) { |
| release_sock(sk); |
| if (scp->state == DN_CI || scp->state == DN_CC) |
| - *timeo = schedule_timeout(*timeo); |
| + *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo); |
| lock_sock(sk); |
| err = 0; |
| if (scp->state == DN_RUN) |
| @@ -885,9 +884,8 @@ static int dn_wait_run(struct sock *sk, long *timeo) |
| err = -ETIMEDOUT; |
| if (!*timeo) |
| break; |
| - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| } |
| - finish_wait(sk_sleep(sk), &wait); |
| + remove_wait_queue(sk_sleep(sk), &wait); |
| out: |
| if (err == 0) { |
| sk->sk_socket->state = SS_CONNECTED; |
| @@ -1032,16 +1030,16 @@ static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt) |
| |
| static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) |
| { |
| - DEFINE_WAIT(wait); |
| + DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| struct sk_buff *skb = NULL; |
| int err = 0; |
| |
| - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| + add_wait_queue(sk_sleep(sk), &wait); |
| for(;;) { |
| release_sock(sk); |
| skb = skb_dequeue(&sk->sk_receive_queue); |
| if (skb == NULL) { |
| - *timeo = schedule_timeout(*timeo); |
| + *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo); |
| skb = skb_dequeue(&sk->sk_receive_queue); |
| } |
| lock_sock(sk); |
| @@ -1056,9 +1054,8 @@ static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) |
| err = -EAGAIN; |
| if (!*timeo) |
| break; |
| - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| } |
| - finish_wait(sk_sleep(sk), &wait); |
| + remove_wait_queue(sk_sleep(sk), &wait); |
| |
| return skb == NULL ? ERR_PTR(err) : skb; |
| } |
| -- |
| 2.30.2 |
| |