summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-12-03 15:28:33 +0100
committerHans de Goede <hdegoede@redhat.com>2012-12-05 00:39:09 +0100
commit356e8098afb51437067f4e0c421307c90a45185b (patch)
treec2eb3c176c3505a55a6b53c95af98edfee4ddb6c
parent6ae6de3786e2b46096ee556079637ff696f6e4fc (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.c89
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);