VYPR
Unrated severityNVD Advisory· Published Jun 3, 2026

CVE-2026-46267

CVE-2026-46267

Description

Linux kernel NFC vulnerability allows UAF and shutdown races due to improper timer and work handling during deinitialization.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Linux kernel NFC vulnerability allows UAF and shutdown races due to improper timer and work handling during deinitialization.

Vulnerability

The Linux kernel's NFC subsystem has a use-after-free (UAF) and shutdown race condition vulnerability. The llc_shdlc_deinit() function frees the llc_shdlc context while its timers and state machine work might still be active. Timer callbacks can schedule sm_work, which accesses the SHDLC state and skb queues, leading to a UAF if teardown occurs concurrently with queued or running work items. This affects versions prior to the fix [1].

Exploitation

An attacker could exploit this vulnerability by triggering a deinitialization sequence in the NFC subsystem while timers or state machine work items are active. This race condition requires specific timing and conditions related to the NFC device's lifecycle and ongoing operations to manifest, potentially involving parallel execution paths within the kernel's NFC handling code [1].

Impact

Successful exploitation of this vulnerability can lead to a use-after-free condition and other shutdown race issues within the Linux kernel's NFC subsystem. This could result in system instability, crashes, or potentially allow an attacker to gain elevated privileges or execute arbitrary code with kernel-level permissions, depending on the exact nature of the UAF and race condition [1].

Mitigation

The vulnerability has been resolved by ensuring all SHDLC timers are stopped and sm_work is canceled synchronously before purging queues and freeing the context. The fix is available in the Linux kernel. Specific patched versions and release dates are not detailed in the provided references, but the fix is present in the kernel source [1].

AI Insight generated on Jun 3, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

14
a24a676329d4

nfc: hci: shdlc: Stop timers and work before freeing context

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitVotokina VictoriaFixed in 6.1.165via kernel-cna
1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index e90f70385813a..a106f4352356d 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);
    -- 
    cgit 1.3-korg
    
    
    
c9efde1e537b

nfc: hci: shdlc: Stop timers and work before freeing context

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitVotokina VictoriaFixed in 7.0via kernel-cna
1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index 4fc37894860c9..08c8aa1530d8a 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);
    -- 
    cgit 1.3-korg
    
    
    
c60f41022eaa

nfc: hci: shdlc: Stop timers and work before freeing context

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitVotokina VictoriaFixed in 5.15.202via kernel-cna
1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index aef750d7787c8..948cf4d210bde 100644
    --- a/net/nfc/hci/llc_shdlc.c
    +++ b/net/nfc/hci/llc_shdlc.c
    @@ -779,6 +779,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);
    -- 
    cgit 1.3-korg
    
    
    
77eef9f2eef0

nfc: hci: shdlc: Stop timers and work before freeing context

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitVotokina VictoriaFixed in 6.6.128via kernel-cna
1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index e90f70385813a..a106f4352356d 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);
    -- 
    cgit 1.3-korg
    
    
    
cf70cedce327

nfc: hci: shdlc: Stop timers and work before freeing context

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitVotokina VictoriaFixed in 6.12.75via kernel-cna
1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index e90f70385813a..a106f4352356d 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);
    -- 
    cgit 1.3-korg
    
    
    
276820278e97

nfc: hci: shdlc: Stop timers and work before freeing context

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitVotokina VictoriaFixed in 6.18.14via kernel-cna
1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index 4fc37894860c9..08c8aa1530d8a 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);
    -- 
    cgit 1.3-korg
    
    
    
1cb97b122545

nfc: hci: shdlc: Stop timers and work before freeing context

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitVotokina VictoriaFixed in 6.19.4via kernel-cna
1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index 4fc37894860c9..08c8aa1530d8a 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);
    -- 
    cgit 1.3-korg
    
    
    
1cb97b122545

nfc: hci: shdlc: Stop timers and work before freeing context

1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index 4fc37894860c9..08c8aa1530d8a 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);
    -- 
    cgit 1.3-korg
    
    
    
a24a676329d4

nfc: hci: shdlc: Stop timers and work before freeing context

1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index e90f70385813a..a106f4352356d 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);
    -- 
    cgit 1.3-korg
    
    
    
276820278e97

nfc: hci: shdlc: Stop timers and work before freeing context

1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index 4fc37894860c9..08c8aa1530d8a 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);
    -- 
    cgit 1.3-korg
    
    
    
77eef9f2eef0

nfc: hci: shdlc: Stop timers and work before freeing context

1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index e90f70385813a..a106f4352356d 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);
    -- 
    cgit 1.3-korg
    
    
    
c9efde1e537b

nfc: hci: shdlc: Stop timers and work before freeing context

1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index 4fc37894860c9..08c8aa1530d8a 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);
    -- 
    cgit 1.3-korg
    
    
    
c60f41022eaa

nfc: hci: shdlc: Stop timers and work before freeing context

1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index aef750d7787c8..948cf4d210bde 100644
    --- a/net/nfc/hci/llc_shdlc.c
    +++ b/net/nfc/hci/llc_shdlc.c
    @@ -779,6 +779,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);
    -- 
    cgit 1.3-korg
    
    
    
cf70cedce327

nfc: hci: shdlc: Stop timers and work before freeing context

1 file changed · +8 1
  • net/nfc/hci/llc_shdlc.c+8 1 modified
    diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
    index e90f70385813a..a106f4352356d 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);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"The llc_shdlc_deinit function frees the llc_shdlc context while timers and work items may still be active."

Attack vector

The vulnerability is triggered during the teardown of the SHDLC context. If the teardown process in `llc_shdlc_deinit()` occurs concurrently with an active timer callback or a queued/running work item, it can lead to race conditions. Specifically, timer callbacks can schedule `sm_work`, which then accesses the SHDLC state and skb queues after they may have been freed, resulting in a use-after-free vulnerability and other shutdown races.

Affected code

The vulnerability exists in the `llc_shdlc_deinit()` function within the `net/nfc/hci/llc_shdlc.c` file. The original implementation purged skb queues and freed the `llc_shdlc` structure while its timers and state machine work might still be active. The fix introduces synchronous cancellation of timers and work items before memory deallocation.

What the fix does

The patch modifies the `llc_shdlc_deinit()` function to ensure that all SHDLC timers are stopped synchronously using `timer_shutdown_sync()` and that the `sm_work` is cancelled synchronously using `cancel_work_sync()`. This is done before the function proceeds to purge the skb queues and free the `llc_shdlc` context. By synchronizing the shutdown of timers and work items, the patch prevents the `sm_work` from accessing freed memory, thus mitigating the use-after-free and shutdown race conditions.

Generated on Jun 3, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

1