15
15
16
16
#define VERSION "0.1"
17
17
18
- #define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})
19
-
20
18
int qca_read_soc_version (struct hci_dev * hdev , struct qca_btsoc_version * ver ,
21
19
enum qca_btsoc_type soc_type )
22
20
{
@@ -101,7 +99,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
101
99
{
102
100
struct sk_buff * skb ;
103
101
struct edl_event_hdr * edl ;
104
- char cmd , build_label [QCA_FW_BUILD_VER_LEN ];
102
+ char * build_label ;
103
+ char cmd ;
105
104
int build_lbl_len , err = 0 ;
106
105
107
106
bt_dev_dbg (hdev , "QCA read fw build info" );
@@ -116,6 +115,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
116
115
return err ;
117
116
}
118
117
118
+ if (skb -> len < sizeof (* edl )) {
119
+ err = - EILSEQ ;
120
+ goto out ;
121
+ }
122
+
119
123
edl = (struct edl_event_hdr * )(skb -> data );
120
124
if (!edl ) {
121
125
bt_dev_err (hdev , "QCA read fw build info with no header" );
@@ -131,14 +135,25 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
131
135
goto out ;
132
136
}
133
137
138
+ if (skb -> len < sizeof (* edl ) + 1 ) {
139
+ err = - EILSEQ ;
140
+ goto out ;
141
+ }
142
+
134
143
build_lbl_len = edl -> data [0 ];
135
- if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1 ) {
136
- memcpy (build_label , edl -> data + 1 , build_lbl_len );
137
- * (build_label + build_lbl_len ) = '\0' ;
144
+
145
+ if (skb -> len < sizeof (* edl ) + 1 + build_lbl_len ) {
146
+ err = - EILSEQ ;
147
+ goto out ;
138
148
}
139
149
150
+ build_label = kstrndup (& edl -> data [1 ], build_lbl_len , GFP_KERNEL );
151
+ if (!build_label )
152
+ goto out ;
153
+
140
154
hci_set_fw_info (hdev , "%s" , build_label );
141
155
156
+ kfree (build_label );
142
157
out :
143
158
kfree_skb (skb );
144
159
return err ;
@@ -237,6 +252,11 @@ static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
237
252
goto out ;
238
253
}
239
254
255
+ if (skb -> len < 3 ) {
256
+ err = - EILSEQ ;
257
+ goto out ;
258
+ }
259
+
240
260
* bid = (edl -> data [1 ] << 8 ) + edl -> data [2 ];
241
261
bt_dev_dbg (hdev , "%s: bid = %x" , __func__ , * bid );
242
262
@@ -267,9 +287,10 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
267
287
}
268
288
EXPORT_SYMBOL_GPL (qca_send_pre_shutdown_cmd );
269
289
270
- static void qca_tlv_check_data (struct hci_dev * hdev ,
290
+ static int qca_tlv_check_data (struct hci_dev * hdev ,
271
291
struct qca_fw_config * config ,
272
- u8 * fw_data , enum qca_btsoc_type soc_type )
292
+ u8 * fw_data , size_t fw_size ,
293
+ enum qca_btsoc_type soc_type )
273
294
{
274
295
const u8 * data ;
275
296
u32 type_len ;
@@ -279,12 +300,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
279
300
struct tlv_type_patch * tlv_patch ;
280
301
struct tlv_type_nvm * tlv_nvm ;
281
302
uint8_t nvm_baud_rate = config -> user_baud_rate ;
303
+ u8 type ;
282
304
283
305
config -> dnld_mode = QCA_SKIP_EVT_NONE ;
284
306
config -> dnld_type = QCA_SKIP_EVT_NONE ;
285
307
286
308
switch (config -> type ) {
287
309
case ELF_TYPE_PATCH :
310
+ if (fw_size < 7 )
311
+ return - EINVAL ;
312
+
288
313
config -> dnld_mode = QCA_SKIP_EVT_VSE_CC ;
289
314
config -> dnld_type = QCA_SKIP_EVT_VSE_CC ;
290
315
@@ -293,6 +318,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
293
318
bt_dev_dbg (hdev , "File version : 0x%x" , fw_data [6 ]);
294
319
break ;
295
320
case TLV_TYPE_PATCH :
321
+ if (fw_size < sizeof (struct tlv_type_hdr ) + sizeof (struct tlv_type_patch ))
322
+ return - EINVAL ;
323
+
296
324
tlv = (struct tlv_type_hdr * )fw_data ;
297
325
type_len = le32_to_cpu (tlv -> type_len );
298
326
tlv_patch = (struct tlv_type_patch * )tlv -> data ;
@@ -332,25 +360,64 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
332
360
break ;
333
361
334
362
case TLV_TYPE_NVM :
363
+ if (fw_size < sizeof (struct tlv_type_hdr ))
364
+ return - EINVAL ;
365
+
335
366
tlv = (struct tlv_type_hdr * )fw_data ;
336
367
337
368
type_len = le32_to_cpu (tlv -> type_len );
338
- length = (type_len >> 8 ) & 0x00ffffff ;
369
+ length = type_len >> 8 ;
370
+ type = type_len & 0xff ;
339
371
340
- BT_DBG ("TLV Type\t\t : 0x%x" , type_len & 0x000000ff );
372
+ /* Some NVM files have more than one set of tags, only parse
373
+ * the first set when it has type 2 for now. When there is
374
+ * more than one set there is an enclosing header of type 4.
375
+ */
376
+ if (type == 4 ) {
377
+ if (fw_size < 2 * sizeof (struct tlv_type_hdr ))
378
+ return - EINVAL ;
379
+
380
+ tlv ++ ;
381
+
382
+ type_len = le32_to_cpu (tlv -> type_len );
383
+ length = type_len >> 8 ;
384
+ type = type_len & 0xff ;
385
+ }
386
+
387
+ BT_DBG ("TLV Type\t\t : 0x%x" , type );
341
388
BT_DBG ("Length\t\t : %d bytes" , length );
342
389
390
+ if (type != 2 )
391
+ break ;
392
+
393
+ if (fw_size < length + (tlv -> data - fw_data ))
394
+ return - EINVAL ;
395
+
343
396
idx = 0 ;
344
397
data = tlv -> data ;
345
- while (idx < length ) {
398
+ while (idx < length - sizeof ( struct tlv_type_nvm ) ) {
346
399
tlv_nvm = (struct tlv_type_nvm * )(data + idx );
347
400
348
401
tag_id = le16_to_cpu (tlv_nvm -> tag_id );
349
402
tag_len = le16_to_cpu (tlv_nvm -> tag_len );
350
403
404
+ if (length < idx + sizeof (struct tlv_type_nvm ) + tag_len )
405
+ return - EINVAL ;
406
+
351
407
/* Update NVM tags as needed */
352
408
switch (tag_id ) {
409
+ case EDL_TAG_ID_BD_ADDR :
410
+ if (tag_len != sizeof (bdaddr_t ))
411
+ return - EINVAL ;
412
+
413
+ memcpy (& config -> bdaddr , tlv_nvm -> data , sizeof (bdaddr_t ));
414
+
415
+ break ;
416
+
353
417
case EDL_TAG_ID_HCI :
418
+ if (tag_len < 3 )
419
+ return - EINVAL ;
420
+
354
421
/* HCI transport layer parameters
355
422
* enabling software inband sleep
356
423
* onto controller side.
@@ -366,6 +433,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
366
433
break ;
367
434
368
435
case EDL_TAG_ID_DEEP_SLEEP :
436
+ if (tag_len < 1 )
437
+ return - EINVAL ;
438
+
369
439
/* Sleep enable mask
370
440
* enabling deep sleep feature on controller.
371
441
*/
@@ -374,14 +444,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
374
444
break ;
375
445
}
376
446
377
- idx += ( sizeof (u16 ) + sizeof ( u16 ) + 8 + tag_len ) ;
447
+ idx += sizeof (struct tlv_type_nvm ) + tag_len ;
378
448
}
379
449
break ;
380
450
381
451
default :
382
452
BT_ERR ("Unknown TLV type %d" , config -> type );
383
- break ;
453
+ return - EINVAL ;
384
454
}
455
+
456
+ return 0 ;
385
457
}
386
458
387
459
static int qca_tlv_send_segment (struct hci_dev * hdev , int seg_size ,
@@ -531,7 +603,9 @@ static int qca_download_firmware(struct hci_dev *hdev,
531
603
memcpy (data , fw -> data , size );
532
604
release_firmware (fw );
533
605
534
- qca_tlv_check_data (hdev , config , data , soc_type );
606
+ ret = qca_tlv_check_data (hdev , config , data , size , soc_type );
607
+ if (ret )
608
+ goto out ;
535
609
536
610
segment = data ;
537
611
remain = size ;
@@ -614,7 +688,7 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
614
688
}
615
689
EXPORT_SYMBOL_GPL (qca_set_bdaddr_rome );
616
690
617
- static int qca_check_bdaddr (struct hci_dev * hdev )
691
+ static int qca_check_bdaddr (struct hci_dev * hdev , const struct qca_fw_config * config )
618
692
{
619
693
struct hci_rp_read_bd_addr * bda ;
620
694
struct sk_buff * skb ;
@@ -638,7 +712,7 @@ static int qca_check_bdaddr(struct hci_dev *hdev)
638
712
}
639
713
640
714
bda = (struct hci_rp_read_bd_addr * )skb -> data ;
641
- if (!bacmp (& bda -> bdaddr , QCA_BDADDR_DEFAULT ))
715
+ if (!bacmp (& bda -> bdaddr , & config -> bdaddr ))
642
716
set_bit (HCI_QUIRK_USE_BDADDR_PROPERTY , & hdev -> quirks );
643
717
644
718
kfree_skb (skb );
@@ -667,7 +741,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
667
741
enum qca_btsoc_type soc_type , struct qca_btsoc_version ver ,
668
742
const char * firmware_name )
669
743
{
670
- struct qca_fw_config config ;
744
+ struct qca_fw_config config = {} ;
671
745
int err ;
672
746
u8 rom_ver = 0 ;
673
747
u32 soc_ver ;
@@ -852,7 +926,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
852
926
break ;
853
927
}
854
928
855
- err = qca_check_bdaddr (hdev );
929
+ err = qca_check_bdaddr (hdev , & config );
856
930
if (err )
857
931
return err ;
858
932
0 commit comments