Re: [BUG] Potential race condition in usbip attach

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!

Here's a small report including the script to reproduce.

Test environment:
    QEMU/KVM Virtual Machine with Fedora 38 Workstation x86-64

    Kernel: 6.4.0-0.rc4.20230604gte5282a7d.339.vanilla.fc38.x86_64
from mainline repo

    usbip user-space package:
    Name         : usbip
    Version      : 5.7.9
    Release      : 8.fc38
    Architecture : x86_64
    Size         : 164 k
    Source       : usbip-5.7.9-8.fc38.src.rpm

    USB devices: two USB sticks passed to the VM, busid 1-5 and 1-6

usbipd and usbip attach commands are called on the same host.

Set up commands:
=====================
modprobe usbip_host
modprobe vhci_hcd

usbip bind -b 1-5
usbip bind -b 1-6
=====================

Start usbipd server:
=====================
usbipd
=====================

Test script:
=====================
#!/bin/bash

# This script tries to trigger the race condition during two parallel
calls of the usbip attach command.

while true; do
        usbip attach -r localhost -b 1-5 &
        # comment out this sleep to trigger race condition
        sleep 2
        usbip attach -r localhost -b 1-6 &
        wait
        echo "usbip attach called twice"
        # comment out this sleep to see usbip port command fail
        sleep 1
        check_attach="$(usbip port | wc -l)"
        if [[ ! $check_attach =~ "10" ]]; then
                echo "usbip port failed"
                usbip port
                break
        fi
        usbip detach -p 0
        usbip detach -p 1
        # comment out this sleep to see usbip port command fail
        sleep 1
        check_detach="$(usbip port | wc -l)"
        if [[ ! $check_detach =~ "2" ]]; then
                echo "usbip detach or usbip port failed"
                break
        fi
done
=====================

Test results:
1. With all three sleeps uncommented we observer the correct output:
the infinite loop repeats printing
===================== script output start ==============
usbip attach called twice
usbip: info: Port 0 is now detached!

usbip: info: Port 1 is now detached!

===================== script output end ===============
which means that we can attach and detach devices as many times as we want.

usbip port shows correct number of usbip devices
==================== usbip port output start ====================
[root@localhost-live ~]# usbip port
Imported USB devices
====================
Port 00: <Port in Use> at High Speed(480Mbps)
       Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.)
: unknown product (090c:2000)
       3-1 -> usbip://localhost:3240/1-5
           -> remote bus/dev 001/004
Port 01: <Port in Use> at High Speed(480Mbps)
       unknown vendor : unknown product (0000:7777)
       3-2 -> usbip://localhost:3240/1-6
           -> remote bus/dev 001/005
====================== usbip port output end ===================

2. Comment out the first sleep and you will get race condition. The
script hangs since one of the
usbip attach commands is stuck in its inner infinite loop and the same
message is repeated in dmesg output:
===================== dmesg ===========================
[  691.760921] vhci_hcd vhci_hcd.0: port 0 already used
[  691.761022] vhci_hcd vhci_hcd.0: port 0 already used
[  691.761428] vhci_hcd vhci_hcd.0: port 0 already used
[  691.761553] vhci_hcd vhci_hcd.0: port 0 already used
[  691.761752] vhci_hcd vhci_hcd.0: port 0 already used
[  691.761892] vhci_hcd vhci_hcd.0: port 0 already used
===================== dmesg ===========================

usbipd does not know about the client issue and prints the following
as nothing happened:
====================== usbipd output start ==========================
usbipd: info: connection from ::1:42928
usbipd: info: connection from ::1:42942
usbipd: info: received request: 0x8003(5)
usbipd: info: found requested device: 1-5
usbipd: info: received request: 0x8003(5)
usbipd: info: found requested device: 1-6
usbip: info: connect: 1-5
usbipd: info: request 0x8003(5): complete
usbip: info: connect: 1-6
usbipd: info: request 0x8003(5): complete
======================= usbipd output end =============================

usbip port command shows only one device attached to the client:
======================= usbip port output start ==============================
[root@localhost-live ~]# usbip port
Imported USB devices
====================
Port 00: <Port in Use> at High Speed(480Mbps)
       unknown vendor : unknown product (0000:7777)
       3-1 -> usbip://localhost:3240/1-6
           -> remote bus/dev 001/005
======================== usbip port output end ================================


3. Speaking about the second and the third sleep, we need to put sleep there
because there is no synchronization between kernel and userspace.
Comment it out to observe other behaviour.

Best,
Alexander Timofeev

On Sat, May 27, 2023 at 1:32 AM Shuah Khan <skhan@xxxxxxxxxxxxxxxxxxx> wrote:
>
> On 5/24/23 11:48, Alexander Timofeev wrote:
> > Hi!
> >
> > Sorry if you have received this email twice. My first email contained
> > html and was not accepted by the mailing list.
> >
> > I think I have found a race condition which can be triggered for
> > example when calling two usbip attach commands in parallel on the same
> > host.
> >
> > In file linux/tools/usb/usbip/src /usbip_attach.c:
> > In function static int import_device(int sockfd, struct usbip_usb_device *udev):
> >
> > At first two processes may call usbip_vhci_driver_open() before
> > entering the do-while loop.
> > Next they both call usbip_vhci_get_free_port() and get the same free port.
> > Finally, they pass the same port number to usbip_vhci_attach_device().
> >
> > Current recommendation to end users: run usbip attach commands only
> > sequentially.
> >
>
> Will you be able to share the reproducer?
>
> thanks,
> -- Shuah
>




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux