* [PATCH net] nfc: nci: fix uninit-value in nci_core_init_rsp_packet()
@ 2026-06-23 22:24 Samuel Page
0 siblings, 0 replies; only message in thread
From: Samuel Page @ 2026-06-23 22:24 UTC (permalink / raw)
To: David Heidelberg
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, oe-linux-nfc, netdev, linux-kernel, stable
The CORE_INIT_RSP handlers walk the response using length fields taken
from the packet itself, without checking they stay within skb->len:
- v1 computes
rsp_2 = skb->data + 6 + rsp_1->num_supported_rf_interfaces;
from the on-wire (unclamped) interface count and then dereferences
rsp_2, and memcpy()s the advertised interfaces - both can run past the
received data;
- v2 walks supported_rf_interfaces[], advancing the cursor by an
in-packet rf_extension_cnt with no bound.
A short CORE_INIT_RSP therefore makes the parser read past the packet
(into the uninitialised tail of the RX skb); the values are stored into
struct nci_dev and consumed while bringing the device up:
BUG: KMSAN: uninit-value in nci_dev_up+0x10f3/0x1720
nci_dev_up+0x10f3/0x1720
nfc_dev_up+0x187/0x380
nfc_genl_dev_up+0xdc/0x1a0
genl_rcv_msg+0x5d4/0x9e0
netlink_rcv_skb+0x28f/0x530
Uninit was stored to memory at:
nci_rsp_packet+0x68f/0x2310
nci_rx_work+0x25f/0x5d0
Uninit was created at:
__alloc_skb+0x540/0xd40
virtual_ncidev_write+0x65/0x210
Bound both parsers to skb->len before dereferencing the variable-length
parts, rejecting truncated responses with NCI_STATUS_SYNTAX_ERROR.
Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation")
Fixes: bcd684aace34 ("net/nfc/nci: Support NCI 2.x initial sequence")
Cc: stable@vger.kernel.org
Assisted-by: Bynario AI
Signed-off-by: Samuel Page <sam@bynar.io>
---
net/nfc/nci/rsp.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index 9eeb862825c5..cdcd23c8ca95 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -50,6 +50,9 @@ static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev,
const struct nci_core_init_rsp_1 *rsp_1 = (void *)skb->data;
const struct nci_core_init_rsp_2 *rsp_2;
+ if (skb->len < sizeof(*rsp_1))
+ return NCI_STATUS_SYNTAX_ERROR;
+
pr_debug("status 0x%x\n", rsp_1->status);
if (rsp_1->status != NCI_STATUS_OK)
@@ -58,6 +61,15 @@ static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev,
ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
+ /*
+ * supported_rf_interfaces[] and the trailing nci_core_init_rsp_2 are
+ * addressed using the on-wire (unclamped) interface count, so the
+ * response must be long enough for both before they are dereferenced.
+ */
+ if (skb->len < sizeof(*rsp_1) +
+ rsp_1->num_supported_rf_interfaces + sizeof(*rsp_2))
+ return NCI_STATUS_SYNTAX_ERROR;
+
ndev->num_supported_rf_interfaces =
min((int)ndev->num_supported_rf_interfaces,
NCI_MAX_SUPPORTED_RF_INTERFACES);
@@ -88,9 +100,13 @@ static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev,
{
const struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
const u8 *supported_rf_interface = rsp->supported_rf_interfaces;
+ const u8 *end = skb->data + skb->len;
u8 rf_interface_idx = 0;
u8 rf_extension_cnt = 0;
+ if (skb->len < sizeof(*rsp))
+ return NCI_STATUS_SYNTAX_ERROR;
+
pr_debug("status %x\n", rsp->status);
if (rsp->status != NCI_STATUS_OK)
@@ -104,10 +120,16 @@ static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev,
NCI_MAX_SUPPORTED_RF_INTERFACES);
while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
- ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++;
+ /* one interface byte + one extension-count byte must be present */
+ if (end - supported_rf_interface < 2)
+ return NCI_STATUS_SYNTAX_ERROR;
+ ndev->supported_rf_interfaces[rf_interface_idx++] =
+ *supported_rf_interface++;
- /* skip rf extension parameters */
+ /* skip rf extension parameters, bounded by the packet */
rf_extension_cnt = *supported_rf_interface++;
+ if (rf_extension_cnt > end - supported_rf_interface)
+ return NCI_STATUS_SYNTAX_ERROR;
supported_rf_interface += rf_extension_cnt;
}
base-commit: a986fde914d88af47eb78fd29c5d1af7952c3500
--
2.54.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-06-23 22:24 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-23 22:24 [PATCH net] nfc: nci: fix uninit-value in nci_core_init_rsp_packet() Samuel Page
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox