summaryrefslogtreecommitdiff
path: root/chromium/services/device/usb
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/services/device/usb')
-rw-r--r--chromium/services/device/usb/mojo/device_manager_impl.cc5
-rw-r--r--chromium/services/device/usb/mojo/device_manager_impl.h1
-rw-r--r--chromium/services/device/usb/usb_device_handle_usbfs.cc41
-rw-r--r--chromium/services/device/usb/usb_device_handle_usbfs.h4
-rw-r--r--chromium/services/device/usb/usb_device_handle_win.cc24
-rw-r--r--chromium/services/device/usb/usb_service.h2
-rw-r--r--chromium/services/device/usb/usb_service_linux.cc12
-rw-r--r--chromium/services/device/usb/usb_service_win.cc49
8 files changed, 104 insertions, 34 deletions
diff --git a/chromium/services/device/usb/mojo/device_manager_impl.cc b/chromium/services/device/usb/mojo/device_manager_impl.cc
index 2c7b79af77c..8c3aa4ee25b 100644
--- a/chromium/services/device/usb/mojo/device_manager_impl.cc
+++ b/chromium/services/device/usb/mojo/device_manager_impl.cc
@@ -123,6 +123,7 @@ void DeviceManagerImpl::CheckAccess(const std::string& guid,
void DeviceManagerImpl::OpenFileDescriptor(
const std::string& guid,
+ uint32_t drop_privileges_mask,
OpenFileDescriptorCallback callback) {
scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid);
if (!device) {
@@ -133,8 +134,8 @@ void DeviceManagerImpl::OpenFileDescriptor(
base::AdaptCallbackForRepeating(std::move(callback));
auto devpath =
static_cast<device::UsbDeviceLinux*>(device.get())->device_path();
- chromeos::PermissionBrokerClient::Get()->OpenPath(
- devpath,
+ chromeos::PermissionBrokerClient::Get()->OpenPathWithDroppedPrivileges(
+ devpath, drop_privileges_mask,
base::BindOnce(&DeviceManagerImpl::OnOpenFileDescriptor,
weak_factory_.GetWeakPtr(), copyable_callback),
base::BindOnce(&DeviceManagerImpl::OnOpenFileDescriptorError,
diff --git a/chromium/services/device/usb/mojo/device_manager_impl.h b/chromium/services/device/usb/mojo/device_manager_impl.h
index 5684eab03cf..a048b379dff 100644
--- a/chromium/services/device/usb/mojo/device_manager_impl.h
+++ b/chromium/services/device/usb/mojo/device_manager_impl.h
@@ -70,6 +70,7 @@ class DeviceManagerImpl : public mojom::UsbDeviceManager,
CheckAccessCallback callback) override;
void OpenFileDescriptor(const std::string& guid,
+ uint32_t drop_privileges_mask,
OpenFileDescriptorCallback callback) override;
void OnOpenFileDescriptor(OpenFileDescriptorCallback callback,
diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.cc b/chromium/services/device/usb/usb_device_handle_usbfs.cc
index 90e2be66708..68eb5658725 100644
--- a/chromium/services/device/usb/usb_device_handle_usbfs.cc
+++ b/chromium/services/device/usb/usb_device_handle_usbfs.cc
@@ -17,6 +17,7 @@
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/numerics/checked_math.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sequence_checker.h"
#include "base/stl_util.h"
@@ -169,7 +170,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper {
DISALLOW_COPY_AND_ASSIGN(BlockingTaskRunnerHelper);
};
-struct UsbDeviceHandleUsbfs::Transfer {
+struct UsbDeviceHandleUsbfs::Transfer final {
Transfer() = delete;
Transfer(scoped_refptr<base::RefCountedBytes> buffer,
TransferCallback callback);
@@ -291,8 +292,12 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetInterface(
USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
<< " to alternate setting " << alternate_setting;
}
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(std::move(callback), rc == 0));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete,
+ device_handle_, interface_number, alternate_setting, rc == 0,
+ std::move(callback)));
}
void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ResetDevice(
@@ -386,9 +391,9 @@ UsbDeviceHandleUsbfs::Transfer::Transfer(
scoped_refptr<base::RefCountedBytes> buffer,
IsochronousTransferCallback callback)
: buffer(buffer), isoc_callback(std::move(callback)) {
- memset(
- &urb, 0,
- sizeof(urb) + sizeof(usbdevfs_iso_packet_desc) * urb.number_of_packets);
+ // This buffer size calculation is checked in operator new().
+ memset(&urb, 0,
+ sizeof(urb) + sizeof(urb.iso_frame_desc[0]) * urb.number_of_packets);
urb.usercontext = this;
urb.buffer = buffer->front();
}
@@ -396,10 +401,15 @@ UsbDeviceHandleUsbfs::Transfer::Transfer(
UsbDeviceHandleUsbfs::Transfer::~Transfer() = default;
void* UsbDeviceHandleUsbfs::Transfer::operator new(
- std::size_t size,
+ size_t size,
size_t number_of_iso_packets) {
- void* p = ::operator new(size + sizeof(usbdevfs_iso_packet_desc) *
- number_of_iso_packets);
+ // The checked math should pass as long as Mojo message size limits are being
+ // enforced.
+ size_t total_size =
+ base::CheckAdd(size, base::CheckMul(sizeof(urb.iso_frame_desc[0]),
+ number_of_iso_packets))
+ .ValueOrDie();
+ void* p = ::operator new(total_size);
Transfer* transfer = static_cast<Transfer*>(p);
transfer->urb.number_of_packets = number_of_iso_packets;
return p;
@@ -763,6 +773,19 @@ void UsbDeviceHandleUsbfs::SetConfigurationComplete(int configuration_value,
std::move(callback).Run(success);
}
+void UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete(
+ int interface_number,
+ int alternate_setting,
+ bool success,
+ ResultCallback callback) {
+ DCHECK(sequence_checker_.CalledOnValidSequence());
+ if (success && device_) {
+ interfaces_[interface_number].alternate_setting = alternate_setting;
+ RefreshEndpointInfo();
+ }
+ std::move(callback).Run(success);
+}
+
void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(int interface_number,
ResultCallback callback) {
DCHECK(sequence_checker_.CalledOnValidSequence());
diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.h b/chromium/services/device/usb/usb_device_handle_usbfs.h
index 33a09d00542..949ddd05327 100644
--- a/chromium/services/device/usb/usb_device_handle_usbfs.h
+++ b/chromium/services/device/usb/usb_device_handle_usbfs.h
@@ -103,6 +103,10 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle {
void SetConfigurationComplete(int configuration_value,
bool success,
ResultCallback callback);
+ void SetAlternateInterfaceSettingComplete(int interface_number,
+ int alternate_setting,
+ bool success,
+ ResultCallback callback);
void ReleaseInterfaceComplete(int interface_number, ResultCallback callback);
void IsochronousTransferInternal(uint8_t endpoint_address,
scoped_refptr<base::RefCountedBytes> buffer,
diff --git a/chromium/services/device/usb/usb_device_handle_win.cc b/chromium/services/device/usb/usb_device_handle_win.cc
index 2cac1b0cc6d..e9364245b16 100644
--- a/chromium/services/device/usb/usb_device_handle_win.cc
+++ b/chromium/services/device/usb/usb_device_handle_win.cc
@@ -26,6 +26,7 @@
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/win/object_watcher.h"
@@ -335,8 +336,8 @@ void UsbDeviceHandleWin::SetInterfaceAlternateSetting(int interface_number,
// Use a strong reference to |this| rather than a weak pointer to prevent
// |interface.handle| from being freed because |this| was destroyed.
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&SetCurrentAlternateSettingBlocking,
interface.handle.Get(), alternate_setting),
base::BindOnce(&UsbDeviceHandleWin::OnSetAlternateInterfaceSetting, this,
@@ -388,8 +389,8 @@ void UsbDeviceHandleWin::ClearHalt(mojom::UsbTransferDirection direction,
// Use a strong reference to |this| rather than a weak pointer to prevent
// |interface.handle| from being freed because |this| was destroyed.
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&ResetPipeBlocking, interface.handle.Get(),
endpoint_address),
base::BindOnce(&UsbDeviceHandleWin::OnClearHalt, this,
@@ -1017,13 +1018,22 @@ void UsbDeviceHandleWin::GotDescriptorFromNodeConnection(
if (win32_result != ERROR_SUCCESS) {
SetLastError(win32_result);
USB_PLOG(ERROR) << "Failed to read descriptor from node connection";
- std::move(callback).Run(UsbTransferStatus::TRANSFER_ERROR, nullptr, 0);
+ std::move(callback).Run(UsbTransferStatus::TRANSFER_ERROR,
+ /*buffer=*/nullptr, /*length=*/0);
+ return;
+ }
+
+ if (bytes_transferred < sizeof(USB_DESCRIPTOR_REQUEST)) {
+ USB_LOG(ERROR) << "Descriptor response too short (" << bytes_transferred
+ << " < " << sizeof(USB_DESCRIPTOR_REQUEST) << ")";
+ std::move(callback).Run(UsbTransferStatus::TRANSFER_ERROR,
+ /*buffer=*/nullptr, /*length=*/0);
return;
}
- DCHECK_GE(bytes_transferred, sizeof(USB_DESCRIPTOR_REQUEST));
bytes_transferred -= sizeof(USB_DESCRIPTOR_REQUEST);
- DCHECK_LE(bytes_transferred, original_buffer->size());
+ bytes_transferred = std::min(bytes_transferred, original_buffer->size());
+
memcpy(original_buffer->front(),
request_buffer->front() + sizeof(USB_DESCRIPTOR_REQUEST),
bytes_transferred);
diff --git a/chromium/services/device/usb/usb_service.h b/chromium/services/device/usb/usb_service.h
index 97a44f0ccea..3e9df5c05ab 100644
--- a/chromium/services/device/usb/usb_service.h
+++ b/chromium/services/device/usb/usb_service.h
@@ -12,7 +12,7 @@
#include <vector>
#include "base/bind_helpers.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
diff --git a/chromium/services/device/usb/usb_service_linux.cc b/chromium/services/device/usb/usb_service_linux.cc
index d5cef63fe30..7e7eb833b76 100644
--- a/chromium/services/device/usb/usb_service_linux.cc
+++ b/chromium/services/device/usb/usb_service_linux.cc
@@ -34,6 +34,8 @@ namespace device {
namespace {
+constexpr char kSubsystemUsb[] = "usb";
+
// Standard USB requests and descriptor types:
const uint16_t kUsbVersion2_1 = 0x0210;
@@ -109,7 +111,8 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::Start() {
// Initializing udev for device enumeration and monitoring may fail. In that
// case this service will continue to exist but no devices will be found.
- watcher_ = UdevWatcher::StartWatching(this);
+ watcher_ = UdevWatcher::StartWatching(
+ this, {UdevWatcher::Filter(kSubsystemUsb, "")});
if (watcher_)
watcher_->EnumerateExistingDevices();
@@ -123,9 +126,12 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceAdded(
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
+
+#if DCHECK_IS_ON()
const char* subsystem = udev_device_get_subsystem(device.get());
- if (!subsystem || strcmp(subsystem, "usb") != 0)
- return;
+ DCHECK(subsystem);
+ DCHECK_EQ(base::StringPiece(subsystem), kSubsystemUsb);
+#endif
const char* value = udev_device_get_devnode(device.get());
if (!value)
diff --git a/chromium/services/device/usb/usb_service_win.cc b/chromium/services/device/usb/usb_service_win.cc
index 6acaf445f91..4e8989f6d3d 100644
--- a/chromium/services/device/usb/usb_service_win.cc
+++ b/chromium/services/device/usb/usb_service_win.cc
@@ -24,8 +24,11 @@
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "base/threading/scoped_thread_priority.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/registry.h"
+#include "base/win/scoped_devinfo.h"
#include "base/win/scoped_handle.h"
#include "components/device_event_log/device_event_log.h"
#include "services/device/usb/usb_descriptors.h"
@@ -37,16 +40,13 @@ namespace device {
namespace {
-struct DevInfoScopedTraits {
- static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
- static void Free(HDEVINFO h) { SetupDiDestroyDeviceInfoList(h); }
-};
-
-using ScopedDevInfo = base::ScopedGeneric<HDEVINFO, DevInfoScopedTraits>;
-
base::Optional<uint32_t> GetDeviceUint32Property(HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
+ // SetupDiGetDeviceProperty() makes an RPC which may block.
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
+
DEVPROPTYPE property_type;
uint32_t buffer;
if (!SetupDiGetDeviceProperty(
@@ -63,6 +63,10 @@ base::Optional<base::string16> GetDeviceStringProperty(
HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
+ // SetupDiGetDeviceProperty() makes an RPC which may block.
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
+
DEVPROPTYPE property_type;
DWORD required_size;
if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
@@ -87,6 +91,10 @@ base::Optional<std::vector<base::string16>> GetDeviceStringListProperty(
HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
+ // SetupDiGetDeviceProperty() makes an RPC which may block.
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
+
DEVPROPTYPE property_type;
DWORD required_size;
if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
@@ -236,7 +244,7 @@ bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
base::string16 GetDevicePath(const base::string16& instance_id,
const GUID& device_interface_guid) {
- ScopedDevInfo dev_info(
+ base::win::ScopedDevInfo dev_info(
SetupDiGetClassDevs(&device_interface_guid, instance_id.c_str(), 0,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid()) {
@@ -287,7 +295,8 @@ int GetInterfaceNumber(const base::string16& instance_id) {
UsbDeviceWin::FunctionInfo GetFunctionInfo(const base::string16& instance_id) {
UsbDeviceWin::FunctionInfo info;
- ScopedDevInfo dev_info(SetupDiCreateDeviceInfoList(nullptr, nullptr));
+ base::win::ScopedDevInfo dev_info(
+ SetupDiCreateDeviceInfoList(nullptr, nullptr));
if (!dev_info.is_valid()) {
USB_PLOG(ERROR) << "SetupDiCreateDeviceInfoList";
return info;
@@ -310,6 +319,10 @@ UsbDeviceWin::FunctionInfo GetFunctionInfo(const base::string16& instance_id) {
if (!base::EqualsCaseInsensitiveASCII(info.driver, L"winusb"))
return info;
+ // Boost priority while potentially loading Advapi32.dll on a background
+ // thread for the registry functions used below.
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
// There is no standard device interface GUID for USB functions and so we
// must discover the set of GUIDs that have been set in the registry by
// the INF file or Microsoft OS Compatibility descriptors before
@@ -332,6 +345,10 @@ UsbDeviceWin::FunctionInfo GetFunctionInfo(const base::string16& instance_id) {
}
for (const auto& guid_string : device_interface_guids) {
+ // Boost priority while potentially loading Ole32.dll on a background
+ // thread for CLSIDFromString().
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
GUID guid;
if (FAILED(CLSIDFromString(guid_string.c_str(), &guid))) {
USB_LOG(ERROR) << "Failed to parse device interface GUID: "
@@ -357,7 +374,11 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
~BlockingTaskRunnerHelper() {}
void EnumerateDevices() {
- ScopedDevInfo dev_info(
+ // Boost priority while potentially loading SetupAPI.dll for the following
+ // functions on a background thread.
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
+ base::win::ScopedDevInfo dev_info(
SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, 0,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid()) {
@@ -384,7 +405,11 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
}
void OnDeviceAdded(const GUID& guid, const base::string16& device_path) {
- ScopedDevInfo dev_info(SetupDiGetClassDevs(
+ // Boost priority while potentially loading SetupAPI.dll and Ole32.dll on a
+ // background thread for the following functions.
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
+ base::win::ScopedDevInfo dev_info(SetupDiGetClassDevs(
&guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid()) {
USB_PLOG(ERROR) << "Failed to set up device enumeration";
@@ -407,6 +432,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
}
}
+ private:
void EnumerateDevice(HDEVINFO dev_info,
SP_DEVICE_INTERFACE_DATA* device_interface_data,
const base::Optional<base::string16>& opt_device_path) {
@@ -499,7 +525,6 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
std::move(parent_path), interface_number, info));
}
- private:
std::unordered_map<base::string16, base::string16> hub_paths_;
// Calls back to |service_| must be posted to |service_task_runner_|, which