Re: [PATCH v2] NFC: nxp-nci: fix deadlock between firmware download and IRQ handler

David Heidelberg <[email protected]>
Newsgroups dev.linux.lists.oe-linux-nfc,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
On 10/08/2026 10:21, Ian Ray wrote:
> The firmware download work function holds `info_lock' while calling the
> nxp_nci_fw_send(), which waits for a completion.
> 
> The completion is signalled by the IRQ thread handler, which also takes
> `info_lock', causing a deadlock.
> 
> Fix by dropping the mutex while waiting for the completion.
> 
> Fixes: dece45855a8b ("NFC: nxp-nci: Add support for NXP NCI chips")
> Cc: [email protected]
> Signed-off-by: Ian Ray <[email protected]>
> ---
> Changes since v1:
> - Fixes tag
> - Cc for stable
> ---
>   drivers/nfc/nxp-nci/firmware.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 

Hello Ian,

I checked the Sashiko review and it seems found an issue (feel free to ignore 
the 2nd pre-existing), could you check please (below)?

Thanks
David

--- Patch [1]: [PATCH v2] NFC: nxp-nci: fix deadlock between firmware download 
and IRQ handler ---
commit aeb1accbd1a732a455bf37b530649e8d9f406914
Author: Ian Ray <[email protected]>
Subject: NFC: nxp-nci: fix deadlock between firmware download and IRQ handler

This commit addresses a deadlock during firmware download by dropping the
info_lock mutex while waiting for the IRQ handler to signal completion.

 > diff --git a/drivers/nfc/nxp-nci/firmware.c b/drivers/nfc/nxp-nci/firmware.c
 > index a9533977aff8e..38fcac26ce563 100644
 > --- a/drivers/nfc/nxp-nci/firmware.c
 > +++ b/drivers/nfc/nxp-nci/firmware.c
 > @@ -154,8 +154,13 @@ static int nxp_nci_fw_send(struct nxp_nci_info *info)
 >  		if (fw_info->fw)
 >  			schedule_work(&fw_info->work);
 >  	} else {
 > +		mutex_unlock(&info->info_lock);
 > +
 >  		completion_rc = wait_for_completion_interruptible_timeout(
 >  			&fw_info->cmd_completion, NXP_NCI_FW_ANSWER_TIMEOUT);
 > +
 > +		mutex_lock(&info->info_lock);
 > +

If wait_for_completion_interruptible_timeout() times out, could this open a
race condition leading to a use-after-free?

When the timeout expires, the IRQ handler might run before info_lock is
re-acquired here. Since the timeout path hasn't cleaned up fw_info->fw yet,
the IRQ handler would see fw_info->fw != NULL and erroneously call
schedule_work(&fw_info->work) for a late response:

drivers/nfc/nxp-nci/firmware.c:nxp_nci_fw_recv_frame() {
     ...
     if (fw_info->fw)
         schedule_work(&fw_info->work);
     ...
}

After re-acquiring the lock, this function returns -ETIMEDOUT, and the caller
nxp_nci_fw_work_complete() will free the firmware buffer.

Could the spuriously scheduled work then execute and dereference the freed
memory when it calls nxp_nci_fw_send_chunk():

     skb_put_data(skb, fw_info->data + fw_info->written, chunk_len);

 >  		if (completion_rc == 0)
 >  			return -ETIMEDOUT;
 >  	}

This is a pre-existing issue, but does nxp_nci_remove() have a use-after-free
if a firmware download is currently running?

nxp_nci_remove() calls nxp_nci_fw_work_complete() to free the firmware buffer
before cancelling the work queue:

drivers/nfc/nxp-nci/core.c:nxp_nci_remove() {
     ...
     if (info->mode == NXP_NCI_MODE_FW)
         nxp_nci_fw_work_complete(info, -ESHUTDOWN);
     cancel_work_sync(&info->fw_info.work);
     ...
}

Since nxp_nci_fw_work_complete() frees fw_info->fw without holding info_lock,
could the concurrent nxp_nci_fw_work() thread be actively copying data from
fw_info->data, resulting in a use-after-free or a double free if the worker
finishes and calls nxp_nci_fw_work_complete() as well?

This is a pre-existing issue, but is there a potential integer underflow and
out-of-bounds read earlier in nxp_nci_fw_send()?

Before dropping the lock, the firmware size is modified without a length
check:

drivers/nfc/nxp-nci/firmware.c:nxp_nci_fw_send() {
     ...
     if (fw_info->written == 0) {
         fw_info->frame_size = get_unaligned_be16(fw_info->data) &
                               NXP_NCI_FW_FRAME_LEN_MASK;
         fw_info->data += NXP_NCI_FW_HDR_LEN;
         fw_info->size -= NXP_NCI_FW_HDR_LEN;
     }
     ...
}

If the provided firmware file is smaller than NXP_NCI_FW_HDR_LEN (2 bytes),
fw_info->size (which is unsigned) will underflow to a very large value.

Would this cause the subsequent safety check to be bypassed:

     if (fw_info->frame_size > fw_info->size)
         return -EMSGSIZE;

and allow nxp_nci_fw_send_chunk() to read out-of-bounds heap memory?
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.