Skip to content

[Bug]: VUSB: USBProxyDevice-usbip buffer handling regression 7.1.12 -> 7.2.0 => fixed in SVN/next 7.2.x maintenance #192

@mars-low

Description

@mars-low

Version

7.2.0

Host OS Type

all

Host OS name + version

macOS Sequoia Version 15.6.1 (24G90)

Host Architecture

ARM

Guest OS Type

all

Guest Architecture

ARM

Guest OS name + version

Debian 12.11.0

Component

USB and Serial Ports

What happened?

Recently I've stumbled upon the regression in USB/IP backend. I've confirmed it works with VirtualBox 7.1.12 (released July 15 2025) and is broken on 7.2.0 for Linux (X86-64), Windows (X86-64) and macOS (Apple Silicon) hosts. My main computer is Apple Mac Mini M4 Pro. On macOS I've tested with Windows 11 Arm64, Debian 12 Arm64 and FreeBSD 14.3 Arm64 guests and USB/IP backend doesn't work in any case. Therefore I think it isn't specific to host/guest/arch combination. Direct USB device capture works fine in all cases, so it seems specific to USBProxyDevice-usbip.cpp.

I would expect USB/IP backend to work as it used to work in VirtualBox 7.1.12.

How can we reproduce this?

There is no established open-source solution for USB/IP server on macOS, so a reproduction on this system is a little convoluted. One needs to use a machine (physical or virtual) with Windows or Linux operating system to export USB devices via USB/IP server.

  1. Linux has built-in support for USB/IP client and server
  2. Windows has quite popular third-party implementations of USB/IP protocol

I've played with tools above and all have practical applications / support multiple devices of different classes.

There are also custom USB/IP server implementations, used mainly for the emulation of arbitrary devices, but these usually don't support multiple simultaneous connections required by VirtualBox - one thread in VirtualBox is polling for available devices exported by the server and separate threads are used for each imported device to exchange URBs.

For reproduction, only USB/IP server is of interest, because USB/IP client is already implemented by VirtualBox itself. Considering the above conditions, I think it's easiest to reproduce the issue on Windows or Linux where USB/IP server is readily available. Especially on Linux, setup is already described in Setting up USB/IP Support on a Linux System chapter of VirtualBox manual.

As I have unconstrained access only to macOS machine, I've tried to prepare clear reproduction steps based on virtual machines spawned with VirtualBox. Hopefully it can be reproduced in a similar way on any host system (probably besides steps related to VM setup which seem to contain elements specific to Arm64 guests). Initial steps related to VM creation and guest system installation can be performed using GUI as well. I've ported instructions to command line to avoid pasting multiple screenshots.

Machine configuration and guest OS installation

The setup consists of two identical Linux virtual machines VM A and VM B. VM A is used to run USB/IP server with an emulated USB device on a Linux guest. VM B is used to import USB/IP device exported by VM A using USB/IP client built into VirtualBox. Guest system for VM B doesn't matter - for simplicity it's a clone of VM A.

VM_NAME_A="Debian12A"
VM_NAME_B="Debian12B" # VM B will be the clone of VM A

VDI_PATH_A="$HOME/VirtualBox VMs/$VM_NAME_A/$VM_NAME_A.vdi"

# Use Debian 12 Arm64 as the guest OS which is listed by `vboxmanage list ostypes | grep Debian12_arm64`
vboxmanage createvm --name $VM_NAME_A --ostype "Debian12_arm64" --register
# USB controller is necessary to test the capture of USB/IP device to a virtual machine.
vboxmanage modifyvm $VM_NAME_A --memory 4096 --vram 128 --ioapic on --graphicscontroller vmsvga --usb-xhci on --mouse usbtablet --keyboard usb

# virtio-scsi transport may be specific to macOS Apple Silicon.
# Adapt to other platforms or use GUI configurator to create VM.
vboxmanage storagectl $VM_NAME_A --name "VirtioSCSI" --add virtio-scsi --controller VirtIO --bootable on --hostiocache off --portcount 2
vboxmanage createmedium --filename $VDI_PATH_A --size 20480
vboxmanage storageattach $VM_NAME_A --storagectl "VirtioSCSI" --port 0 --device 0 --type hdd --medium $VDI_PATH_A

# Download ISO from the official source and perform unattended install.
curl -L -o debian-12.11.0-arm64-netinst.iso https://cdimage.debian.org/cdimage/archive/12.11.0/arm64/iso-cd/debian-12.11.0-arm64-netinst.iso
vboxmanage unattended install $VM_NAME_A --iso debian-12.11.0-arm64-netinst.iso --user codespace --user-password codespace --admin-password codespace --start-vm headless

# Once the installation is complete and machine rebooted, turn it off.
# To check for restart in headless mode, run `vboxmanage guestproperty enumerate $VM_NAME_A`.
# The output should contain the line: `/VirtualBox/VMInfo/ResetCounter   = '1'`.
vboxmanage controlvm $VM_NAME_A poweroff

# Clone machine (the first one will be used to provide USB/IP server from the Linux guest,
# the second one will be used to attach USB/IP exported device using VirtualBox's built-in USB/IP client).
vboxmanage clonevm $VM_NAME_A --name $VM_NAME_B --register

# Setup port forwarding to access machines via ssh in headless mode.
vboxmanage modifyvm $VM_NAME_A --nat-pf1="guestssh,tcp,,2222,,22"
vboxmanage modifyvm $VM_NAME_B --nat-pf1="guestssh,tcp,,2223,,22"

# For the machine additionally forward USB/IP server port
# which will be used for testing built-in USB/IP client in VirtualBox.
# USB/IP server port 3240 on the guest is forwarded to port 3245 on the host.
vboxmanage modifyvm $VM_NAME_A --nat-pf1="guestusbipserver,tcp,,3245,,3240"

# Start both virtual machines.
vboxmanage startvm $VM_NAME_A --type headless
vboxmanage startvm $VM_NAME_B --type headless

# Virtual machines were launched in headless mode without GUI.
# Connect to them via ssh (we previously configured port forwarding).
ssh -p 2222 codespace@localhost
ssh -p 2223 codespace@localhost

The reproducer provided below doesn't require access to physical USB device.

I've managed to leverage USB Gadget framework with a virtual UDC called usbip-vudc to emulate USB device and export it via USB/IP server on Linux.

A documentation about exporting emulated USB Gadget is supplemented with vudc_server_example.sh. ABI for sysfs-platform-usbip-vudc is also available.

VM A

ssh -p 2222 codespace@localhost (password: codespace):

# Run as superuser (most commands below require root acces).
su
# /usr/sbin is not in the path by default (it contains usbip tool installed later).
export PATH=$PATH:/usr/sbin
# Load basic modules to enable support for USB Gadgets.
modprobe udc-core
modprobe libcomposite
# Create a single instance of virtual UDC.
modprobe usbip-vudc num=1
# Load an example gadget module (CDC-ACM) provided by the kernel.
# By default it is bound to the first available UDC.
modprobe g_serial
# Install userspace tool to handle usbip commands.
apt update && apt install usbip
# Run USB/IP daemon on port 3240 (default) in a device mode.
usbipd --tcp-port 3240 --device

VM B

ssh -p 2223 codespace@localhost (password: codespace):

su
dmesg -wH
# You will see kernel logs appearing when device gets enumerated.

On the host

Optional step: Wireshark for observing USB/IP traffic

11.2. Start Wireshark from the command line:

wireshark --interface lo0 -f "tcp port 3245" -d tcp.port==3245,usbip --display-filter 'usbip and !(_ws.col.info == "Device List Request") and  !(_ws.col.info == "Device List Response")' -k -S -l

Display filter is specified to decode traffic as USB/IP protocol and to filter out abundant OP_REQ_DEVLIST<->OP_REP_DEVLIST traffic from the VirtualBox's USB/IP client polling thread.

Attach USB/IP device to VirtualBox

# Register USB/IP server provided by VM A in the previous steps.
vboxmanage usbdevsource add usbipd3245 --backend USBIP --address 127.0.0.1:3245
# Attach USB/IP device exported by USB/IP server.
# Capture URB traffic in [usbmon format](https://docs.kernel.org/usb/usbmon.html) to get extra information about USB traffic besides the one obtained through Wireshark.
vboxmanage controlvm $VM_NAME_B usbattach "usbip://127.0.0.1:3245:usbip-vudc.0" --capturefile $HOME/vbox_usbip_client_attached_linux_usbip_server.pcap

After attaching, you should observe the successful USB device enumeration on VM B.

root@vbox:/home/codespace# dmesg -wH
[Aug31 17:54] usb 1-3: new high-speed USB device number 4 using xhci_hcd
[  +0.169678] usb 1-3: New USB device found, idVendor=0525, idProduct=a4a7, bcdDevice= 6.01
[  +0.000003] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  +0.000001] usb 1-3: Product: Gadget Serial v2.4
[  +0.000000] usb 1-3: Manufacturer: Linux 6.1.0-38-arm64 with usbip-vudc
[  +0.024737] cdc_acm 1-3:2.0: ttyACM0: USB ACM device
[  +0.000058] usbcore: registered new interface driver cdc_acm
[  +0.000001] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[  +2.542106] usb 1-3: USB disconnect, device number 4

Note

Device disconnects after the enumeration, what is an unintended behavior, but it's the issue specific only to USB/IP server on Linux. usbipd-win server doesn't manifest such behavior.
In any case it's not meaningful for the reproducer, as the regression in VirtualBox 7.2.0 prevents the very first packet from succeeding, so it doesn't even reach the enumerated state.

After testing is finished, unregister USB/IP server.

vboxmanage usbdevsource remove usbipd3245

Stop Wireshark capture if it was previously started.

Attachments

I attached the following files collected on macOS Apple Silicon host:

VirtualBox 7.1.12:

VirtualBox 7.2.0:

To analyze USB/IP pcap capture files attached in zip archives with wireshark, run the following command to apply the same decoder and filter used during capture:

wireshark -d tcp.port==3245,usbip --display-filter 'usbip and !(_ws.col.info == "Device List Request") and  !(_ws.col.info == "Device List Response")' 7_2_0_wireshark_usbip.pcapng

As an alternative, I attached plain text versions of capture files (File -> Export Packet Dissections -> As Plain Text...).

7_2_0_wireshark_usbip_as_plain_text.txt contains especially useful information. It presents 6 consecutive failed attempts to perform a control transfer. The issue seems to arise from USBProxyDevice.cpp::*GetStdDescSync even before XHCI controller kicks in.

Setup packet on VirtualBox 7.2.0 contains some garbage data (9083776b01000000) that doesn't represent a standard request.
Setup packet on VirtualBox 7.1.12 (8006000100001200) represents a standard request GET DESCRIPTOR (DEVICE) and I would expect the same on VirtualBox 7.2.0.

Other fields in USBIP_CMD_SUBMIT packet contain valid data. For example Transfer buffer length [bytes]: 18 what is the expected length of USB Device Descriptor.

Control transfer USB/IP traffic on VirtualBox 7.2.0 (regression)
No.     Time           Source                Destination           Protocol Length Info
     43 3.006046       host                  0.0.0                 USB      104    Unknown type 83 Request

Frame 43: 104 bytes on wire (832 bits), 104 bytes captured (832 bits) on interface lo0, id 0
Null/Loopback
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 49216, Dst Port: 3245, Seq: 41, Ack: 321, Len: 48
USBIP Protocol
    Command: OP_CMD_SUBMIT (0x00000001)
    Sequence: 1
    [Command frame: 43]
    [Return frame: 45]
    [Devid: 0x00000000]
    [.... .... .... .... .... .... .... ...1 = Direction: IN (0x1)]
    [.... .... .... .... .... .... .... 0000 = Endpoint: 0x0]
    Devid: 0x00000000
    .... .... .... .... .... .... .... ...1 = Direction: IN (0x1)
    .... .... .... .... .... .... .... 0000 = Endpoint: 0x0
    Transfer flags: 0x00000000
    Transfer buffer length [bytes]: 18
    ISO Start frame: 0
    Number of ISO descriptors: 0
    Interval: 0
    Setup Data: 9083776b01000000
USB URB
Setup Data
    bmRequestType: 0x90
    bRequest: Unknown (131)
    wValue: 0x6b77
    wIndex: 1 (0x0001)
    wLength: 0

No.     Time           Source                Destination           Protocol Length Info
     45 3.006844       127.0.0.1             127.0.0.1             USBIP    104    URB Response

Frame 45: 104 bytes on wire (832 bits), 104 bytes captured (832 bits) on interface lo0, id 0
Null/Loopback
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 3245, Dst Port: 49216, Seq: 321, Ack: 89, Len: 48
USBIP Protocol
    Command: OP_RET_SUBMIT (0x00000003)
    Sequence: 1
    [Command frame: 43]
    [Return frame: 45]
    [Devid: 0x00000000]
    [.... .... .... .... .... .... .... ...1 = Direction: IN (0x1)]
    [.... .... .... .... .... .... .... 0000 = Endpoint: 0x0]
    Devid: 0x00000000
    .... .... .... .... .... .... .... ...0 = Direction: OUT (0x0)
    .... .... .... .... .... .... .... 0000 = Endpoint: 0x0
    Status: Broken pipe (-EPIPE) (-32)
    Actual length: 0
    ISO Start frame: 0
    Number of ISO descriptors: 0
    ISO error count: 0
    Setup Data: 0000000000000000
Control transfer USB/IP traffic on VirtualBox 7.1.12 (okay)
No.     Time           Source                Destination           Protocol Length Info
     48 3.005296       host                  0.0.0                 USB      104    GET DESCRIPTOR Request DEVICE

Frame 48: 104 bytes on wire (832 bits), 104 bytes captured (832 bits) on interface lo0, id 0
Null/Loopback
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 50691, Dst Port: 3245, Seq: 41, Ack: 321, Len: 48
USBIP Protocol
    Command: OP_CMD_SUBMIT (0x00000001)
    Sequence: 1
    [Command frame: 48]
    [Return frame: 50]
    [Devid: 0x00000000]
    [.... .... .... .... .... .... .... ...1 = Direction: IN (0x1)]
    [.... .... .... .... .... .... .... 0000 = Endpoint: 0x0]
    Devid: 0x00000000
    .... .... .... .... .... .... .... ...1 = Direction: IN (0x1)
    .... .... .... .... .... .... .... 0000 = Endpoint: 0x0
    Transfer flags: 0x00000000
    Transfer buffer length [bytes]: 18
    ISO Start frame: 0
    Number of ISO descriptors: 0
    Interval: 0
    Setup Data: 8006000100001200
USB URB
Setup Data
    bmRequestType: 0x80
    bRequest: GET DESCRIPTOR (6)
    Descriptor Index: 0x00
    bDescriptorType: DEVICE (0x01)
    Language Id: no language specified (0x0000)
    wLength: 18

No.     Time           Source                Destination           Protocol Length Info
     50 3.006187       0.0.0                 host                  USB      122    GET DESCRIPTOR Response DEVICE

Frame 50: 122 bytes on wire (976 bits), 122 bytes captured (976 bits) on interface lo0, id 0
Null/Loopback
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 3245, Dst Port: 50691, Seq: 321, Ack: 89, Len: 66
USBIP Protocol
    Command: OP_RET_SUBMIT (0x00000003)
    Sequence: 1
    [Command frame: 48]
    [Return frame: 50]
    [Devid: 0x00000000]
    [.... .... .... .... .... .... .... ...1 = Direction: IN (0x1)]
    [.... .... .... .... .... .... .... 0000 = Endpoint: 0x0]
    Devid: 0x00000000
    .... .... .... .... .... .... .... ...0 = Direction: OUT (0x0)
    .... .... .... .... .... .... .... 0000 = Endpoint: 0x0
    Status: Success (0)
    Actual length: 18
    ISO Start frame: 0
    Number of ISO descriptors: 0
    ISO error count: 0
    Setup Data: 0000000000000000
USB URB
DEVICE DESCRIPTOR

I'd be eager to provide more necessary information at your request.
I'm in the process of learning how to build and debug VirtualBox from the source on Apple Silicon macOS
so I might be able to provide more useful insights.

Did you upload all of your necessary log files, screenshots, etc.?

  • Yes, I've uploaded all pertinent files to this issue.

Metadata

Metadata

Labels

bugSomething isn't workingfixed in svnCommit made to SVN repo. Will be on GitHub on next SVN sync. Issue/PR staged for close.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions