diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-05-19 02:28:32 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-06-09 13:42:18 -0400 |
commit | a10c0ce76098857b899505d05de9f2e13ddf7a7a (patch) | |
tree | 130592c6baaff2e38dd813448337dded1ee1645b /drivers/firewire/core-transaction.c | |
parent | 262444eecce40950af19ea4d75a3dc03b3c07283 (diff) |
firewire: check cdev response length
Add a check that the data length in the SEND_RESPONSE ioctl is correct.
Incidentally, this also fixes the previously wrong response length of
software-handled lock requests.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/core-transaction.c')
-rw-r--r-- | drivers/firewire/core-transaction.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index fdc33ff06dc1..4fd5c3b2128e 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c | |||
@@ -580,6 +580,41 @@ static void free_response_callback(struct fw_packet *packet, | |||
580 | kfree(request); | 580 | kfree(request); |
581 | } | 581 | } |
582 | 582 | ||
583 | int fw_get_response_length(struct fw_request *r) | ||
584 | { | ||
585 | int tcode, ext_tcode, data_length; | ||
586 | |||
587 | tcode = HEADER_GET_TCODE(r->request_header[0]); | ||
588 | |||
589 | switch (tcode) { | ||
590 | case TCODE_WRITE_QUADLET_REQUEST: | ||
591 | case TCODE_WRITE_BLOCK_REQUEST: | ||
592 | return 0; | ||
593 | |||
594 | case TCODE_READ_QUADLET_REQUEST: | ||
595 | return 4; | ||
596 | |||
597 | case TCODE_READ_BLOCK_REQUEST: | ||
598 | data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]); | ||
599 | return data_length; | ||
600 | |||
601 | case TCODE_LOCK_REQUEST: | ||
602 | ext_tcode = HEADER_GET_EXTENDED_TCODE(r->request_header[3]); | ||
603 | data_length = HEADER_GET_DATA_LENGTH(r->request_header[3]); | ||
604 | switch (ext_tcode) { | ||
605 | case EXTCODE_FETCH_ADD: | ||
606 | case EXTCODE_LITTLE_ADD: | ||
607 | return data_length; | ||
608 | default: | ||
609 | return data_length / 2; | ||
610 | } | ||
611 | |||
612 | default: | ||
613 | WARN(1, KERN_ERR "wrong tcode %d", tcode); | ||
614 | return 0; | ||
615 | } | ||
616 | } | ||
617 | |||
583 | void fw_fill_response(struct fw_packet *response, u32 *request_header, | 618 | void fw_fill_response(struct fw_packet *response, u32 *request_header, |
584 | int rcode, void *payload, size_t length) | 619 | int rcode, void *payload, size_t length) |
585 | { | 620 | { |
@@ -713,7 +748,8 @@ void fw_send_response(struct fw_card *card, | |||
713 | 748 | ||
714 | if (rcode == RCODE_COMPLETE) | 749 | if (rcode == RCODE_COMPLETE) |
715 | fw_fill_response(&request->response, request->request_header, | 750 | fw_fill_response(&request->response, request->request_header, |
716 | rcode, request->data, request->length); | 751 | rcode, request->data, |
752 | fw_get_response_length(request)); | ||
717 | else | 753 | else |
718 | fw_fill_response(&request->response, request->request_header, | 754 | fw_fill_response(&request->response, request->request_header, |
719 | rcode, NULL, 0); | 755 | rcode, NULL, 0); |