diff options
| author | 2010-01-23 23:09:43 +0100 | |
|---|---|---|
| committer | 2010-01-24 00:20:01 +0100 | |
| commit | c0b02222fd85feabb0b9901364082dc6ab484b68 (patch) | |
| tree | e465e0a29a24431c67feb35529912214f8d1308f | |
| parent | 68729a347011a8fb39f1e4aa35ae06c4f2f491d4 (diff) | |
| download | usbmuxd-c0b02222fd85feabb0b9901364082dc6ab484b68.tar.gz usbmuxd-c0b02222fd85feabb0b9901364082dc6ab484b68.tar.bz2 | |
Clean up packet size types and add some paranoia
None of this should fix an exploit, it's just healthy paranoia.
| -rw-r--r-- | daemon/client.c | 12 | ||||
| -rw-r--r-- | daemon/client.h | 4 | ||||
| -rw-r--r-- | daemon/device.c | 38 | ||||
| -rw-r--r-- | daemon/device.h | 2 |
4 files changed, 35 insertions, 21 deletions
diff --git a/daemon/client.c b/daemon/client.c index 5498586..4f44bcc 100644 --- a/daemon/client.c +++ b/daemon/client.c | |||
| @@ -52,11 +52,11 @@ enum client_state { | |||
| 52 | struct mux_client { | 52 | struct mux_client { |
| 53 | int fd; | 53 | int fd; |
| 54 | unsigned char *ob_buf; | 54 | unsigned char *ob_buf; |
| 55 | int ob_size; | 55 | uint32_t ob_size; |
| 56 | int ob_capacity; | 56 | uint32_t ob_capacity; |
| 57 | unsigned char *ib_buf; | 57 | unsigned char *ib_buf; |
| 58 | int ib_size; | 58 | uint32_t ib_size; |
| 59 | int ib_capacity; | 59 | uint32_t ib_capacity; |
| 60 | short events, devents; | 60 | short events, devents; |
| 61 | uint32_t connect_tag; | 61 | uint32_t connect_tag; |
| 62 | int connect_device; | 62 | int connect_device; |
| @@ -65,7 +65,7 @@ struct mux_client { | |||
| 65 | 65 | ||
| 66 | static struct collection client_list; | 66 | static struct collection client_list; |
| 67 | 67 | ||
| 68 | int client_read(struct mux_client *client, void *buffer, int len) | 68 | int client_read(struct mux_client *client, void *buffer, uint32_t len) |
| 69 | { | 69 | { |
| 70 | usbmuxd_log(LL_SPEW, "client_read fd %d buf %p len %d", client->fd, buffer, len); | 70 | usbmuxd_log(LL_SPEW, "client_read fd %d buf %p len %d", client->fd, buffer, len); |
| 71 | if(client->state != CLIENT_CONNECTED) { | 71 | if(client->state != CLIENT_CONNECTED) { |
| @@ -75,7 +75,7 @@ int client_read(struct mux_client *client, void *buffer, int len) | |||
| 75 | return recv(client->fd, buffer, len, 0); | 75 | return recv(client->fd, buffer, len, 0); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | int client_write(struct mux_client *client, void *buffer, int len) | 78 | int client_write(struct mux_client *client, void *buffer, uint32_t len) |
| 79 | { | 79 | { |
| 80 | usbmuxd_log(LL_SPEW, "client_write fd %d buf %p len %d", client->fd, buffer, len); | 80 | usbmuxd_log(LL_SPEW, "client_write fd %d buf %p len %d", client->fd, buffer, len); |
| 81 | if(client->state != CLIENT_CONNECTED) { | 81 | if(client->state != CLIENT_CONNECTED) { |
diff --git a/daemon/client.h b/daemon/client.h index 444fe15..60d8348 100644 --- a/daemon/client.h +++ b/daemon/client.h | |||
| @@ -28,8 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 28 | struct device_info; | 28 | struct device_info; |
| 29 | struct mux_client; | 29 | struct mux_client; |
| 30 | 30 | ||
| 31 | int client_read(struct mux_client *client, void *buffer, int len); | 31 | int client_read(struct mux_client *client, void *buffer, uint32_t len); |
| 32 | int client_write(struct mux_client *client, void *buffer, int len); | 32 | int client_write(struct mux_client *client, void *buffer, uint32_t len); |
| 33 | int client_set_events(struct mux_client *client, short events); | 33 | int client_set_events(struct mux_client *client, short events); |
| 34 | void client_close(struct mux_client *client); | 34 | void client_close(struct mux_client *client); |
| 35 | int client_notify_connect(struct mux_client *client, enum usbmuxd_result result); | 35 | int client_notify_connect(struct mux_client *client, enum usbmuxd_result result); |
diff --git a/daemon/device.c b/daemon/device.c index 7cda462..759cb91 100644 --- a/daemon/device.c +++ b/daemon/device.c | |||
| @@ -38,7 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 38 | 38 | ||
| 39 | int next_device_id; | 39 | int next_device_id; |
| 40 | 40 | ||
| 41 | #define DEV_PKTBUF_SIZE 65536 | 41 | #define DEV_MRU 65536 |
| 42 | 42 | ||
| 43 | #define CONN_INBUF_SIZE 262144 | 43 | #define CONN_INBUF_SIZE 262144 |
| 44 | #define CONN_OUTBUF_SIZE 65536 | 44 | #define CONN_OUTBUF_SIZE 65536 |
| @@ -90,13 +90,13 @@ struct mux_connection | |||
| 90 | uint32_t tx_seq, tx_ack, tx_acked, tx_win; | 90 | uint32_t tx_seq, tx_ack, tx_acked, tx_win; |
| 91 | uint32_t rx_seq, rx_recvd, rx_ack, rx_win; | 91 | uint32_t rx_seq, rx_recvd, rx_ack, rx_win; |
| 92 | int max_payload; | 92 | int max_payload; |
| 93 | int sendable; | 93 | uint32_t sendable; |
| 94 | int flags; | 94 | int flags; |
| 95 | unsigned char *ib_buf; | 95 | unsigned char *ib_buf; |
| 96 | int ib_size; | 96 | uint32_t ib_size; |
| 97 | int ib_capacity; | 97 | uint32_t ib_capacity; |
| 98 | unsigned char *ob_buf; | 98 | unsigned char *ob_buf; |
| 99 | int ob_capacity; | 99 | uint32_t ob_capacity; |
| 100 | short events; | 100 | short events; |
| 101 | uint64_t last_ack_time; | 101 | uint64_t last_ack_time; |
| 102 | }; | 102 | }; |
| @@ -109,7 +109,7 @@ struct mux_device | |||
| 109 | struct collection connections; | 109 | struct collection connections; |
| 110 | uint16_t next_sport; | 110 | uint16_t next_sport; |
| 111 | unsigned char *pktbuf; | 111 | unsigned char *pktbuf; |
| 112 | int pktlen; | 112 | uint32_t pktlen; |
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | static struct collection device_list; | 115 | static struct collection device_list; |
| @@ -404,7 +404,7 @@ void device_client_process(int device_id, struct mux_client *client, short event | |||
| 404 | update_connection(conn); | 404 | update_connection(conn); |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | static void connection_device_input(struct mux_connection *conn, unsigned char *payload, int payload_length) | 407 | static void connection_device_input(struct mux_connection *conn, unsigned char *payload, uint32_t payload_length) |
| 408 | { | 408 | { |
| 409 | if((conn->ib_size + payload_length) > conn->ib_capacity) { | 409 | if((conn->ib_size + payload_length) > conn->ib_capacity) { |
| 410 | usbmuxd_log(LL_ERROR, "Input buffer overflow on device %d connection %d->%d (space=%d, payload=%d)", conn->dev->id, conn->sport, conn->dport, conn->ib_capacity-conn->ib_size, payload_length); | 410 | usbmuxd_log(LL_ERROR, "Input buffer overflow on device %d connection %d->%d (space=%d, payload=%d)", conn->dev->id, conn->sport, conn->dport, conn->ib_capacity-conn->ib_size, payload_length); |
| @@ -459,7 +459,7 @@ static void device_version_input(struct mux_device *dev, struct version_header * | |||
| 459 | client_device_add(&info); | 459 | client_device_add(&info); |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned char *payload, int payload_length) | 462 | static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned char *payload, uint32_t payload_length) |
| 463 | { | 463 | { |
| 464 | usbmuxd_log(LL_DEBUG, "[IN] dev=%d sport=%d dport=%d seq=%d ack=%d flags=0x%x window=%d[%d] len=%d", | 464 | usbmuxd_log(LL_DEBUG, "[IN] dev=%d sport=%d dport=%d seq=%d ack=%d flags=0x%x window=%d[%d] len=%d", |
| 465 | dev->id, ntohs(th->th_sport), ntohs(th->th_dport), ntohl(th->th_seq), ntohl(th->th_ack), th->th_flags, ntohs(th->th_win) << 8, ntohs(th->th_win), payload_length); | 465 | dev->id, ntohs(th->th_sport), ntohs(th->th_dport), ntohl(th->th_seq), ntohl(th->th_ack), th->th_flags, ntohs(th->th_win) << 8, ntohs(th->th_win), payload_length); |
| @@ -531,7 +531,7 @@ static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned | |||
| 531 | } | 531 | } |
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | void device_data_input(struct usb_device *usbdev, unsigned char *buffer, int length) | 534 | void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length) |
| 535 | { | 535 | { |
| 536 | struct mux_device *dev = NULL; | 536 | struct mux_device *dev = NULL; |
| 537 | FOREACH(struct mux_device *tdev, &device_list) { | 537 | FOREACH(struct mux_device *tdev, &device_list) { |
| @@ -548,11 +548,17 @@ void device_data_input(struct usb_device *usbdev, unsigned char *buffer, int len | |||
| 548 | if(!length) | 548 | if(!length) |
| 549 | return; | 549 | return; |
| 550 | 550 | ||
| 551 | // sanity check (should never happen with current USB implementation) | ||
| 552 | if((length > USB_MRU) || (length > DEV_MRU)) { | ||
| 553 | usbmuxd_log(LL_ERROR, "Too much data received from USB (%d), file a bug", length); | ||
| 554 | return; | ||
| 555 | } | ||
| 556 | |||
| 551 | usbmuxd_log(LL_SPEW, "Mux data input for device %p: %p len %d", dev, buffer, length); | 557 | usbmuxd_log(LL_SPEW, "Mux data input for device %p: %p len %d", dev, buffer, length); |
| 552 | 558 | ||
| 553 | // handle broken up transfers | 559 | // handle broken up transfers |
| 554 | if(dev->pktlen) { | 560 | if(dev->pktlen) { |
| 555 | if((length + dev->pktlen) > DEV_PKTBUF_SIZE) { | 561 | if((length + dev->pktlen) > DEV_MRU) { |
| 556 | usbmuxd_log(LL_ERROR, "Incoming split packet is too large (%d so far), dropping!", length + dev->pktlen); | 562 | usbmuxd_log(LL_ERROR, "Incoming split packet is too large (%d so far), dropping!", length + dev->pktlen); |
| 557 | dev->pktlen = 0; | 563 | dev->pktlen = 0; |
| 558 | return; | 564 | return; |
| @@ -588,13 +594,21 @@ void device_data_input(struct usb_device *usbdev, unsigned char *buffer, int len | |||
| 588 | 594 | ||
| 589 | struct tcphdr *th; | 595 | struct tcphdr *th; |
| 590 | unsigned char *payload; | 596 | unsigned char *payload; |
| 591 | int payload_length; | 597 | uint32_t payload_length; |
| 592 | 598 | ||
| 593 | switch(ntohl(mhdr->protocol)) { | 599 | switch(ntohl(mhdr->protocol)) { |
| 594 | case MUX_PROTO_VERSION: | 600 | case MUX_PROTO_VERSION: |
| 601 | if(length < (sizeof(struct mux_header) + sizeof(struct version_header))) { | ||
| 602 | usbmuxd_log(LL_ERROR, "Incoming version packet is too small (%d)", length); | ||
| 603 | return; | ||
| 604 | } | ||
| 595 | device_version_input(dev, (struct version_header *)(mhdr+1)); | 605 | device_version_input(dev, (struct version_header *)(mhdr+1)); |
| 596 | break; | 606 | break; |
| 597 | case MUX_PROTO_TCP: | 607 | case MUX_PROTO_TCP: |
| 608 | if(length < (sizeof(struct mux_header) + sizeof(struct tcphdr))) { | ||
| 609 | usbmuxd_log(LL_ERROR, "Incoming TCP packet is too small (%d)", length); | ||
| 610 | return; | ||
| 611 | } | ||
| 598 | th = (struct tcphdr *)(mhdr+1); | 612 | th = (struct tcphdr *)(mhdr+1); |
| 599 | payload = (unsigned char *)(th+1); | 613 | payload = (unsigned char *)(th+1); |
| 600 | payload_length = length - sizeof(struct tcphdr) - sizeof(struct mux_header); | 614 | payload_length = length - sizeof(struct tcphdr) - sizeof(struct mux_header); |
| @@ -618,7 +632,7 @@ int device_add(struct usb_device *usbdev) | |||
| 618 | dev->usbdev = usbdev; | 632 | dev->usbdev = usbdev; |
| 619 | dev->state = MUXDEV_INIT; | 633 | dev->state = MUXDEV_INIT; |
| 620 | dev->next_sport = 1; | 634 | dev->next_sport = 1; |
| 621 | dev->pktbuf = malloc(DEV_PKTBUF_SIZE); | 635 | dev->pktbuf = malloc(DEV_MRU); |
| 622 | dev->pktlen = 0; | 636 | dev->pktlen = 0; |
| 623 | struct version_header vh; | 637 | struct version_header vh; |
| 624 | vh.major = htonl(1); | 638 | vh.major = htonl(1); |
diff --git a/daemon/device.h b/daemon/device.h index 4bf9752..ea77069 100644 --- a/daemon/device.h +++ b/daemon/device.h | |||
| @@ -31,7 +31,7 @@ struct device_info { | |||
| 31 | uint16_t pid; | 31 | uint16_t pid; |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | void device_data_input(struct usb_device *dev, unsigned char *buf, int length); | 34 | void device_data_input(struct usb_device *dev, unsigned char *buf, uint32_t length); |
| 35 | 35 | ||
| 36 | int device_add(struct usb_device *dev); | 36 | int device_add(struct usb_device *dev); |
| 37 | void device_remove(struct usb_device *dev); | 37 | void device_remove(struct usb_device *dev); |
