Skip to content

Commit 8566b41

Browse files
committed
all: add new pseudo-call syz_usb_finish_probe
Full description is here.
1 parent 0595aa2 commit 8566b41

File tree

16 files changed

+512
-171
lines changed

16 files changed

+512
-171
lines changed

executor/common.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ NORETURN void doexit_thread(int status)
6666
#endif
6767
#endif
6868

69-
#if SYZ_EXECUTOR || SYZ_MULTI_PROC || SYZ_REPEAT && SYZ_CGROUPS || \
70-
SYZ_NET_DEVICES || __NR_syz_mount_image || __NR_syz_read_part_table || \
71-
__NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_usbip_server_init || \
69+
#if SYZ_EXECUTOR || SYZ_MULTI_PROC || SYZ_REPEAT && SYZ_CGROUPS || \
70+
SYZ_NET_DEVICES || __NR_syz_mount_image || __NR_syz_read_part_table || \
71+
__NR_syz_usb_connect || __NR_syz_usbip_server_init || \
7272
(GOOS_freebsd || GOOS_darwin || GOOS_openbsd || GOOS_netbsd) && SYZ_NET_INJECTION
7373
static unsigned long long procid;
7474
#endif
@@ -178,7 +178,7 @@ static void kill_and_wait(int pid, int* status)
178178

179179
#if !GOOS_windows
180180
#if SYZ_EXECUTOR || SYZ_THREADED || SYZ_REPEAT && SYZ_EXECUTOR_USES_FORK_SERVER || \
181-
__NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || __NR_syz_sleep_ms || \
181+
__NR_syz_usb_connect || __NR_syz_usb_finish_probe || __NR_syz_sleep_ms || \
182182
__NR_syz_usb_control_io || __NR_syz_usb_ep_read || __NR_syz_usb_ep_write || \
183183
__NR_syz_usb_disconnect
184184
static void sleep_ms(uint64 ms)

executor/common_linux.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ static int event_timedwait(event_t* ev, uint64 timeout)
7373
#if SYZ_EXECUTOR || SYZ_REPEAT || SYZ_NET_INJECTION || SYZ_FAULT || SYZ_SANDBOX_NONE || \
7474
SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID || \
7575
SYZ_FAULT || SYZ_LEAK || SYZ_BINFMT_MISC || SYZ_SYSCTL || \
76-
((__NR_syz_usb_connect || __NR_syz_usb_connect_ath9k) && USB_DEBUG) || \
76+
(__NR_syz_usb_connect && USB_DEBUG) || \
7777
__NR_syz_usbip_server_init
7878
#include <errno.h>
7979
#include <fcntl.h>
@@ -2376,11 +2376,11 @@ static long syz_extract_tcp_res(volatile long a0, volatile long a1, volatile lon
23762376
}
23772377
#endif
23782378

2379-
#if SYZ_EXECUTOR || SYZ_CLOSE_FDS || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k
2379+
#if SYZ_EXECUTOR || SYZ_CLOSE_FDS || __NR_syz_usb_connect
23802380
#define MAX_FDS 30
23812381
#endif
23822382

2383-
#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_connect_ath9k || \
2383+
#if SYZ_EXECUTOR || __NR_syz_usb_connect || __NR_syz_usb_finish_probe || \
23842384
__NR_syz_usb_ep_write || __NR_syz_usb_ep_read || __NR_syz_usb_control_io || \
23852385
__NR_syz_usb_disconnect
23862386
#include <errno.h>

executor/common_usb.h

Lines changed: 107 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -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
5252
static 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
6565
static int usb_devices_num;
6666

6767
static 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

572604
static 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

587623
static 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

Comments
 (0)