Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8a0c321 authored by Cong Wang's avatar Cong Wang Committed by Greg Kroah-Hartman
Browse files

kcm: fix strp_init() order and cleanup



[ Upstream commit 8fc29ff3910f3af08a7c40a75d436b5720efe2bf ]

strp_init() is called just a few lines above this csk->sk_user_data
check, it also initializes strp->work etc., therefore, it is
unnecessary to call strp_done() to cancel the freshly initialized
work.

And if sk_user_data is already used by KCM, psock->strp should not be
touched, particularly strp->work state, so we need to move strp_init()
after the csk->sk_user_data check.

This also makes a lockdep warning reported by syzbot go away.

Reported-and-tested-by: default avatar <syzbot+9fc084a4348493ef65d2@syzkaller.appspotmail.com>
Reported-by: default avatar <syzbot+e696806ef96cdd2d87cd@syzkaller.appspotmail.com>
Fixes: e5571240 ("kcm: Check if sk_user_data already set in kcm_attach")
Fixes: dff8baa2 ("kcm: Call strp_stop before strp_done in kcm_attach")
Cc: Tom Herbert <tom@herbertland.com>
Signed-off-by: default avatarCong Wang <cong.wang@bytedance.com>
Link: https://lore.kernel.org/r/20220827181314.193710-1-xiyou.wangcong@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 11f1e0c9
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -1412,12 +1412,6 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
	psock->sk = csk;
	psock->bpf_prog = prog;

	err = strp_init(&psock->strp, csk, &cb);
	if (err) {
		kmem_cache_free(kcm_psockp, psock);
		goto out;
	}

	write_lock_bh(&csk->sk_callback_lock);

	/* Check if sk_user_data is aready by KCM or someone else.
@@ -1425,13 +1419,18 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
	 */
	if (csk->sk_user_data) {
		write_unlock_bh(&csk->sk_callback_lock);
		strp_stop(&psock->strp);
		strp_done(&psock->strp);
		kmem_cache_free(kcm_psockp, psock);
		err = -EALREADY;
		goto out;
	}

	err = strp_init(&psock->strp, csk, &cb);
	if (err) {
		write_unlock_bh(&csk->sk_callback_lock);
		kmem_cache_free(kcm_psockp, psock);
		goto out;
	}

	psock->save_data_ready = csk->sk_data_ready;
	psock->save_write_space = csk->sk_write_space;
	psock->save_state_change = csk->sk_state_change;