libusb: guard USB session packet allocator

Fixes #4389
This commit is contained in:
Christian Prochaska
2022-01-24 12:03:34 +01:00
committed by Norman Feske
parent e98760a3d5
commit 2591c61e7d

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2016-2017 Genode Labs GmbH * Copyright (C) 2016-2022 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -85,6 +85,17 @@ static Genode::Entrypoint &ep()
static Libc::Allocator libc_alloc { }; static Libc::Allocator libc_alloc { };
/*
* Prevent modification of packet allocator
* by multiple threads.
*/
static Genode::Mutex &usb_packet_allocator_mutex()
{
static Genode::Mutex instance;
return instance;
}
struct Completion : Usb::Completion struct Completion : Usb::Completion
{ {
struct usbi_transfer *itransfer; struct usbi_transfer *itransfer;
@ -128,6 +139,7 @@ struct Usb_device
usb_connection.source()->get_acked_packet(); usb_connection.source()->get_acked_packet();
if (p.type == Usb::Packet_descriptor::ALT_SETTING) { if (p.type == Usb::Packet_descriptor::ALT_SETTING) {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
usb_connection.source()->release_packet(p); usb_connection.source()->release_packet(p);
continue; continue;
} }
@ -141,6 +153,7 @@ struct Usb_device
destroy(libc_alloc, completion); destroy(libc_alloc, completion);
if (_open == 0) { if (_open == 0) {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
usb_connection.source()->release_packet(p); usb_connection.source()->release_packet(p);
continue; continue;
} }
@ -149,7 +162,10 @@ struct Usb_device
if (!p.succeded) if (!p.succeded)
Genode::error("USB transfer failed: ", (unsigned)p.type); Genode::error("USB transfer failed: ", (unsigned)p.type);
itransfer->transferred = 0; itransfer->transferred = 0;
usb_connection.source()->release_packet(p); {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
usb_connection.source()->release_packet(p);
}
usbi_signal_transfer_completion(itransfer); usbi_signal_transfer_completion(itransfer);
continue; continue;
} }
@ -223,11 +239,15 @@ struct Usb_device
default: default:
Genode::error(__PRETTY_FUNCTION__, Genode::error(__PRETTY_FUNCTION__,
": unsupported transfer type"); ": unsupported transfer type");
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
usb_connection.source()->release_packet(p); usb_connection.source()->release_packet(p);
continue; continue;
} }
usb_connection.source()->release_packet(p); {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
usb_connection.source()->release_packet(p);
}
usbi_signal_transfer_completion(itransfer); usbi_signal_transfer_completion(itransfer);
} }
@ -296,6 +316,8 @@ struct Usb_device
bool altsetting(int number, int alt_setting) bool altsetting(int number, int alt_setting)
{ {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
Usb::Packet_descriptor p = Usb::Packet_descriptor p =
usb_connection.source()->alloc_packet(0); usb_connection.source()->alloc_packet(0);
@ -549,6 +571,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
Usb::Packet_descriptor p; Usb::Packet_descriptor p;
try { try {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
p = usb_device->usb_connection.source()->alloc_packet(setup->wLength); p = usb_device->usb_connection.source()->alloc_packet(setup->wLength);
} catch (Usb::Session::Tx::Source::Packet_alloc_failed) { } catch (Usb::Session::Tx::Source::Packet_alloc_failed) {
return LIBUSB_ERROR_BUSY; return LIBUSB_ERROR_BUSY;
@ -593,6 +616,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
Usb::Packet_descriptor p; Usb::Packet_descriptor p;
try { try {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
p = usb_device->usb_connection.source()->alloc_packet(transfer->length); p = usb_device->usb_connection.source()->alloc_packet(transfer->length);
} catch (Usb::Session::Tx::Source::Packet_alloc_failed) { } catch (Usb::Session::Tx::Source::Packet_alloc_failed) {
return LIBUSB_ERROR_BUSY; return LIBUSB_ERROR_BUSY;
@ -629,6 +653,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
Usb::Packet_descriptor p; Usb::Packet_descriptor p;
try { try {
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
p = usb_device->usb_connection.source()->alloc_packet(total_length); p = usb_device->usb_connection.source()->alloc_packet(total_length);
} catch (Usb::Session::Tx::Source::Packet_alloc_failed) { } catch (Usb::Session::Tx::Source::Packet_alloc_failed) {
return LIBUSB_ERROR_BUSY; return LIBUSB_ERROR_BUSY;
@ -777,4 +802,3 @@ void __attribute__((constructor)) init_libc_libusb(void)
{ {
static Plugin plugin; static Plugin plugin;
} }