Skip to content

Commit f3a8a7c

Browse files
deepanshu406gregkh
authored andcommitted
net: nfc: fix deadlock between nfc_unregister_device and rfkill_fop_write
commit 1ab526d upstream. 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. Fixes: 3e3b5df ("NFC: reorder the logic in nfc_{un,}register_device") Cc: stable@vger.kernel.org Reported-by: syzbot+4ef89409a235d804c6c2@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=4ef89409a235d804c6c2 Link: https://lore.kernel.org/all/20251217054908.178907-1-kartikey406@gmail.com/T/ [v1] Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com> Link: https://patch.msgid.link/20251218012355.279940-1-kartikey406@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 2431c1e commit f3a8a7c

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

net/nfc/core.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,7 @@ EXPORT_SYMBOL(nfc_register_device);
11541154
void nfc_unregister_device(struct nfc_dev *dev)
11551155
{
11561156
int rc;
1157+
struct rfkill *rfk = NULL;
11571158

11581159
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
11591160

@@ -1164,13 +1165,17 @@ void nfc_unregister_device(struct nfc_dev *dev)
11641165

11651166
device_lock(&dev->dev);
11661167
if (dev->rfkill) {
1167-
rfkill_unregister(dev->rfkill);
1168-
rfkill_destroy(dev->rfkill);
1168+
rfk = dev->rfkill;
11691169
dev->rfkill = NULL;
11701170
}
11711171
dev->shutting_down = true;
11721172
device_unlock(&dev->dev);
11731173

1174+
if (rfk) {
1175+
rfkill_unregister(rfk);
1176+
rfkill_destroy(rfk);
1177+
}
1178+
11741179
if (dev->ops->check_presence) {
11751180
timer_delete_sync(&dev->check_pres_timer);
11761181
cancel_work_sync(&dev->check_pres_work);

0 commit comments

Comments
 (0)