1515
1616#define VERSION "0.1"
1717
18- #define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})
19-
2018int qca_read_soc_version (struct hci_dev * hdev , struct qca_btsoc_version * ver ,
2119 enum qca_btsoc_type soc_type )
2220{
@@ -101,7 +99,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
10199{
102100 struct sk_buff * skb ;
103101 struct edl_event_hdr * edl ;
104- char cmd , build_label [QCA_FW_BUILD_VER_LEN ];
102+ char * build_label ;
103+ char cmd ;
105104 int build_lbl_len , err = 0 ;
106105
107106 bt_dev_dbg (hdev , "QCA read fw build info" );
@@ -116,6 +115,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
116115 return err ;
117116 }
118117
118+ if (skb -> len < sizeof (* edl )) {
119+ err = - EILSEQ ;
120+ goto out ;
121+ }
122+
119123 edl = (struct edl_event_hdr * )(skb -> data );
120124 if (!edl ) {
121125 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)
131135 goto out ;
132136 }
133137
138+ if (skb -> len < sizeof (* edl ) + 1 ) {
139+ err = - EILSEQ ;
140+ goto out ;
141+ }
142+
134143 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 ;
138148 }
139149
150+ build_label = kstrndup (& edl -> data [1 ], build_lbl_len , GFP_KERNEL );
151+ if (!build_label )
152+ goto out ;
153+
140154 hci_set_fw_info (hdev , "%s" , build_label );
141155
156+ kfree (build_label );
142157out :
143158 kfree_skb (skb );
144159 return err ;
@@ -237,6 +252,11 @@ static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
237252 goto out ;
238253 }
239254
255+ if (skb -> len < 3 ) {
256+ err = - EILSEQ ;
257+ goto out ;
258+ }
259+
240260 * bid = (edl -> data [1 ] << 8 ) + edl -> data [2 ];
241261 bt_dev_dbg (hdev , "%s: bid = %x" , __func__ , * bid );
242262
@@ -267,9 +287,10 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
267287}
268288EXPORT_SYMBOL_GPL (qca_send_pre_shutdown_cmd );
269289
270- static void qca_tlv_check_data (struct hci_dev * hdev ,
290+ static int qca_tlv_check_data (struct hci_dev * hdev ,
271291 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 )
273294{
274295 const u8 * data ;
275296 u32 type_len ;
@@ -279,12 +300,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
279300 struct tlv_type_patch * tlv_patch ;
280301 struct tlv_type_nvm * tlv_nvm ;
281302 uint8_t nvm_baud_rate = config -> user_baud_rate ;
303+ u8 type ;
282304
283305 config -> dnld_mode = QCA_SKIP_EVT_NONE ;
284306 config -> dnld_type = QCA_SKIP_EVT_NONE ;
285307
286308 switch (config -> type ) {
287309 case ELF_TYPE_PATCH :
310+ if (fw_size < 7 )
311+ return - EINVAL ;
312+
288313 config -> dnld_mode = QCA_SKIP_EVT_VSE_CC ;
289314 config -> dnld_type = QCA_SKIP_EVT_VSE_CC ;
290315
@@ -293,6 +318,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
293318 bt_dev_dbg (hdev , "File version : 0x%x" , fw_data [6 ]);
294319 break ;
295320 case TLV_TYPE_PATCH :
321+ if (fw_size < sizeof (struct tlv_type_hdr ) + sizeof (struct tlv_type_patch ))
322+ return - EINVAL ;
323+
296324 tlv = (struct tlv_type_hdr * )fw_data ;
297325 type_len = le32_to_cpu (tlv -> type_len );
298326 tlv_patch = (struct tlv_type_patch * )tlv -> data ;
@@ -332,25 +360,64 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
332360 break ;
333361
334362 case TLV_TYPE_NVM :
363+ if (fw_size < sizeof (struct tlv_type_hdr ))
364+ return - EINVAL ;
365+
335366 tlv = (struct tlv_type_hdr * )fw_data ;
336367
337368 type_len = le32_to_cpu (tlv -> type_len );
338- length = (type_len >> 8 ) & 0x00ffffff ;
369+ length = type_len >> 8 ;
370+ type = type_len & 0xff ;
339371
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 );
341388 BT_DBG ("Length\t\t : %d bytes" , length );
342389
390+ if (type != 2 )
391+ break ;
392+
393+ if (fw_size < length + (tlv -> data - fw_data ))
394+ return - EINVAL ;
395+
343396 idx = 0 ;
344397 data = tlv -> data ;
345- while (idx < length ) {
398+ while (idx < length - sizeof ( struct tlv_type_nvm ) ) {
346399 tlv_nvm = (struct tlv_type_nvm * )(data + idx );
347400
348401 tag_id = le16_to_cpu (tlv_nvm -> tag_id );
349402 tag_len = le16_to_cpu (tlv_nvm -> tag_len );
350403
404+ if (length < idx + sizeof (struct tlv_type_nvm ) + tag_len )
405+ return - EINVAL ;
406+
351407 /* Update NVM tags as needed */
352408 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+
353417 case EDL_TAG_ID_HCI :
418+ if (tag_len < 3 )
419+ return - EINVAL ;
420+
354421 /* HCI transport layer parameters
355422 * enabling software inband sleep
356423 * onto controller side.
@@ -366,6 +433,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
366433 break ;
367434
368435 case EDL_TAG_ID_DEEP_SLEEP :
436+ if (tag_len < 1 )
437+ return - EINVAL ;
438+
369439 /* Sleep enable mask
370440 * enabling deep sleep feature on controller.
371441 */
@@ -374,14 +444,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
374444 break ;
375445 }
376446
377- idx += ( sizeof (u16 ) + sizeof ( u16 ) + 8 + tag_len ) ;
447+ idx += sizeof (struct tlv_type_nvm ) + tag_len ;
378448 }
379449 break ;
380450
381451 default :
382452 BT_ERR ("Unknown TLV type %d" , config -> type );
383- break ;
453+ return - EINVAL ;
384454 }
455+
456+ return 0 ;
385457}
386458
387459static 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,
531603 memcpy (data , fw -> data , size );
532604 release_firmware (fw );
533605
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 ;
535609
536610 segment = data ;
537611 remain = size ;
@@ -614,7 +688,7 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
614688}
615689EXPORT_SYMBOL_GPL (qca_set_bdaddr_rome );
616690
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 )
618692{
619693 struct hci_rp_read_bd_addr * bda ;
620694 struct sk_buff * skb ;
@@ -638,7 +712,7 @@ static int qca_check_bdaddr(struct hci_dev *hdev)
638712 }
639713
640714 bda = (struct hci_rp_read_bd_addr * )skb -> data ;
641- if (!bacmp (& bda -> bdaddr , QCA_BDADDR_DEFAULT ))
715+ if (!bacmp (& bda -> bdaddr , & config -> bdaddr ))
642716 set_bit (HCI_QUIRK_USE_BDADDR_PROPERTY , & hdev -> quirks );
643717
644718 kfree_skb (skb );
@@ -667,7 +741,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
667741 enum qca_btsoc_type soc_type , struct qca_btsoc_version ver ,
668742 const char * firmware_name )
669743{
670- struct qca_fw_config config ;
744+ struct qca_fw_config config = {} ;
671745 int err ;
672746 u8 rom_ver = 0 ;
673747 u32 soc_ver ;
@@ -852,7 +926,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
852926 break ;
853927 }
854928
855- err = qca_check_bdaddr (hdev );
929+ err = qca_check_bdaddr (hdev , & config );
856930 if (err )
857931 return err ;
858932
0 commit comments