---
id: "CVE-2026-98580"
kind: "vulnerability"
aliases: ["CVE-2026-98580"]
title: "Linux kernel NFC LLCP: race in accept queue can cause use-after-free"
severity: "unknown"
cvss: null
epss: null
exploited: false
status: "open"
category: "runtime"
products: []
ecosystems: []
tags: ["kernel", "linux", "nfc", "runtime", "self-hosted"]
not_affected_if: ["nfc-module-not-loaded", "no-nfc-hardware"]
published_at: "2026-10-18T16:17:10+00:00"
first_seen_at: "2026-10-23T21:57:15+00:00"
updated_at: "2026-10-25T05:23:05+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-98580", "first_seen_at": "2026-10-23T21:57:15+00:00"}]
---

# Linux kernel NFC LLCP: race in accept queue can cause use-after-free

A race between socket release and accept() in the Linux kernel's NFC LLCP code can unlink and free the same child socket twice. The result is a use-after-free or NULL pointer dereference in the kernel, which can crash the machine or possibly be turned into code execution.

_Summary, check and fix written by a model from the sources; labelled as such._

## How to check

- Check the running kernel with `uname -r` and compare it to the fixed versions in the kernel's stable branch, which the sources do not list.
- Check whether the NFC LLCP module is loaded with `lsmod | grep nfc` or whether `nfc` is built in.
- unknown

## Fix

- Update to a Linux kernel release that includes the upstream commit fixing nfc: llcp accept_queue lifecycle; the exact fixed version is unknown from the sources.
- If NFC is not needed, blacklist the module with `modprobe -r nfc` and add `install nfc /bin/false` to a modprobe.d file.

## Timeline

- 2026-10-23T21:57:15+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-98580

## From the sources

In the Linux kernel, the following vulnerability has been resolved:

nfc: llcp: Fix race condition in accept_queue lifecycle

In nfc_llcp_socket_release(), sockets and listener accept queues are
walked under the local sockets rwlock and bh_lock_sock().  However,
bh_lock_sock() does not synchronise against process-context lock_sock()
held by nfc_llcp_accept_dequeue() during accept().  Because
socket_release() does not check sock_owned_by_user(), both paths can
concurrently unlink and release the same child socket, resulting in
use-after-free or a NULL pointer dereference of child->parent in
nfc_llcp_accept_unlink().

Fix this synchronisation race by having nfc_llcp_socket_release() use
process-context lock_sock() instead of bh_lock_sock():

1. Pop sockets from the local sockets list under the write lock using
   nfc_llcp_sock_list_pop() so lock_sock() can be acquired without
   holding the rwlock.

2. Because lock_sock() can sleep, defer the final release of the
   nfc_llcp_local structure to a workqueue (release_work).  This avoids
   a sleeping-in-atomic bug when the last local reference is dropped
   from softirq context.  Additionally, hold a single device reference
   on local from registration until final destruction.

3. In nfc_llcp_local_get(), use kref_get_unless_zero() to prevent
   resurrecting a local object whose teardown has been scheduled.

4. In llcp_sock_accept(), verify that the listener socket state is still
   LLCP_LISTEN after waking from schedule_timeout() to prevent hangs if
   the listener is closed concurrently.

5. When unlinking unaccepted child sockets during listener release,
   unlink them from local->sockets, call sock_orphan(), and drop their
   initial sk_alloc creation reference via sock_put().

6. Make nfc_llcp_accept_unlink() idempotent by guarding parent access with
   a NULL check.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
