diff options
| author | Votokina Victoria <Victoria.Votokina@kaspersky.com> | 2026-02-03 14:31:57 +0300 |
|---|---|---|
| committer | Sasha Levin <sashal@kernel.org> | 2026-03-04 15:19:43 +0300 |
| commit | a24a676329d40481b2331bfa1418a679577dfd3a (patch) | |
| tree | 27f07e9285d40c65986e917d720be0a6c8219942 /net | |
| parent | a01c3073f8a5454883d80c4b6041b0a764bd6762 (diff) | |
| download | linux-a24a676329d40481b2331bfa1418a679577dfd3a.tar.xz | |
nfc: hci: shdlc: Stop timers and work before freeing context
[ Upstream commit c9efde1e537baed7648a94022b43836a348a074f ]
llc_shdlc_deinit() purges SHDLC skb queues and frees the llc_shdlc
structure while its timers and state machine work may still be active.
Timer callbacks can schedule sm_work, and sm_work accesses SHDLC state
and the skb queues. If teardown happens in parallel with a queued/running
work item, it can lead to UAF and other shutdown races.
Stop all SHDLC timers and cancel sm_work synchronously before purging the
queues and freeing the context.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: 4a61cd6687fc ("NFC: Add an shdlc llc module to llc core")
Signed-off-by: Votokina Victoria <Victoria.Votokina@kaspersky.com>
Link: https://patch.msgid.link/20260203113158.2008723-1-Victoria.Votokina@kaspersky.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
| -rw-r--r-- | net/nfc/hci/llc_shdlc.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c index e90f70385813..a106f4352356 100644 --- a/net/nfc/hci/llc_shdlc.c +++ b/net/nfc/hci/llc_shdlc.c @@ -762,6 +762,14 @@ static void llc_shdlc_deinit(struct nfc_llc *llc) { struct llc_shdlc *shdlc = nfc_llc_get_data(llc); + timer_shutdown_sync(&shdlc->connect_timer); + timer_shutdown_sync(&shdlc->t1_timer); + timer_shutdown_sync(&shdlc->t2_timer); + shdlc->t1_active = false; + shdlc->t2_active = false; + + cancel_work_sync(&shdlc->sm_work); + skb_queue_purge(&shdlc->rcv_q); skb_queue_purge(&shdlc->send_q); skb_queue_purge(&shdlc->ack_pending_q); |
