Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys_usbd: Prevent sys_usbd_get_descriptor() from buffer overflow & Add some more arguments to sys_usbd_attach()'s logging for better debugging #14900

Merged
merged 2 commits into from Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion BUILDING.md
Expand Up @@ -104,7 +104,7 @@ git submodule update --init

Open `rpcs3.sln`. The recommended build configuration is `Release`. (On older revisions: `Release - LLVM`)

You may want to download the precompiled [LLVM libs](https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win-16.0.1/llvmlibs_mt.7z) and extract them to `3rdparty\llvm\`, as well as download and extract the [additional libs](https://github.com/RPCS3/glslang/releases/download/custom-build-win/glslanglibs_mt.7z) to `lib\%CONFIGURATION%-x64\` to speed up compilation time (unoptimised/debug libs are currently not available precompiled).
You may want to download the precompiled [LLVM libs](https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win-16.0.1/llvmlibs_mt.7z) and extract them to `3rdparty\llvm\`, as well as download and extract the [additional libs](https://github.com/RPCS3/glslang/releases/latest/download/glslanglibs_mt.7z) to `lib\%CONFIGURATION%-x64\` to speed up compilation time (unoptimised/debug libs are currently not available precompiled).

If you're not using the precompiled libs, build the following projects in *__BUILD_BEFORE* folder by right-clicking on a project > *Build*.:
* glslang
Expand Down
20 changes: 11 additions & 9 deletions rpcs3/Emu/Cell/lv2/sys_usbd.cpp
Expand Up @@ -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<u8>(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);
}
}

Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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<u8*>(descriptor.get_ptr());
usbh.handled_devices[device_handle].second->device.write_data(ptr);
if (!descriptor)
brian218 marked this conversation as resolved.
Show resolved Hide resolved
{
return CELL_EFAULT;
}

usbh.handled_devices[device_handle].second->device.write_data(reinterpret_cast<u8*>(descriptor.get_ptr()), desc_size);

return CELL_OK;
}
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_usbd.h
Expand Up @@ -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<u64> arg1, vm::ptr<u64> arg2, vm::ptr<u64> 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<u8> buf, u32 buf_size, vm::ptr<UsbDeviceRequest> request, u32 type_transfer);
error_code sys_usbd_isochronous_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm::ptr<UsbDeviceIsoRequest> iso_request);
error_code sys_usbd_get_transfer_status(ppu_thread& ppu, u32 handle, u32 id_transfer, u32 unk1, vm::ptr<u32> result, vm::ptr<u32> count);
Expand Down
17 changes: 10 additions & 7 deletions rpcs3/Emu/Io/usb_device.h
Expand Up @@ -144,6 +144,7 @@ struct UsbDescriptorNode
subnodes.push_back(newnode);
return subnodes.back();
}

u32 get_size() const
{
u32 nodesize = bLength;
Expand All @@ -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<u32>(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;
}
};

Expand Down