Skip to content

Commit c0bffbc

Browse files
Nevsorgregkh
authored andcommitted
net: kcm: Fix race condition in kcm_unattach()
[ Upstream commit 52565a935213cd6a8662ddb8efe5b4219343a25d ] syzbot found a race condition when kcm_unattach(psock) and kcm_release(kcm) are executed at the same time. kcm_unattach() is missing a check of the flag kcm->tx_stopped before calling queue_work(). If the kcm has a reserved psock, kcm_unattach() might get executed between cancel_work_sync() and unreserve_psock() in kcm_release(), requeuing kcm->tx_work right before kcm gets freed in kcm_done(). Remove kcm->tx_stopped and replace it by the less error-prone disable_work_sync(). Fixes: ab7ac4e ("kcm: Kernel Connection Multiplexor module") Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=e62c9db591c30e174662 Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=d199b52665b6c3069b94 Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=be6b1fdfeae512726b4e Signed-off-by: Sven Stegemann <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent eb0336f commit c0bffbc

File tree

2 files changed

+2
-9
lines changed

2 files changed

+2
-9
lines changed

include/net/kcm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ struct kcm_sock {
7171
struct list_head wait_psock_list;
7272
struct sk_buff *seq_skb;
7373
struct mutex tx_mutex;
74-
u32 tx_stopped : 1;
7574

7675
/* Don't use bit fields here, these are set under different locks */
7776
bool tx_wait;

net/kcm/kcmsock.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ static void psock_write_space(struct sock *sk)
429429

430430
/* Check if the socket is reserved so someone is waiting for sending. */
431431
kcm = psock->tx_kcm;
432-
if (kcm && !unlikely(kcm->tx_stopped))
432+
if (kcm)
433433
queue_work(kcm_wq, &kcm->tx_work);
434434

435435
spin_unlock_bh(&mux->lock);
@@ -1696,12 +1696,6 @@ static int kcm_release(struct socket *sock)
16961696
*/
16971697
__skb_queue_purge(&sk->sk_write_queue);
16981698

1699-
/* Set tx_stopped. This is checked when psock is bound to a kcm and we
1700-
* get a writespace callback. This prevents further work being queued
1701-
* from the callback (unbinding the psock occurs after canceling work.
1702-
*/
1703-
kcm->tx_stopped = 1;
1704-
17051699
release_sock(sk);
17061700

17071701
spin_lock_bh(&mux->lock);
@@ -1717,7 +1711,7 @@ static int kcm_release(struct socket *sock)
17171711
/* Cancel work. After this point there should be no outside references
17181712
* to the kcm socket.
17191713
*/
1720-
cancel_work_sync(&kcm->tx_work);
1714+
disable_work_sync(&kcm->tx_work);
17211715

17221716
lock_sock(sk);
17231717
psock = kcm->tx_psock;

0 commit comments

Comments
 (0)