@@ -47,7 +47,7 @@ struct usb_info {
4747 struct usb_device_index index ;
4848};
4949
50- #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \
50+ #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || \
5151 __NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write
5252static struct usb_info usb_devices [USB_MAX_FDS ];
5353
@@ -61,7 +61,7 @@ static struct usb_device_index* lookup_usb_index(int fd)
6161}
6262#endif
6363
64- #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
64+ #if SYZ_EXECUTOR || __NR_syz_usb_connect
6565static int usb_devices_num ;
6666
6767static bool parse_usb_descriptor (const char * buffer , size_t length , struct usb_device_index * index )
@@ -128,7 +128,7 @@ static struct usb_device_index* add_usb_index(int fd, const char* dev, size_t de
128128 return & usb_devices [i ].index ;
129129}
130130
131- #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
131+ #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect
132132
133133#if USB_DEBUG
134134
@@ -567,7 +567,39 @@ struct vusb_connect_descriptors {
567567 struct vusb_connect_string_descriptor strs [0 ];
568568} __attribute__((packed ));
569569
570- #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
570+ #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_control_io || __NR_syz_usb_finish_probe
571+
572+ struct vusb_descriptor {
573+ uint8 req_type ;
574+ uint8 desc_type ;
575+ uint32 len ;
576+ char data [0 ];
577+ } __attribute__((packed ));
578+
579+ struct vusb_descriptors {
580+ uint32 len ;
581+ struct vusb_descriptor * generic ;
582+ struct vusb_descriptor * descs [0 ];
583+ } __attribute__((packed ));
584+
585+ struct vusb_response {
586+ uint8 type ;
587+ uint8 req ;
588+ uint32 len ;
589+ // Number of times this request *should* be processed. 0 by default.
590+ uint32 expected ;
591+ char data [0 ];
592+ } __attribute__((packed ));
593+
594+ struct vusb_responses {
595+ uint32 len ;
596+ struct vusb_response * generic ;
597+ struct vusb_response * resps [0 ];
598+ } __attribute__((packed ));
599+
600+ #endif // SYZ_EXECUTOR || __NR_syz_usb_control_io || __NR_syz_usb_finish_probe
601+
602+ #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe
571603
572604static const char default_string [] = {
573605 8 , USB_DT_STRING ,
@@ -580,24 +612,32 @@ static const char default_lang_id[] = {
580612};
581613
582614// lookup_connect_response_in() is a helper function that returns a response to a USB IN request
583- // based on syzkaller-generated arguments provided to syz_usb_connect* pseudo-syscalls. The data
584- // and its length to be used as a response are returned in *response_data and *response_length.
585- // The return value of this function lookup_connect_response_inindicates whether the request is known to syzkaller.
615+ // based on syzkaller-generated arguments provided to syz_usb_connect* and syz_usb_finish_probe*
616+ // pseudo-syscalls. The data and its length to be used as a response are returned in *response_data
617+ // and *response_length. The return value of this function lookup_connect_response_in indicates
618+ // whether the request is known to syzkaller.
619+
620+ // Use *done counter (for instance, in syz_usb_finish_probe variants) to keep track of requests
621+ // which remain to be processed.
586622
587623static bool lookup_connect_response_in (int fd , const struct vusb_connect_descriptors * descs ,
624+ const struct vusb_responses * resps ,
588625 const struct usb_ctrlrequest * ctrl ,
589626 struct usb_qualifier_descriptor * qual ,
590- char * * response_data , uint32 * response_length )
627+ char * * response_data , uint32 * response_length , int * done )
591628{
592629 struct usb_device_index * index = lookup_usb_index (fd );
593630 uint8 str_idx ;
631+ int resps_num = 0 ;
632+ uint8 req = ctrl -> bRequest ;
633+ uint8 req_type = ctrl -> bRequestType ;
594634
595635 if (!index )
596636 return false;
597637
598- switch (ctrl -> bRequestType & USB_TYPE_MASK ) {
638+ switch (req_type & USB_TYPE_MASK ) {
599639 case USB_TYPE_STANDARD :
600- switch (ctrl -> bRequest ) {
640+ switch (req ) {
601641 case USB_REQ_GET_DESCRIPTOR :
602642 switch (ctrl -> wValue >> 8 ) {
603643 case USB_DT_DEVICE :
@@ -655,107 +695,95 @@ static bool lookup_connect_response_in(int fd, const struct vusb_connect_descrip
655695 }
656696 break ;
657697 default :
658- break ;
659- }
698+ if (! resps || ! done )
699+ break ;
660700
661- debug ("lookup_connect_response_in: unknown request" );
662- return false;
663- }
701+ resps_num = (resps -> len - offsetof(struct vusb_responses , resps )) / sizeof (resps -> resps [0 ]);
664702
665- #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
703+ int i ;
704+ for (i = 0 ; i < resps_num ; i ++ ) {
705+ struct vusb_response * resp = resps -> resps [i ];
706+ if (!resp )
707+ continue ;
666708
667- // lookup_connect_response_out() functions process a USB OUT request and return in *done
668- // whether this is the last request that must be handled by syz_usb_connect* pseudo-syscalls.
709+ if ( resp -> type == req_type && resp -> req == req ) {
710+ * response_length = resp -> len ;
669711
670- typedef bool (* lookup_connect_out_response_t )(int fd , const struct vusb_connect_descriptors * descs ,
671- const struct usb_ctrlrequest * ctrl , bool * done );
712+ if (* response_length != 0 )
713+ * response_data = & resp -> data [0 ];
714+ else
715+ * response_data = NULL ;
672716
673- #if SYZ_EXECUTOR || __NR_syz_usb_connect
674- static bool lookup_connect_response_out_generic (int fd , const struct vusb_connect_descriptors * descs ,
675- const struct usb_ctrlrequest * ctrl , bool * done )
676- {
677- switch (ctrl -> bRequestType & USB_TYPE_MASK ) {
678- case USB_TYPE_STANDARD :
679- switch (ctrl -> bRequest ) {
680- case USB_REQ_SET_CONFIGURATION :
681- * done = true;
717+ if (resp -> expected != 0 )
718+ * done -= 1 ;
719+
720+ return true;
721+ }
722+ }
723+
724+ if (resps -> generic ) {
725+ * response_data = & resps -> generic -> data [0 ];
726+ * response_length = resps -> generic -> len ;
682727 return true;
683- default :
684- break ;
685728 }
686729 break ;
687730 }
688731
689- debug ("lookup_connect_response_out : unknown request" );
732+ debug ("lookup_connect_response_in : unknown request" );
690733 return false;
691734}
692- #endif // SYZ_EXECUTOR || __NR_syz_usb_connect
693-
694- #if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k )
695735
696- // drivers/net/wireless/ath/ath9k/hif_usb.h
697- #define ATH9K_FIRMWARE_DOWNLOAD 0x30
698- #define ATH9K_FIRMWARE_DOWNLOAD_COMP 0x31
736+ // lookup_connect_response_out() functions process a USB OUT request and return in *done
737+ // whether the number of requests left to be handled by syz_usb_connect* or syz_usb_finish_probe*
738+ // pseudo-syscalls.
699739
700- static bool lookup_connect_response_out_ath9k (int fd , const struct vusb_connect_descriptors * descs ,
701- const struct usb_ctrlrequest * ctrl , bool * done )
740+ static bool lookup_connect_response_out (int fd , const struct vusb_connect_descriptors * descs ,
741+ const struct vusb_responses * resps , const struct usb_ctrlrequest * ctrl , int * done )
702742{
703- switch (ctrl -> bRequestType & USB_TYPE_MASK ) {
743+ uint8 req = ctrl -> bRequest ;
744+ uint8 req_type = ctrl -> bRequestType ;
745+ int resps_num = 0 ;
746+
747+ switch (req_type & USB_TYPE_MASK ) {
704748 case USB_TYPE_STANDARD :
705- switch (ctrl -> bRequest ) {
749+ switch (req ) {
706750 case USB_REQ_SET_CONFIGURATION :
751+ * done -= 1 ;
707752 return true;
708753 default :
709754 break ;
710755 }
711- break ;
712- case USB_TYPE_VENDOR :
713- switch (ctrl -> bRequest ) {
714- case ATH9K_FIRMWARE_DOWNLOAD :
715- return true;
716- case ATH9K_FIRMWARE_DOWNLOAD_COMP :
717- * done = true;
718- return true;
719- default :
756+
757+ default :
758+ if (!resps )
720759 break ;
760+
761+ resps_num = (resps -> len - offsetof(struct vusb_responses , resps )) / sizeof (resps -> resps [0 ]);
762+
763+ int i ;
764+ for (i = 0 ; i < resps_num ; i ++ ) {
765+ struct vusb_response * resp = resps -> resps [i ];
766+ if (!resp )
767+ continue ;
768+
769+ if (resp -> type == req_type && resp -> req == req ) {
770+ if (resp -> expected != 0 )
771+ * done -= 1 ;
772+
773+ return true;
774+ }
721775 }
722776 break ;
723777 }
724778
725- debug ("lookup_connect_response_out_ath9k : unknown request" );
779+ debug ("lookup_connect_response_out : unknown request" );
726780 return false;
727781}
728782
729- #endif // SYZ_EXECUTOR || __NR_syz_usb_connect_ath9k
783+ #endif // #if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe
730784
731785#if GOOS_linux && (SYZ_EXECUTOR || __NR_syz_usb_control_io )
732786
733- struct vusb_descriptor {
734- uint8 req_type ;
735- uint8 desc_type ;
736- uint32 len ;
737- char data [0 ];
738- } __attribute__((packed ));
739-
740- struct vusb_descriptors {
741- uint32 len ;
742- struct vusb_descriptor * generic ;
743- struct vusb_descriptor * descs [0 ];
744- } __attribute__((packed ));
745-
746- struct vusb_response {
747- uint8 type ;
748- uint8 req ;
749- uint32 len ;
750- char data [0 ];
751- } __attribute__((packed ));
752-
753- struct vusb_responses {
754- uint32 len ;
755- struct vusb_response * generic ;
756- struct vusb_response * resps [0 ];
757- } __attribute__((packed ));
758-
759787// lookup_control_response() is a helper function that returns a response to a USB IN request based
760788// on syzkaller-generated arguments provided to syz_usb_control_io* pseudo-syscalls. The data and its
761789// length to be used as a response are returned in *response_data and *response_length. The return
0 commit comments