drivers/nfc/microread/microread.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
microread_target_discovered() parses target discovery payloads from
skb->data according to the HCI gate. The fixed field offsets and UID
copies were checked only against the destination nfc_target buffers, not
against the actual skb length.
Validate that each gate-specific payload contains the fixed fields and
UID bytes before reading or copying them.
Fixes: cfad1ba87150 ("NFC: Initial support for Inside Secure microread")
Cc: stable@vger.kernel.org
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
Changes since v1: https://lore.kernel.org/all/20260701053709.45176-1-pengpeng@iscas.ac.cn/
- add the Fixes tag and stable Cc requested during review
- rebase onto the current net tree
drivers/nfc/microread/microread.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c
index 4149c5d735bd..dfa2490db545 100644
--- a/drivers/nfc/microread/microread.c
+++ b/drivers/nfc/microread/microread.c
@@ -483,13 +483,19 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
switch (gate) {
case MICROREAD_GATE_ID_MREAD_ISO_A:
+ if (skb->len <= MICROREAD_EMCF_A_LEN) {
+ r = -EINVAL;
+ goto exit_free;
+ }
+
targets->supported_protocols =
nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A_SAK]);
targets->sens_res =
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]);
targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK];
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN];
- if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
+ if (targets->nfcid1_len > sizeof(targets->nfcid1) ||
+ targets->nfcid1_len > skb->len - MICROREAD_EMCF_A_UID) {
r = -EINVAL;
goto exit_free;
}
@@ -497,13 +503,19 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
targets->nfcid1_len);
break;
case MICROREAD_GATE_ID_MREAD_ISO_A_3:
+ if (skb->len <= MICROREAD_EMCF_A3_LEN) {
+ r = -EINVAL;
+ goto exit_free;
+ }
+
targets->supported_protocols =
nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A3_SAK]);
targets->sens_res =
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]);
targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK];
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN];
- if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
+ if (targets->nfcid1_len > sizeof(targets->nfcid1) ||
+ targets->nfcid1_len > skb->len - MICROREAD_EMCF_A3_UID) {
r = -EINVAL;
goto exit_free;
}
@@ -511,11 +523,21 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
targets->nfcid1_len);
break;
case MICROREAD_GATE_ID_MREAD_ISO_B:
+ if (skb->len < MICROREAD_EMCF_B_UID + 4) {
+ r = -EINVAL;
+ goto exit_free;
+ }
+
targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_B_UID], 4);
targets->nfcid1_len = 4;
break;
case MICROREAD_GATE_ID_MREAD_NFC_T1:
+ if (skb->len < MICROREAD_EMCF_T1_UID + 4) {
+ r = -EINVAL;
+ goto exit_free;
+ }
+
targets->supported_protocols = NFC_PROTO_JEWEL_MASK;
targets->sens_res =
le16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_T1_ATQA]);
@@ -523,6 +545,11 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
targets->nfcid1_len = 4;
break;
case MICROREAD_GATE_ID_MREAD_NFC_T3:
+ if (skb->len < MICROREAD_EMCF_T3_UID + 8) {
+ r = -EINVAL;
+ goto exit_free;
+ }
+
targets->supported_protocols = NFC_PROTO_FELICA_MASK;
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T3_UID], 8);
targets->nfcid1_len = 8;
--
2.50.1 (Apple Git-155)
© 2016 - 2026 Red Hat, Inc.