diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-12-03 15:28:33 +0100 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2012-12-05 00:39:09 +0100 |
commit | 356e8098afb51437067f4e0c421307c90a45185b (patch) | |
tree | c2eb3c176c3505a55a6b53c95af98edfee4ddb6c | |
parent | 6ae6de3786e2b46096ee556079637ff696f6e4fc (diff) |
usbredirparser: Verify that interrupt / bulk recv gets an input ep
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | usbredirparser/usbredirparser.c | 89 |
1 files changed, 81 insertions, 8 deletions
diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c index 113ee3a..7539c02 100644 --- a/usbredirparser/usbredirparser.c +++ b/usbredirparser/usbredirparser.c @@ -511,6 +511,22 @@ static int usbredirparser_expect_extra_data(struct usbredirparser_priv *parser) } } +static int usbredirparser_verify_bulk_recv_cap( + struct usbredirparser *parser_pub, int send) +{ + struct usbredirparser_priv *parser = + (struct usbredirparser_priv *)parser_pub; + + if ((send && !usbredirparser_peer_has_cap(parser_pub, + usb_redir_cap_bulk_receiving)) || + (!send && !usbredirparser_have_cap(parser_pub, + usb_redir_cap_bulk_receiving))) { + ERROR("error bulk_receiving without cap_bulk_receiving"); + return 0; + } + return 1; /* Verify ok */ +} + static int usbredirparser_verify_type_header( struct usbredirparser *parser_pub, int32_t type, void *header, uint8_t *data, int data_len, int send) @@ -537,6 +553,36 @@ static int usbredirparser_verify_type_header( } break; } + case usb_redir_start_interrupt_receiving: { + struct usb_redir_start_interrupt_receiving_header *start_int = header; + + if (!(start_int->endpoint & 0x80)) { + ERROR("start int receiving on non input ep %02x", + start_int->endpoint); + return 0; + } + break; + } + case usb_redir_stop_interrupt_receiving: { + struct usb_redir_stop_interrupt_receiving_header *stop_int = header; + + if (!(stop_int->endpoint & 0x80)) { + ERROR("stop int receiving on non input ep %02x", + stop_int->endpoint); + return 0; + } + break; + } + case usb_redir_interrupt_receiving_status: { + struct usb_redir_interrupt_receiving_status_header *int_status = header; + + if (!(int_status->endpoint & 0x80)) { + ERROR("int receiving status for non input ep %02x", + int_status->endpoint); + return 0; + } + break; + } case usb_redir_filter_reject: if ((send && !usbredirparser_peer_has_cap(parser_pub, usb_redir_cap_filter)) || @@ -575,23 +621,47 @@ static int usbredirparser_verify_type_header( case usb_redir_start_bulk_receiving: { struct usb_redir_start_bulk_receiving_header *start_bulk = header; + if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) { + return 0; + } if (start_bulk->bytes_per_transfer > MAX_BULK_TRANSFER_SIZE) { ERROR("start bulk receiving length exceeds limits %u > %u", start_bulk->bytes_per_transfer, MAX_BULK_TRANSFER_SIZE); return 0; } - /* Fall through for caps check */ + if (!(start_bulk->endpoint & 0x80)) { + ERROR("start bulk receiving on non input ep %02x", + start_bulk->endpoint); + return 0; + } + break; } - case usb_redir_stop_bulk_receiving: - case usb_redir_bulk_receiving_status: - if ((send && !usbredirparser_peer_has_cap(parser_pub, - usb_redir_cap_bulk_receiving)) || - (!send && !usbredirparser_have_cap(parser_pub, - usb_redir_cap_bulk_receiving))) { - ERROR("error bulk_receiving without cap_bulk_receiving"); + case usb_redir_stop_bulk_receiving: { + struct usb_redir_stop_bulk_receiving_header *stop_bulk = header; + + if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) { + return 0; + } + if (!(stop_bulk->endpoint & 0x80)) { + ERROR("stop bulk receiving on non input ep %02x", + stop_bulk->endpoint); return 0; } break; + } + case usb_redir_bulk_receiving_status: { + struct usb_redir_bulk_receiving_status_header *bulk_status = header; + + if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) { + return 0; + } + if (!(bulk_status->endpoint & 0x80)) { + ERROR("bulk receiving status for non input ep %02x", + bulk_status->endpoint); + return 0; + } + break; + } case usb_redir_control_packet: length = ((struct usb_redir_control_packet_header *)header)->length; ep = ((struct usb_redir_control_packet_header *)header)->endpoint; @@ -627,6 +697,9 @@ static int usbredirparser_verify_type_header( case usb_redir_buffered_bulk_packet: { struct usb_redir_buffered_bulk_packet_header *buf_bulk_pkt = header; length = buf_bulk_pkt->length; + if (!usbredirparser_verify_bulk_recv_cap(parser_pub, send)) { + return 0; + } if ((uint32_t)length > MAX_BULK_TRANSFER_SIZE) { ERROR("buffered bulk transfer length exceeds limits %u > %u", (uint32_t)length, MAX_BULK_TRANSFER_SIZE); |