From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
patches@lists.linux.dev, Suman Ghosh <sumang@marvell.com>,
Siddh Raman Pant <code@siddh.me>,
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>,
"David S. Miller" <davem@davemloft.net>,
Sasha Levin <sashal@kernel.org>,
syzbot+bbe84a4010eeea00982d@syzkaller.appspotmail.com
Subject: [PATCH 4.14 1/7] nfc: llcp_core: Hold a ref to llcp_local->dev when holding a ref to llcp_local
Date: Mon, 8 Jan 2024 15:21:55 +0100 [thread overview]
Message-ID: <20240108141854.206910310@linuxfoundation.org> (raw)
In-Reply-To: <20240108141854.158274814@linuxfoundation.org>
4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siddh Raman Pant <code@siddh.me>
[ Upstream commit c95f919567d6f1914f13350af61a1b044ac85014 ]
llcp_sock_sendmsg() calls nfc_llcp_send_ui_frame() which in turn calls
nfc_alloc_send_skb(), which accesses the nfc_dev from the llcp_sock for
getting the headroom and tailroom needed for skb allocation.
Parallelly the nfc_dev can be freed, as the refcount is decreased via
nfc_free_device(), leading to a UAF reported by Syzkaller, which can
be summarized as follows:
(1) llcp_sock_sendmsg() -> nfc_llcp_send_ui_frame()
-> nfc_alloc_send_skb() -> Dereference *nfc_dev
(2) virtual_ncidev_close() -> nci_free_device() -> nfc_free_device()
-> put_device() -> nfc_release() -> Free *nfc_dev
When a reference to llcp_local is acquired, we do not acquire the same
for the nfc_dev. This leads to freeing even when the llcp_local is in
use, and this is the case with the UAF described above too.
Thus, when we acquire a reference to llcp_local, we should acquire a
reference to nfc_dev, and release the references appropriately later.
References for llcp_local is initialized in nfc_llcp_register_device()
(which is called by nfc_register_device()). Thus, we should acquire a
reference to nfc_dev there.
nfc_unregister_device() calls nfc_llcp_unregister_device() which in
turn calls nfc_llcp_local_put(). Thus, the reference to nfc_dev is
appropriately released later.
Reported-and-tested-by: syzbot+bbe84a4010eeea00982d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=bbe84a4010eeea00982d
Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket")
Reviewed-by: Suman Ghosh <sumang@marvell.com>
Signed-off-by: Siddh Raman Pant <code@siddh.me>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/nfc/llcp_core.c | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index 150f7ffbf6bc6..5c14fbcfecbab 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -157,6 +157,13 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
{
+ /* Since using nfc_llcp_local may result in usage of nfc_dev, whenever
+ * we hold a reference to local, we also need to hold a reference to
+ * the device to avoid UAF.
+ */
+ if (!nfc_get_device(local->dev->idx))
+ return NULL;
+
kref_get(&local->ref);
return local;
@@ -190,10 +197,18 @@ static void local_release(struct kref *ref)
int nfc_llcp_local_put(struct nfc_llcp_local *local)
{
+ struct nfc_dev *dev;
+ int ret;
+
if (local == NULL)
return 0;
- return kref_put(&local->ref, local_release);
+ dev = local->dev;
+
+ ret = kref_put(&local->ref, local_release);
+ nfc_put_device(dev);
+
+ return ret;
}
static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
@@ -959,8 +974,17 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
}
new_sock = nfc_llcp_sock(new_sk);
- new_sock->dev = local->dev;
+
new_sock->local = nfc_llcp_local_get(local);
+ if (!new_sock->local) {
+ reason = LLCP_DM_REJ;
+ sock_put(&new_sock->sk);
+ release_sock(&sock->sk);
+ sock_put(&sock->sk);
+ goto fail;
+ }
+
+ new_sock->dev = local->dev;
new_sock->rw = sock->rw;
new_sock->miux = sock->miux;
new_sock->nfc_protocol = sock->nfc_protocol;
@@ -1586,7 +1610,16 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
if (local == NULL)
return -ENOMEM;
- local->dev = ndev;
+ /* As we are going to initialize local's refcount, we need to get the
+ * nfc_dev to avoid UAF, otherwise there is no point in continuing.
+ * See nfc_llcp_local_get().
+ */
+ local->dev = nfc_get_device(ndev->idx);
+ if (!local->dev) {
+ kfree(local);
+ return -ENODEV;
+ }
+
INIT_LIST_HEAD(&local->list);
kref_init(&local->ref);
mutex_init(&local->sdp_lock);
--
2.43.0
next prev parent reply other threads:[~2024-01-08 14:22 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-08 14:21 [PATCH 4.14 0/7] 4.14.336-rc1 review Greg Kroah-Hartman
2024-01-08 14:21 ` Greg Kroah-Hartman [this message]
2024-01-08 14:21 ` [PATCH 4.14 2/7] net: sched: em_text: fix possible memory leak in em_text_destroy() Greg Kroah-Hartman
2024-01-08 14:21 ` [PATCH 4.14 3/7] net: bcmgenet: Fix FCS generation for fragmented skbuffs Greg Kroah-Hartman
2024-01-08 14:21 ` [PATCH 4.14 4/7] i40e: fix use-after-free in i40e_aqc_add_filters() Greg Kroah-Hartman
2024-01-08 14:21 ` [PATCH 4.14 5/7] firewire: ohci: suppress unexpected system reboot in AMD Ryzen machines and ASM108x/VT630x PCIe cards Greg Kroah-Hartman
2024-01-08 14:22 ` [PATCH 4.14 6/7] mmc: rpmb: fixes pause retune on all RPMB partitions Greg Kroah-Hartman
2024-01-08 14:22 ` [PATCH 4.14 7/7] mmc: core: Cancel delayed work before releasing host Greg Kroah-Hartman
2024-01-09 13:18 ` [PATCH 4.14 0/7] 4.14.336-rc1 review Naresh Kamboju
2024-01-09 13:45 ` Jon Hunter
2024-01-09 19:52 ` Pavel Machek
2024-01-10 14:02 ` Harshit Mogalapalli
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=20240108141854.206910310@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=code@siddh.me \
--cc=davem@davemloft.net \
--cc=krzysztof.kozlowski@linaro.org \
--cc=patches@lists.linux.dev \
--cc=sashal@kernel.org \
--cc=stable@vger.kernel.org \
--cc=sumang@marvell.com \
--cc=syzbot+bbe84a4010eeea00982d@syzkaller.appspotmail.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.