From: Duoming Zhou <duoming@zju.edu.cn>
To: krzk@kernel.org, linux-kernel@vger.kernel.org
Cc: davem@davemloft.net, gregkh@linuxfoundation.org,
alexander.deucher@amd.com, akpm@linux-foundation.org,
broonie@kernel.org, netdev@vger.kernel.org, linma@zju.edu.cn,
Duoming Zhou <duoming@zju.edu.cn>
Subject: [PATCH V3 1/3] drivers: nfc: nfcmrvl: fix double free bugs caused by fw_dnld_over()
Date: Thu, 14 Apr 2022 13:31:20 +0800 [thread overview]
Message-ID: <1d34425a0ea8a553a66dcf4f22ca55cc920dbb42.1649913521.git.duoming@zju.edu.cn> (raw)
In-Reply-To: <cover.1649913521.git.duoming@zju.edu.cn>
In-Reply-To: <cover.1649913521.git.duoming@zju.edu.cn>
There are potential double free bugs in nfcmrvl usb driver among
fw_dnld_rx_work(), fw_dnld_timeout() and nfcmrvl_nci_unregister_dev().
All these three functions will call fw_dnld_over(). The fw_dnld_rx_work()
is a work item, the fw_dnld_timeout() is a timer handler and the
nfcmrvl_nci_unregister_dev() is called when nfcmrvl_nci device is
detaching. So these three functions could execute concurrently.
The race between fw_dnld_rx_work() and nfcmrvl_nci_unregister_dev()
can be shown as below:
(Thread 1) | (Thread 2)
| fw_dnld_rx_work
| fw_dnld_over
| release_firmware
| kfree(fw); //(1)
nfcmrvl_disconnect |
nfcmrvl_nci_unregister_dev |
nfcmrvl_fw_dnld_abort |
fw_dnld_over | ...
if (priv->fw_dnld.fw) |
release_firmware |
kfree(fw); //(2) |
... | priv->fw_dnld.fw = NULL;
When the fw_dnld_rx_work work item is executing, we detach the device.
The release_firmware() will deallocate firmware in position (1),
but firmware will be deallocated again in position (2), which
leads to double free.
The race between fw_dnld_rx_work() and fw_dnld_timeout()
can be shown as below:
(Thread 1) | (Thread 2)
| fw_dnld_rx_work
| fw_dnld_over
| release_firmware
| kfree(fw); //(1)
fw_dnld_timeout |
fw_dnld_over | ...
if (priv->fw_dnld.fw) |
release_firmware |
kfree(fw); //(2) |
... | priv->fw_dnld.fw = NULL;
The release_firmware() will deallocate firmware in position (1),
but firmware will be deallocated again in position (2), which
leads to double free.
The race between fw_dnld_timeout() and nfcmrvl_nci_unregister_dev()
can be shown as below.
(Thread 1) | (Thread 2)
| nfcmrvl_disconnect
| nfcmrvl_nci_unregister_dev
| nfcmrvl_fw_dnld_abort
| fw_dnld_over
| release_firmware
| kfree(fw); //(1)
fw_dnld_timeout |
fw_dnld_over | ...
if (priv->fw_dnld.fw) |
release_firmware |
kfree(fw); //(2) |
... | priv->fw_dnld.fw = NULL;
The release_firmware() will deallocate firmware in position (1),
but firmware will be deallocated again in position (2), which
leads to double free.
This patch adds spin_lock_irq in fw_dnld_over() in order to synchronize
among different threads that call fw_dnld_over(). The priv->fw_dnld.fw will
be set to NULL after work item is finished and fw_dnld_over() called by
other threads will check whether priv->fw_dnld.fw is NULL. So the double
free bug could be prevented.
Fixes: 3194c6870158e3 ("NFC: nfcmrvl: add firmware download support")
Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
Reviewed-by: Lin Ma <linma@zju.edu.cn>
---
Changes in V3:
- Make commit message more clearer.
- Use spin_lock_irq to synchronize.
drivers/nfc/nfcmrvl/fw_dnld.c | 3 +++
drivers/nfc/nfcmrvl/fw_dnld.h | 2 ++
2 files changed, 5 insertions(+)
diff --git a/drivers/nfc/nfcmrvl/fw_dnld.c b/drivers/nfc/nfcmrvl/fw_dnld.c
index e83f65596a8..c22a4556db5 100644
--- a/drivers/nfc/nfcmrvl/fw_dnld.c
+++ b/drivers/nfc/nfcmrvl/fw_dnld.c
@@ -92,12 +92,14 @@ static struct sk_buff *alloc_lc_skb(struct nfcmrvl_private *priv, uint8_t plen)
static void fw_dnld_over(struct nfcmrvl_private *priv, u32 error)
{
+ spin_lock_irq(&priv->fw_dnld.lock);
if (priv->fw_dnld.fw) {
release_firmware(priv->fw_dnld.fw);
priv->fw_dnld.fw = NULL;
priv->fw_dnld.header = NULL;
priv->fw_dnld.binary_config = NULL;
}
+ spin_unlock_irq(&priv->fw_dnld.lock);
atomic_set(&priv->ndev->cmd_cnt, 0);
@@ -451,6 +453,7 @@ int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv)
if (!priv->fw_dnld.rx_wq)
return -ENOMEM;
skb_queue_head_init(&priv->fw_dnld.rx_q);
+ spin_lock_init(&priv->fw_dnld.lock);
return 0;
}
diff --git a/drivers/nfc/nfcmrvl/fw_dnld.h b/drivers/nfc/nfcmrvl/fw_dnld.h
index 7c4d91b0191..6974c307947 100644
--- a/drivers/nfc/nfcmrvl/fw_dnld.h
+++ b/drivers/nfc/nfcmrvl/fw_dnld.h
@@ -75,6 +75,8 @@ struct nfcmrvl_fw_dnld {
struct sk_buff_head rx_q;
struct timer_list timer;
+ /* To synchronize among different threads that call firmware.*/
+ spinlock_t lock;
};
int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv);
--
2.17.1
next prev parent reply other threads:[~2022-04-14 5:32 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-14 5:31 [PATCH 0/3] Fix double free bugs and UAF bug in nfcmrvl module Duoming Zhou
2022-04-14 5:31 ` Duoming Zhou [this message]
2022-04-14 5:50 ` [PATCH V3 1/3] drivers: nfc: nfcmrvl: fix double free bugs caused by fw_dnld_over() Lin Ma
2022-04-14 5:31 ` [PATCH V2 2/3] drivers: nfc: nfcmrvl: fix double free bug in nfc_fw_download_done() Duoming Zhou
2022-04-14 5:47 ` Lin Ma
2022-04-14 5:31 ` [PATCH 3/3] drivers: nfc: nfcmrvl: fix use-after-free bug in nfcmrvl_fw_dnld_start() Duoming Zhou
2022-04-14 9:37 ` [PATCH 0/3] Fix double free bugs and UAF bug in nfcmrvl module Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1d34425a0ea8a553a66dcf4f22ca55cc920dbb42.1649913521.git.duoming@zju.edu.cn \
--to=duoming@zju.edu.cn \
--cc=akpm@linux-foundation.org \
--cc=alexander.deucher@amd.com \
--cc=broonie@kernel.org \
--cc=davem@davemloft.net \
--cc=gregkh@linuxfoundation.org \
--cc=krzk@kernel.org \
--cc=linma@zju.edu.cn \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).