Security Vulnerability Report
中文
CVE-2025-71079 CVSS 5.5 MEDIUM

CVE-2025-71079

Published: 2026-01-13 16:16:07
Last Modified: 2026-03-25 19:44:19
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: net: nfc: fix deadlock between nfc_unregister_device and rfkill_fop_write A deadlock can occur between nfc_unregister_device() and rfkill_fop_write() due to lock ordering inversion between device_lock and rfkill_global_mutex. The problematic lock order is: Thread A (rfkill_fop_write): rfkill_fop_write() mutex_lock(&rfkill_global_mutex) rfkill_set_block() nfc_rfkill_set_block() nfc_dev_down() device_lock(&dev->dev) <- waits for device_lock Thread B (nfc_unregister_device): nfc_unregister_device() device_lock(&dev->dev) rfkill_unregister() mutex_lock(&rfkill_global_mutex) <- waits for rfkill_global_mutex This creates a classic ABBA deadlock scenario. Fix this by moving rfkill_unregister() and rfkill_destroy() outside the device_lock critical section. Store the rfkill pointer in a local variable before releasing the lock, then call rfkill_unregister() after releasing device_lock. This change is safe because rfkill_fop_write() holds rfkill_global_mutex while calling the rfkill callbacks, and rfkill_unregister() also acquires rfkill_global_mutex before cleanup. Therefore, rfkill_unregister() will wait for any ongoing callback to complete before proceeding, and device_del() is only called after rfkill_unregister() returns, preventing any use-after-free. The similar lock ordering in nfc_register_device() (device_lock -> rfkill_global_mutex via rfkill_register) is safe because during registration the device is not yet in rfkill_list, so no concurrent rfkill operations can occur on this device.

CVSS Details

CVSS Score
5.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
Linux Kernel < 1ab526d97a57e44d26fadcc0e9adeb9c0c0182f5
Linux Kernel < 2e0831e9fc46a06daa6d4d8d57a2738e343130c3
Linux Kernel < 6b93c8ab6f6cda8818983a4ae3fcf84b023037b4
Linux Kernel < 8fc4632fb508432895430cd02b38086bdd649083
Linux Kernel < e02a1c33f10a0ed3aba855ab8ae2b6c4c5be8012

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
// CVE-2025-71079 - Linux Kernel NFC Deadlock PoC // This is a conceptual PoC demonstrating the deadlock condition // Note: This requires local access and kernel development knowledge #include <stdio.h> #include <pthread.h> #include <unistd.h> // Simulated lock structures typedef struct { pthread_mutex_t mutex; } lock_t; lock_t device_lock = {PTHREAD_MUTEX_INITIALIZER}; lock_t rfkill_global_mutex = {PTHREAD_MUTEX_INITIALIZER}; // Thread A: Simulates rfkill_fop_write path void* thread_rfkill_write(void* arg) { printf("[Thread A] Attempting to acquire rfkill_global_mutex\n"); pthread_mutex_lock(&rfkill_global_mutex.mutex); printf("[Thread A] Acquired rfkill_global_mutex, now trying device_lock\n"); // This simulates: nfc_rfkill_set_block -> nfc_dev_down -> device_lock pthread_mutex_lock(&device_lock.mutex); printf("[Thread A] Acquired device_lock\n"); pthread_mutex_unlock(&device_lock.mutex); pthread_mutex_unlock(&rfkill_global_mutex.mutex); return NULL; } // Thread B: Simulates nfc_unregister_device path void* thread_unregister_device(void* arg) { sleep(1); // Ensure Thread A starts first printf("[Thread B] Attempting to acquire device_lock\n"); pthread_mutex_lock(&device_lock.mutex); printf("[Thread B] Acquired device_lock, now trying rfkill_global_mutex\n"); // This simulates: rfkill_unregister -> mutex_lock(&rfkill_global_mutex) pthread_mutex_lock(&rfkill_global_mutex.mutex); printf("[Thread B] Acquired rfkill_global_mutex\n"); pthread_mutex_unlock(&rfkill_global_mutex.mutex); pthread_mutex_unlock(&device_lock.mutex); return NULL; } int main() { pthread_t t1, t2; printf("CVE-2025-71079 Deadlock PoC\n"); printf("Starting two threads that will deadlock...\n"); pthread_create(&t1, NULL, thread_rfkill_write, NULL); pthread_create(&t2, NULL, thread_unregister_device, NULL); sleep(5); printf("DEADLOCK DETECTED: System appears to be frozen\n"); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-71079", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-01-13T16:16:07.433", "lastModified": "2026-03-25T19:44:18.643", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nnet: nfc: fix deadlock between nfc_unregister_device and rfkill_fop_write\n\nA deadlock can occur between nfc_unregister_device() and rfkill_fop_write()\ndue to lock ordering inversion between device_lock and rfkill_global_mutex.\n\nThe problematic lock order is:\n\nThread A (rfkill_fop_write):\n rfkill_fop_write()\n mutex_lock(&rfkill_global_mutex)\n rfkill_set_block()\n nfc_rfkill_set_block()\n nfc_dev_down()\n device_lock(&dev->dev) <- waits for device_lock\n\nThread B (nfc_unregister_device):\n nfc_unregister_device()\n device_lock(&dev->dev)\n rfkill_unregister()\n mutex_lock(&rfkill_global_mutex) <- waits for rfkill_global_mutex\n\nThis creates a classic ABBA deadlock scenario.\n\nFix this by moving rfkill_unregister() and rfkill_destroy() outside the\ndevice_lock critical section. Store the rfkill pointer in a local variable\nbefore releasing the lock, then call rfkill_unregister() after releasing\ndevice_lock.\n\nThis change is safe because rfkill_fop_write() holds rfkill_global_mutex\nwhile calling the rfkill callbacks, and rfkill_unregister() also acquires\nrfkill_global_mutex before cleanup. Therefore, rfkill_unregister() will\nwait for any ongoing callback to complete before proceeding, and\ndevice_del() is only called after rfkill_unregister() returns, preventing\nany use-after-free.\n\nThe similar lock ordering in nfc_register_device() (device_lock ->\nrfkill_global_mutex via rfkill_register) is safe because during\nregistration the device is not yet in rfkill_list, so no concurrent\nrfkill operations can occur on this device."}, {"lang": "es", "value": "En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:\n\nnet: nfc: corrige interbloqueo entre nfc_unregister_device y rfkill_fop_write\n\nPuede ocurrir un interbloqueo entre nfc_unregister_device() y rfkill_fop_write() debido a la inversión del orden de bloqueo entre device_lock y rfkill_global_mutex.\n\nEl orden de bloqueo problemático es:\n\nHilo A (rfkill_fop_write):\n rfkill_fop_write()\n mutex_lock(&amp;rfkill_global_mutex)\n rfkill_set_block()\n nfc_rfkill_set_block()\n nfc_dev_down()\n device_lock(&amp;dev-&gt;dev) &lt;- espera por device_lock\n\nHilo B (nfc_unregister_device):\n nfc_unregister_device()\n device_lock(&amp;dev-&gt;dev)\n rfkill_unregister()\n mutex_lock(&amp;rfkill_global_mutex) &lt;- espera por rfkill_global_mutex\n\nEsto crea un escenario clásico de interbloqueo ABBA.\n\nSoluciona esto moviendo rfkill_unregister() y rfkill_destroy() fuera de la sección crítica de device_lock. Almacena el puntero rfkill en una variable local antes de liberar el bloqueo, luego llama a rfkill_unregister() después de liberar device_lock.\n\nEste cambio es seguro porque rfkill_fop_write() mantiene rfkill_global_mutex mientras llama a las retrollamadas de rfkill, y rfkill_unregister() también adquiere rfkill_global_mutex antes de la limpieza. Por lo tanto, rfkill_unregister() esperará a que cualquier retrollamada en curso se complete antes de continuar, y device_del() solo se llama después de que rfkill_unregister() retorna, previniendo cualquier uso después de liberación.\n\nEl orden de bloqueo similar en nfc_register_device() (device_lock -&gt; rfkill_global_mutex a través de rfkill_register) es seguro porque durante el registro el dispositivo aún no está en rfkill_list, por lo que no pueden ocurrir operaciones rfkill concurrentes en este dispositivo."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", "baseScore": 5.5, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-667"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "4.4.293", "versionEndExcluding": "4.5", "matchCriteriaId": "36838255-8956-4DF8-A38C-0C0EDB3F6963"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "4.9.291", "versionEndExcluding": "4.10", "matchCriteriaId": "3BE45829-77EB-4065-B756-D47219F39C98"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kerne ... (truncated)