Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: chrome/browser/extensions/api/usb/usb_api.cc

Issue 11926005: Fix transfer length validation in Usb Api. (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/extensions/api/usb/usb_apitest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/usb/usb_api.h" 5 #include "chrome/browser/extensions/api/usb/usb_api.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 static const char* kErrorCannotReleaseInterface = "Error releasing interface."; 55 static const char* kErrorCannotReleaseInterface = "Error releasing interface.";
56 static const char* kErrorCannotSetInterfaceAlternateSetting = 56 static const char* kErrorCannotSetInterfaceAlternateSetting =
57 "Error setting alternate interface setting."; 57 "Error setting alternate interface setting.";
58 static const char* kErrorConvertDirection = "Invalid transfer direction."; 58 static const char* kErrorConvertDirection = "Invalid transfer direction.";
59 static const char* kErrorConvertRecipient = "Invalid transfer recipient."; 59 static const char* kErrorConvertRecipient = "Invalid transfer recipient.";
60 static const char* kErrorConvertRequestType = "Invalid request type."; 60 static const char* kErrorConvertRequestType = "Invalid request type.";
61 static const char* kErrorMalformedParameters = "Error parsing parameters."; 61 static const char* kErrorMalformedParameters = "Error parsing parameters.";
62 static const char* kErrorNoDevice = "No such device."; 62 static const char* kErrorNoDevice = "No such device.";
63 static const char* kErrorPermissionDenied = 63 static const char* kErrorPermissionDenied =
64 "Permission to access device was denied"; 64 "Permission to access device was denied";
65 static const char* kErrorInvalidTransferLength = "Transfer length must be a "
66 "positive number less than 104,857,600.";
65 67
68 static const size_t kMaxTransferLength = 100 * 1024 * 1024;
66 static UsbDevice* device_for_test_ = NULL; 69 static UsbDevice* device_for_test_ = NULL;
67 70
68 static bool ConvertDirection(const Direction& input, 71 static bool ConvertDirection(const Direction& input,
69 UsbDevice::TransferDirection* output) { 72 UsbDevice::TransferDirection* output) {
70 switch (input) { 73 switch (input) {
71 case usb::DIRECTION_IN: 74 case usb::DIRECTION_IN:
72 *output = UsbDevice::INBOUND; 75 *output = UsbDevice::INBOUND;
73 return true; 76 return true;
74 case usb::DIRECTION_OUT: 77 case usb::DIRECTION_OUT:
75 *output = UsbDevice::OUTBOUND; 78 *output = UsbDevice::OUTBOUND;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 return false; 125 return false;
123 } 126 }
124 NOTREACHED(); 127 NOTREACHED();
125 return false; 128 return false;
126 } 129 }
127 130
128 template<class T> 131 template<class T>
129 static bool GetTransferSize(const T& input, size_t* output) { 132 static bool GetTransferSize(const T& input, size_t* output) {
130 if (input.direction == usb::DIRECTION_IN) { 133 if (input.direction == usb::DIRECTION_IN) {
131 const int* length = input.length.get(); 134 const int* length = input.length.get();
132 if (length) { 135 if (length && *length >= 0 &&
136 static_cast<size_t>(*length) < kMaxTransferLength) {
133 *output = *length; 137 *output = *length;
134 return true; 138 return true;
135 } 139 }
136 } else if (input.direction == usb::DIRECTION_OUT) { 140 } else if (input.direction == usb::DIRECTION_OUT) {
137 if (input.data.get()) { 141 if (input.data.get()) {
138 *output = input.data->size(); 142 *output = input.data->size();
139 return true; 143 return true;
140 } 144 }
141 } 145 }
142 return false; 146 return false;
143 } 147 }
144 148
145 template<class T> 149 template<class T>
146 static scoped_refptr<net::IOBuffer> CreateBufferForTransfer(const T& input) { 150 static scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
147 size_t size = 0; 151 const T& input, UsbDevice::TransferDirection direction, size_t size) {
148 if (!GetTransferSize(input, &size)) 152
153 if (size > kMaxTransferLength)
149 return NULL; 154 return NULL;
150 155
151 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This 156 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
152 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer 157 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
153 // cannot represent a zero-length buffer, while an URB can. 158 // cannot represent a zero-length buffer, while an URB can.
154 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max( 159 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max(
155 static_cast<size_t>(1), size)); 160 static_cast<size_t>(1), size));
156 if (!input.data.get()) 161
162 if (direction == UsbDevice::INBOUND) {
157 return buffer; 163 return buffer;
158 164 } else if (direction == UsbDevice::OUTBOUND) {
159 memcpy(buffer->data(), input.data->data(), size); 165 if (input.data.get() && size <= input.data->size()) {
160 return buffer; 166 memcpy(buffer->data(), input.data->data(), size);
167 return buffer;
168 }
169 }
170 NOTREACHED();
171 return NULL;
161 } 172 }
162 173
163 static const char* ConvertTransferStatusToErrorString( 174 static const char* ConvertTransferStatusToErrorString(
164 const UsbTransferStatus status) { 175 const UsbTransferStatus status) {
165 switch (status) { 176 switch (status) {
166 case USB_TRANSFER_COMPLETED: 177 case USB_TRANSFER_COMPLETED:
167 return ""; 178 return "";
168 case USB_TRANSFER_ERROR: 179 case USB_TRANSFER_ERROR:
169 return kErrorGeneric; 180 return kErrorGeneric;
170 case USB_TRANSFER_TIMEOUT: 181 case USB_TRANSFER_TIMEOUT:
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 if (!device) { 479 if (!device) {
469 CompleteWithError(kErrorNoDevice); 480 CompleteWithError(kErrorNoDevice);
470 return; 481 return;
471 } 482 }
472 483
473 const ControlTransferInfo& transfer = parameters_->transfer_info; 484 const ControlTransferInfo& transfer = parameters_->transfer_info;
474 485
475 UsbDevice::TransferDirection direction; 486 UsbDevice::TransferDirection direction;
476 UsbDevice::TransferRequestType request_type; 487 UsbDevice::TransferRequestType request_type;
477 UsbDevice::TransferRecipient recipient; 488 UsbDevice::TransferRecipient recipient;
478 size_t size; 489 size_t size = 0;
479 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer);
480 490
481 if (!ConvertDirectionSafely(transfer.direction, &direction) || 491 if (!ConvertDirectionSafely(transfer.direction, &direction) ||
482 !ConvertRequestTypeSafely(transfer.request_type, &request_type) || 492 !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
483 !ConvertRecipientSafely(transfer.recipient, &recipient)) { 493 !ConvertRecipientSafely(transfer.recipient, &recipient)) {
484 AsyncWorkCompleted(); 494 AsyncWorkCompleted();
485 return; 495 return;
486 } 496 }
487 497
488 if (!GetTransferSize(transfer, &size) || !buffer) { 498 if (!GetTransferSize(transfer, &size)) {
499 CompleteWithError(kErrorInvalidTransferLength);
500 return;
501 }
502
503 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
504 transfer, direction, size);
505 if (!buffer) {
489 CompleteWithError(kErrorMalformedParameters); 506 CompleteWithError(kErrorMalformedParameters);
490 return; 507 return;
491 } 508 }
492 509
493 device->device()->ControlTransfer(direction, request_type, recipient, 510 device->device()->ControlTransfer(direction, request_type, recipient,
494 transfer.request, transfer.value, transfer.index, buffer, size, 0, 511 transfer.request, transfer.value, transfer.index, buffer, size, 0,
495 base::Bind(&UsbControlTransferFunction::OnCompleted, this)); 512 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
496 } 513 }
497 514
498 UsbBulkTransferFunction::UsbBulkTransferFunction() {} 515 UsbBulkTransferFunction::UsbBulkTransferFunction() {}
(...skipping 10 matching lines...) Expand all
509 UsbDeviceResource* const device = GetUsbDeviceResource( 526 UsbDeviceResource* const device = GetUsbDeviceResource(
510 parameters_->device.handle); 527 parameters_->device.handle);
511 if (!device) { 528 if (!device) {
512 CompleteWithError(kErrorNoDevice); 529 CompleteWithError(kErrorNoDevice);
513 return; 530 return;
514 } 531 }
515 532
516 const GenericTransferInfo& transfer = parameters_->transfer_info; 533 const GenericTransferInfo& transfer = parameters_->transfer_info;
517 534
518 UsbDevice::TransferDirection direction; 535 UsbDevice::TransferDirection direction;
519 size_t size; 536 size_t size = 0;
520 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer);
521 537
522 if (!ConvertDirectionSafely(transfer.direction, &direction)) { 538 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
523 AsyncWorkCompleted(); 539 AsyncWorkCompleted();
524 return; 540 return;
525 } 541 }
526 542
527 if (!GetTransferSize(transfer, &size) || !buffer) { 543 if (!GetTransferSize(transfer, &size)) {
544 CompleteWithError(kErrorInvalidTransferLength);
545 return;
546 }
547
548 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
549 transfer, direction, size);
550 if (!buffer) {
528 CompleteWithError(kErrorMalformedParameters); 551 CompleteWithError(kErrorMalformedParameters);
529 return; 552 return;
530 } 553 }
531 554
532 device->device()->BulkTransfer(direction, transfer.endpoint, buffer, size, 0, 555 device->device()->BulkTransfer(direction, transfer.endpoint, buffer, size, 0,
533 base::Bind(&UsbBulkTransferFunction::OnCompleted, this)); 556 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
534 } 557 }
535 558
536 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {} 559 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {}
537 560
538 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {} 561 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {}
539 562
540 bool UsbInterruptTransferFunction::Prepare() { 563 bool UsbInterruptTransferFunction::Prepare() {
541 parameters_ = InterruptTransfer::Params::Create(*args_); 564 parameters_ = InterruptTransfer::Params::Create(*args_);
542 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 565 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
543 return true; 566 return true;
544 } 567 }
545 568
546 void UsbInterruptTransferFunction::AsyncWorkStart() { 569 void UsbInterruptTransferFunction::AsyncWorkStart() {
547 UsbDeviceResource* const device = GetUsbDeviceResource( 570 UsbDeviceResource* const device = GetUsbDeviceResource(
548 parameters_->device.handle); 571 parameters_->device.handle);
549 if (!device) { 572 if (!device) {
550 CompleteWithError(kErrorNoDevice); 573 CompleteWithError(kErrorNoDevice);
551 return; 574 return;
552 } 575 }
553 576
554 const GenericTransferInfo& transfer = parameters_->transfer_info; 577 const GenericTransferInfo& transfer = parameters_->transfer_info;
555 578
556 UsbDevice::TransferDirection direction; 579 UsbDevice::TransferDirection direction;
557 size_t size; 580 size_t size = 0;
558 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer);
559 581
560 if (!ConvertDirectionSafely(transfer.direction, &direction)) { 582 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
561 AsyncWorkCompleted(); 583 AsyncWorkCompleted();
562 return; 584 return;
563 } 585 }
564 586
565 if (!GetTransferSize(transfer, &size) || !buffer) { 587 if (!GetTransferSize(transfer, &size)) {
588 CompleteWithError(kErrorInvalidTransferLength);
589 return;
590 }
591
592 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
593 transfer, direction, size);
594 if (!buffer) {
566 CompleteWithError(kErrorMalformedParameters); 595 CompleteWithError(kErrorMalformedParameters);
567 return; 596 return;
568 } 597 }
569 598
570 device->device()->InterruptTransfer(direction, transfer.endpoint, buffer, 599 device->device()->InterruptTransfer(direction, transfer.endpoint, buffer,
571 size, 0, base::Bind(&UsbInterruptTransferFunction::OnCompleted, this)); 600 size, 0, base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
572 } 601 }
573 602
574 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {} 603 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {}
575 604
576 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {} 605 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {}
577 606
578 bool UsbIsochronousTransferFunction::Prepare() { 607 bool UsbIsochronousTransferFunction::Prepare() {
579 parameters_ = IsochronousTransfer::Params::Create(*args_); 608 parameters_ = IsochronousTransfer::Params::Create(*args_);
580 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 609 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
581 return true; 610 return true;
582 } 611 }
583 612
584 void UsbIsochronousTransferFunction::AsyncWorkStart() { 613 void UsbIsochronousTransferFunction::AsyncWorkStart() {
585 UsbDeviceResource* const device = GetUsbDeviceResource( 614 UsbDeviceResource* const device = GetUsbDeviceResource(
586 parameters_->device.handle); 615 parameters_->device.handle);
587 if (!device) { 616 if (!device) {
588 CompleteWithError(kErrorNoDevice); 617 CompleteWithError(kErrorNoDevice);
589 return; 618 return;
590 } 619 }
591 620
592 const IsochronousTransferInfo& transfer = parameters_->transfer_info; 621 const IsochronousTransferInfo& transfer = parameters_->transfer_info;
593 const GenericTransferInfo& generic_transfer = transfer.transfer_info; 622 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
594 623
595 size_t size; 624 size_t size = 0;
596 UsbDevice::TransferDirection direction; 625 UsbDevice::TransferDirection direction;
597 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
598 generic_transfer);
599 626
600 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { 627 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
601 AsyncWorkCompleted(); 628 AsyncWorkCompleted();
602 return; 629 return;
603 } 630 }
604 631
605 if (!GetTransferSize(generic_transfer, &size) || !buffer) { 632 if (!GetTransferSize(generic_transfer, &size)) {
606 CompleteWithError(kErrorNoDevice); 633 CompleteWithError(kErrorInvalidTransferLength);
634 return;
635 }
636
637 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
638 generic_transfer, direction, size);
639 if (!buffer) {
640 CompleteWithError(kErrorMalformedParameters);
607 return; 641 return;
608 } 642 }
609 643
610 device->device()->IsochronousTransfer(direction, generic_transfer.endpoint, 644 device->device()->IsochronousTransfer(direction, generic_transfer.endpoint,
611 buffer, size, transfer.packets, transfer.packet_length, 0, base::Bind( 645 buffer, size, transfer.packets, transfer.packet_length, 0, base::Bind(
612 &UsbIsochronousTransferFunction::OnCompleted, this)); 646 &UsbIsochronousTransferFunction::OnCompleted, this));
613 } 647 }
614 648
615 } // namespace extensions 649 } // namespace extensions
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/extensions/api/usb/usb_apitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698