Skip to content

Commit c692db8

Browse files
mthalmeiSasha Levin
authored andcommitted
net: nfc: nci: Fix parameter validation for packet data
[ Upstream commit 571dcbe ] Since commit 9c328f5 ("net: nfc: nci: Add parameter validation for packet data") communication with nci nfc chips is not working any more. The mentioned commit tries to fix access of uninitialized data, but failed to understand that in some cases the data packet is of variable length and can therefore not be compared to the maximum packet length given by the sizeof(struct). Fixes: 9c328f5 ("net: nfc: nci: Add parameter validation for packet data") Cc: stable@vger.kernel.org Signed-off-by: Michael Thalmeier <michael.thalmeier@hale.at> Reported-by: syzbot+740e04c2a93467a0f8c8@syzkaller.appspotmail.com Link: https://patch.msgid.link/20260218083000.301354-1-michael.thalmeier@hale.at Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent b1e034a commit c692db8

1 file changed

Lines changed: 141 additions & 18 deletions

File tree

net/nfc/nci/ntf.c

Lines changed: 141 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static int nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
5858
struct nci_conn_info *conn_info;
5959
int i;
6060

61-
if (skb->len < sizeof(struct nci_core_conn_credit_ntf))
61+
if (skb->len < offsetofend(struct nci_core_conn_credit_ntf, num_entries))
6262
return -EINVAL;
6363

6464
ntf = (struct nci_core_conn_credit_ntf *)skb->data;
@@ -68,6 +68,10 @@ static int nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
6868
if (ntf->num_entries > NCI_MAX_NUM_CONN)
6969
ntf->num_entries = NCI_MAX_NUM_CONN;
7070

71+
if (skb->len < offsetofend(struct nci_core_conn_credit_ntf, num_entries) +
72+
ntf->num_entries * sizeof(struct conn_credit_entry))
73+
return -EINVAL;
74+
7175
/* update the credits */
7276
for (i = 0; i < ntf->num_entries; i++) {
7377
ntf->conn_entries[i].conn_id =
@@ -138,23 +142,48 @@ static int nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev,
138142
static const __u8 *
139143
nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
140144
struct rf_tech_specific_params_nfca_poll *nfca_poll,
141-
const __u8 *data)
145+
const __u8 *data, ssize_t data_len)
142146
{
147+
/* Check if we have enough data for sens_res (2 bytes) */
148+
if (data_len < 2)
149+
return ERR_PTR(-EINVAL);
150+
143151
nfca_poll->sens_res = __le16_to_cpu(*((__le16 *)data));
144152
data += 2;
153+
data_len -= 2;
154+
155+
/* Check if we have enough data for nfcid1_len (1 byte) */
156+
if (data_len < 1)
157+
return ERR_PTR(-EINVAL);
145158

146159
nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE);
160+
data_len--;
147161

148162
pr_debug("sens_res 0x%x, nfcid1_len %d\n",
149163
nfca_poll->sens_res, nfca_poll->nfcid1_len);
150164

165+
/* Check if we have enough data for nfcid1 */
166+
if (data_len < nfca_poll->nfcid1_len)
167+
return ERR_PTR(-EINVAL);
168+
151169
memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len);
152170
data += nfca_poll->nfcid1_len;
171+
data_len -= nfca_poll->nfcid1_len;
172+
173+
/* Check if we have enough data for sel_res_len (1 byte) */
174+
if (data_len < 1)
175+
return ERR_PTR(-EINVAL);
153176

154177
nfca_poll->sel_res_len = *data++;
178+
data_len--;
179+
180+
if (nfca_poll->sel_res_len != 0) {
181+
/* Check if we have enough data for sel_res (1 byte) */
182+
if (data_len < 1)
183+
return ERR_PTR(-EINVAL);
155184

156-
if (nfca_poll->sel_res_len != 0)
157185
nfca_poll->sel_res = *data++;
186+
}
158187

159188
pr_debug("sel_res_len %d, sel_res 0x%x\n",
160189
nfca_poll->sel_res_len,
@@ -166,12 +195,21 @@ nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
166195
static const __u8 *
167196
nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev,
168197
struct rf_tech_specific_params_nfcb_poll *nfcb_poll,
169-
const __u8 *data)
198+
const __u8 *data, ssize_t data_len)
170199
{
200+
/* Check if we have enough data for sensb_res_len (1 byte) */
201+
if (data_len < 1)
202+
return ERR_PTR(-EINVAL);
203+
171204
nfcb_poll->sensb_res_len = min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE);
205+
data_len--;
172206

173207
pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len);
174208

209+
/* Check if we have enough data for sensb_res */
210+
if (data_len < nfcb_poll->sensb_res_len)
211+
return ERR_PTR(-EINVAL);
212+
175213
memcpy(nfcb_poll->sensb_res, data, nfcb_poll->sensb_res_len);
176214
data += nfcb_poll->sensb_res_len;
177215

@@ -181,14 +219,29 @@ nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev,
181219
static const __u8 *
182220
nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev,
183221
struct rf_tech_specific_params_nfcf_poll *nfcf_poll,
184-
const __u8 *data)
222+
const __u8 *data, ssize_t data_len)
185223
{
224+
/* Check if we have enough data for bit_rate (1 byte) */
225+
if (data_len < 1)
226+
return ERR_PTR(-EINVAL);
227+
186228
nfcf_poll->bit_rate = *data++;
229+
data_len--;
230+
231+
/* Check if we have enough data for sensf_res_len (1 byte) */
232+
if (data_len < 1)
233+
return ERR_PTR(-EINVAL);
234+
187235
nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE);
236+
data_len--;
188237

189238
pr_debug("bit_rate %d, sensf_res_len %d\n",
190239
nfcf_poll->bit_rate, nfcf_poll->sensf_res_len);
191240

241+
/* Check if we have enough data for sensf_res */
242+
if (data_len < nfcf_poll->sensf_res_len)
243+
return ERR_PTR(-EINVAL);
244+
192245
memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len);
193246
data += nfcf_poll->sensf_res_len;
194247

@@ -198,22 +251,49 @@ nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev,
198251
static const __u8 *
199252
nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev,
200253
struct rf_tech_specific_params_nfcv_poll *nfcv_poll,
201-
const __u8 *data)
254+
const __u8 *data, ssize_t data_len)
202255
{
256+
/* Skip 1 byte (reserved) */
257+
if (data_len < 1)
258+
return ERR_PTR(-EINVAL);
259+
203260
++data;
261+
data_len--;
262+
263+
/* Check if we have enough data for dsfid (1 byte) */
264+
if (data_len < 1)
265+
return ERR_PTR(-EINVAL);
266+
204267
nfcv_poll->dsfid = *data++;
268+
data_len--;
269+
270+
/* Check if we have enough data for uid (8 bytes) */
271+
if (data_len < NFC_ISO15693_UID_MAXSIZE)
272+
return ERR_PTR(-EINVAL);
273+
205274
memcpy(nfcv_poll->uid, data, NFC_ISO15693_UID_MAXSIZE);
206275
data += NFC_ISO15693_UID_MAXSIZE;
276+
207277
return data;
208278
}
209279

210280
static const __u8 *
211281
nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev,
212282
struct rf_tech_specific_params_nfcf_listen *nfcf_listen,
213-
const __u8 *data)
283+
const __u8 *data, ssize_t data_len)
214284
{
285+
/* Check if we have enough data for local_nfcid2_len (1 byte) */
286+
if (data_len < 1)
287+
return ERR_PTR(-EINVAL);
288+
215289
nfcf_listen->local_nfcid2_len = min_t(__u8, *data++,
216290
NFC_NFCID2_MAXSIZE);
291+
data_len--;
292+
293+
/* Check if we have enough data for local_nfcid2 */
294+
if (data_len < nfcf_listen->local_nfcid2_len)
295+
return ERR_PTR(-EINVAL);
296+
217297
memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len);
218298
data += nfcf_listen->local_nfcid2_len;
219299

@@ -364,7 +444,7 @@ static int nci_rf_discover_ntf_packet(struct nci_dev *ndev,
364444
const __u8 *data;
365445
bool add_target = true;
366446

367-
if (skb->len < sizeof(struct nci_rf_discover_ntf))
447+
if (skb->len < offsetofend(struct nci_rf_discover_ntf, rf_tech_specific_params_len))
368448
return -EINVAL;
369449

370450
data = skb->data;
@@ -380,26 +460,42 @@ static int nci_rf_discover_ntf_packet(struct nci_dev *ndev,
380460
pr_debug("rf_tech_specific_params_len %d\n",
381461
ntf.rf_tech_specific_params_len);
382462

463+
if (skb->len < (data - skb->data) +
464+
ntf.rf_tech_specific_params_len + sizeof(ntf.ntf_type))
465+
return -EINVAL;
466+
383467
if (ntf.rf_tech_specific_params_len > 0) {
384468
switch (ntf.rf_tech_and_mode) {
385469
case NCI_NFC_A_PASSIVE_POLL_MODE:
386470
data = nci_extract_rf_params_nfca_passive_poll(ndev,
387-
&(ntf.rf_tech_specific_params.nfca_poll), data);
471+
&(ntf.rf_tech_specific_params.nfca_poll), data,
472+
ntf.rf_tech_specific_params_len);
473+
if (IS_ERR(data))
474+
return PTR_ERR(data);
388475
break;
389476

390477
case NCI_NFC_B_PASSIVE_POLL_MODE:
391478
data = nci_extract_rf_params_nfcb_passive_poll(ndev,
392-
&(ntf.rf_tech_specific_params.nfcb_poll), data);
479+
&(ntf.rf_tech_specific_params.nfcb_poll), data,
480+
ntf.rf_tech_specific_params_len);
481+
if (IS_ERR(data))
482+
return PTR_ERR(data);
393483
break;
394484

395485
case NCI_NFC_F_PASSIVE_POLL_MODE:
396486
data = nci_extract_rf_params_nfcf_passive_poll(ndev,
397-
&(ntf.rf_tech_specific_params.nfcf_poll), data);
487+
&(ntf.rf_tech_specific_params.nfcf_poll), data,
488+
ntf.rf_tech_specific_params_len);
489+
if (IS_ERR(data))
490+
return PTR_ERR(data);
398491
break;
399492

400493
case NCI_NFC_V_PASSIVE_POLL_MODE:
401494
data = nci_extract_rf_params_nfcv_passive_poll(ndev,
402-
&(ntf.rf_tech_specific_params.nfcv_poll), data);
495+
&(ntf.rf_tech_specific_params.nfcv_poll), data,
496+
ntf.rf_tech_specific_params_len);
497+
if (IS_ERR(data))
498+
return PTR_ERR(data);
403499
break;
404500

405501
default:
@@ -596,7 +692,7 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
596692
const __u8 *data;
597693
int err = NCI_STATUS_OK;
598694

599-
if (skb->len < sizeof(struct nci_rf_intf_activated_ntf))
695+
if (skb->len < offsetofend(struct nci_rf_intf_activated_ntf, rf_tech_specific_params_len))
600696
return -EINVAL;
601697

602698
data = skb->data;
@@ -628,26 +724,41 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
628724
if (ntf.rf_interface == NCI_RF_INTERFACE_NFCEE_DIRECT)
629725
goto listen;
630726

727+
if (skb->len < (data - skb->data) + ntf.rf_tech_specific_params_len)
728+
return -EINVAL;
729+
631730
if (ntf.rf_tech_specific_params_len > 0) {
632731
switch (ntf.activation_rf_tech_and_mode) {
633732
case NCI_NFC_A_PASSIVE_POLL_MODE:
634733
data = nci_extract_rf_params_nfca_passive_poll(ndev,
635-
&(ntf.rf_tech_specific_params.nfca_poll), data);
734+
&(ntf.rf_tech_specific_params.nfca_poll), data,
735+
ntf.rf_tech_specific_params_len);
736+
if (IS_ERR(data))
737+
return -EINVAL;
636738
break;
637739

638740
case NCI_NFC_B_PASSIVE_POLL_MODE:
639741
data = nci_extract_rf_params_nfcb_passive_poll(ndev,
640-
&(ntf.rf_tech_specific_params.nfcb_poll), data);
742+
&(ntf.rf_tech_specific_params.nfcb_poll), data,
743+
ntf.rf_tech_specific_params_len);
744+
if (IS_ERR(data))
745+
return -EINVAL;
641746
break;
642747

643748
case NCI_NFC_F_PASSIVE_POLL_MODE:
644749
data = nci_extract_rf_params_nfcf_passive_poll(ndev,
645-
&(ntf.rf_tech_specific_params.nfcf_poll), data);
750+
&(ntf.rf_tech_specific_params.nfcf_poll), data,
751+
ntf.rf_tech_specific_params_len);
752+
if (IS_ERR(data))
753+
return -EINVAL;
646754
break;
647755

648756
case NCI_NFC_V_PASSIVE_POLL_MODE:
649757
data = nci_extract_rf_params_nfcv_passive_poll(ndev,
650-
&(ntf.rf_tech_specific_params.nfcv_poll), data);
758+
&(ntf.rf_tech_specific_params.nfcv_poll), data,
759+
ntf.rf_tech_specific_params_len);
760+
if (IS_ERR(data))
761+
return -EINVAL;
651762
break;
652763

653764
case NCI_NFC_A_PASSIVE_LISTEN_MODE:
@@ -657,7 +768,9 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
657768
case NCI_NFC_F_PASSIVE_LISTEN_MODE:
658769
data = nci_extract_rf_params_nfcf_passive_listen(ndev,
659770
&(ntf.rf_tech_specific_params.nfcf_listen),
660-
data);
771+
data, ntf.rf_tech_specific_params_len);
772+
if (IS_ERR(data))
773+
return -EINVAL;
661774
break;
662775

663776
default:
@@ -668,6 +781,13 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
668781
}
669782
}
670783

784+
if (skb->len < (data - skb->data) +
785+
sizeof(ntf.data_exch_rf_tech_and_mode) +
786+
sizeof(ntf.data_exch_tx_bit_rate) +
787+
sizeof(ntf.data_exch_rx_bit_rate) +
788+
sizeof(ntf.activation_params_len))
789+
return -EINVAL;
790+
671791
ntf.data_exch_rf_tech_and_mode = *data++;
672792
ntf.data_exch_tx_bit_rate = *data++;
673793
ntf.data_exch_rx_bit_rate = *data++;
@@ -679,6 +799,9 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
679799
pr_debug("data_exch_rx_bit_rate 0x%x\n", ntf.data_exch_rx_bit_rate);
680800
pr_debug("activation_params_len %d\n", ntf.activation_params_len);
681801

802+
if (skb->len < (data - skb->data) + ntf.activation_params_len)
803+
return -EINVAL;
804+
682805
if (ntf.activation_params_len > 0) {
683806
switch (ntf.rf_interface) {
684807
case NCI_RF_INTERFACE_ISO_DEP:

0 commit comments

Comments
 (0)