From d18f929fafc499936b74e8f4db957af8369fb7b5 Mon Sep 17 00:00:00 2001 From: brian218 Date: Sat, 16 Dec 2023 21:41:32 +0800 Subject: [PATCH] sys_usbd: Prevent sys_usbd_get_descriptor() from buffer overflow sys_usbd: Add some more arguments to sys_usbd_attach()'s logging for better debugging --- rpcs3/Emu/Cell/lv2/sys_usbd.cpp | 20 +++++++++++--------- rpcs3/Emu/Cell/lv2/sys_usbd.h | 2 +- rpcs3/Emu/Io/usb_device.h | 17 ++++++++++------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index 65e183000b..70fabbd13e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -552,17 +552,15 @@ bool usb_handler_thread::add_ldd(std::string_view product, u16 id_vendor, u16 id { if (!dev->open_device()) { - sys_usbd.error("Failed to open device for LDD(VID:0x%04x PID:0x%04x)", dev->device._device.idVendor, dev->device._device.idProduct); + sys_usbd.error("Failed to open USB device(VID=0x%04x, PID=0x%04x) for LDD <%s>", dev->device._device.idVendor, dev->device._device.idProduct, product); continue; } dev->read_descriptors(); dev->assigned_number = dev_counter++; // assign current dev_counter, and atomically increment - - sys_usbd.notice("Ldd device matchup for <%s>, assigned as handled_device=0x%x", product, dev->assigned_number); - handled_devices.emplace(dev->assigned_number, std::pair(UsbInternalDevice{0x00, narrow(dev->assigned_number), 0x02, 0x40}, dev)); send_message(SYS_USBD_ATTACH, dev->assigned_number); + sys_usbd.success("USB device(VID=0x%04x, PID=0x%04x) matches up with LDD <%s>, assigned as handled_device=0x%x", dev->device._device.idVendor, dev->device._device.idProduct, product, dev->assigned_number); } } @@ -585,8 +583,8 @@ bool usb_handler_thread::remove_ldd(std::string_view product) { if (handled_devices.erase(dev->assigned_number)) { - sys_usbd.notice("Ldd device matchup for <%s>, removed 0x%x from handled_devices", iterator->first, dev->assigned_number); send_message(SYS_USBD_DETACH, dev->assigned_number); + sys_usbd.success("USB device(VID=0x%04x, PID=0x%04x) matches up with LDD <%s>, unassigned handled_device=0x%x", dev->device._device.idVendor, dev->device._device.idProduct, product, dev->assigned_number); dev->assigned_number = 0; } } @@ -861,8 +859,12 @@ error_code sys_usbd_get_descriptor(ppu_thread& ppu, u32 handle, u32 device_handl return CELL_EINVAL; } - u8* ptr = static_cast(descriptor.get_ptr()); - usbh.handled_devices[device_handle].second->device.write_data(ptr); + if (!descriptor) + { + return CELL_EFAULT; + } + + usbh.handled_devices[device_handle].second->device.write_data(reinterpret_cast(descriptor.get_ptr()), desc_size); return CELL_OK; } @@ -1040,11 +1042,11 @@ error_code sys_usbd_detect_event(ppu_thread& ppu) return CELL_OK; } -error_code sys_usbd_attach(ppu_thread& ppu, u32 handle) +error_code sys_usbd_attach(ppu_thread& ppu, u32 handle, u32 unk1, u32 unk2, u32 device_handle) { ppu.state += cpu_flag::wait; - sys_usbd.todo("sys_usbd_attach(handle=0x%x)", handle); + sys_usbd.todo("sys_usbd_attach(handle=0x%x, unk1=0x%x, unk2=0x%x, device_handle=0x%x)", handle, unk1, unk2, device_handle); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.h b/rpcs3/Emu/Cell/lv2/sys_usbd.h index 560e1a984b..622c9e718d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.h +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.h @@ -73,7 +73,7 @@ error_code sys_usbd_open_default_pipe(ppu_thread& ppu, u32 handle, u32 device_ha error_code sys_usbd_close_pipe(ppu_thread& ppu, u32 handle, u32 pipe_handle); error_code sys_usbd_receive_event(ppu_thread& ppu, u32 handle, vm::ptr arg1, vm::ptr arg2, vm::ptr arg3); error_code sys_usbd_detect_event(ppu_thread& ppu); -error_code sys_usbd_attach(ppu_thread& ppu, u32 handle); +error_code sys_usbd_attach(ppu_thread& ppu, u32 handle, u32 unk1, u32 unk2, u32 device_handle); error_code sys_usbd_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm::ptr buf, u32 buf_size, vm::ptr request, u32 type_transfer); error_code sys_usbd_isochronous_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm::ptr iso_request); error_code sys_usbd_get_transfer_status(ppu_thread& ppu, u32 handle, u32 id_transfer, u32 unk1, vm::ptr result, vm::ptr count); diff --git a/rpcs3/Emu/Io/usb_device.h b/rpcs3/Emu/Io/usb_device.h index 67dce955f8..2a09db58da 100644 --- a/rpcs3/Emu/Io/usb_device.h +++ b/rpcs3/Emu/Io/usb_device.h @@ -144,6 +144,7 @@ struct UsbDescriptorNode subnodes.push_back(newnode); return subnodes.back(); } + u32 get_size() const { u32 nodesize = bLength; @@ -153,16 +154,18 @@ struct UsbDescriptorNode } return nodesize; } - void write_data(u8*& ptr) + + u32 write_data(u8* ptr, u32 max_size) const { - ptr[0] = bLength; - ptr[1] = bDescriptorType; - memcpy(ptr + 2, data, bLength - 2); - ptr += bLength; - for (auto& node : subnodes) + u32 size = std::min(bLength, max_size); + memcpy(ptr, this, size); + for (const auto& node : subnodes) { - node.write_data(ptr); + const u32 remaining = max_size - size; + if (remaining == 0) break; + size += node.write_data(ptr + size, remaining); } + return size; } };