XCP-ng
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    USB Passthrough has stopped working after update and updating usb-policy.conf

    Scheduled Pinned Locked Moved Solved Hardware
    9 Posts 4 Posters 228 Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • T Offline
      techjeff
      last edited by

      Hello,

      As always, I am grateful for such an awesome open-source solution! Thank you all!

      Asking regarding my home lab -- I have a VM whose disk is located on my master host's local storage and I've been using USB passthrough to pass a Yubikey to the VM.

      I know that in the past, after an update, I often had to update /etc/xensource/usb-policy.conf to allow my YubiKey, reboot the host, then run xe pusb-scan host-uuid=<host-uuid> before I could configure passthrough of my yubikey.

      I installed updates the other day, but as the weather was hot and I wasn't using my homelab, I shut everything down before any of my TLS certificates expired, so I didn't notice that the usb-policy.conf file had been overwritten by the update (I know that this is to be expected).

      Today, I booted up my system and noticed the usb-policy.conf file had overwritten during the update, so I backed up /etc/xensource/usb-policy.conf, then added the line plus comments that has historically allowed my YubiKey to be passed through.

      Original /etc/xensource/usb-policy.conf:

      # When you change this file, run 'xe pusb-scan' to confirm
      # the file can be parsed correctly.
      #
      # Syntax is an ordered list of case insensitive rules where # is line comment
      #  and each rule is (ALLOW | DENY) : ( match )*
      #  and each match is (class|subclass|prot|vid|pid|rel) = hex-number
      # Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
      #
      # USB Hubs (class 09) are always denied, independently of the rules in this file
      DENY: vid=17e9 # All DisplayLink USB displays
      DENY: class=02 # Communications and CDC-Control
      ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
      ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
      ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
      DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
      DENY: class=03 subclass=01 prot=02 # HID Boot mice
      DENY: class=0a # CDC-Data
      DENY: class=0b # Smartcard
      DENY: class=e0 # Wireless controller
      DENY: class=ef subclass=04 # Miscellaneous network devices
      ALLOW: # Otherwise allow everything else
      

      Updated /etc/xensource/usb-policy.conf

      # When you change this file, run 'xe pusb-scan' to confirm
      # the file can be parsed correctly.
      #
      # Syntax is an ordered list of case insensitive rules where # is line comment
      #  and each rule is (ALLOW | DENY) : ( match )*
      #  and each match is (class|subclass|prot|vid|pid|rel) = hex-number
      # Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
      #
      # USB Hubs (class 09) are always denied, independently of the rules in this file
      DENY: vid=17e9 # All DisplayLink USB displays
      DENY: class=02 # Communications and CDC-Control
      ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
      ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
      ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
      DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
      DENY: class=03 subclass=01 prot=02 # HID Boot mice
      DENY: class=0a # CDC-Data
      DENY: class=0b # Smartcard
      DENY: class=e0 # Wireless controller
      DENY: class=ef subclass=04 # Miscellaneous network devices
      
      ### Jeff
      # YubiKey 5 FIPS Series PID 0x0407 - YubiKey OTP+FIDO+CCID
      ALLOW: VID=1050 PID=0407
      
      ALLOW: # Otherwise allow everything else
      

      Today, however, the YubiKey won't show up as a PUSB device when viewing the host's advanced tab, nor is it in the list of available devices when I attempt to create a VUSB for my VM.

      I have rebooted the system, I have run xe pusb-scan host-uuid=... for the appropriate host, I have physically disconnected and reconnected the YubiKey, I have powered down the host, then powered back on, but running xe pusb-list doesn't show the yubikey and I can't select it for passthrough.

      When I run lsusb I do see the YubiKey listed (thoigh it detects it as a Yubikey 4 series instead of 5 series. Can't recall whether that's consistent with past behavior)

      [14:03 xcp-ng-4 ~]# lsusb
      Bus 002 Device 004: ID 1050:0407 Yubico.com Yubikey 4 OTP+U2F+CCID
      Bus 002 Device 005: ID 413c:2113 Dell Computer Corp. 
      Bus 002 Device 003: ID 0557:8021 ATEN International Co., Ltd Hub
      Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
      Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
      Bus 001 Device 003: ID 0557:2221 ATEN International Co., Ltd Winbond Hermon
      Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
      Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
      [14:03 xcp-ng-4 ~]# 
      

      Is there anything I'm missing? Any suggestions for where to look or what to check?

      Thank you!

      1 Reply Last reply Reply Quote 0
      • T Offline
        techjeff @techjeff
        last edited by techjeff

        tl;dr - empty line(s) in /etc/xensource/usb-policy.conf crashes /opt/xensource/libexec/usb_scan.py

        I did a bit of scanning through the xapi source, in particular https://github.com/xapi-project/xen-api/blob/master/python3/libexec/usb_scan.py

        I'm not a python expert, so I could generally follow the flow of things, but I wasn't totally sure what was happening at a detailed level. Then I did some googling and found this xenserver help doc regarding troubleshooting usb passthrough: https://support.citrix.com/external/article/235040/how-to-troubleshoot-xenserver-usb-passth.html

        This article suggested running /opt/xensource/libexec/usb_scan.py with the -d parameter for additional details and that lead me to discover that the script fails when it encounters an empty line in usb-policy.conf

        [23:46 xcp-ng-4 ~]# /opt/xensource/libexec/usb_scan.py -d
        Traceback (most recent call last):
          File "/opt/xensource/libexec/usb_scan.py", line 681, in <module>
            pusbs = make_pusbs_list(devices, interfaces)
          File "/opt/xensource/libexec/usb_scan.py", line 660, in make_pusbs_list
            policy = Policy()
          File "/opt/xensource/libexec/usb_scan.py", line 384, in __init__
            self.parse_line(line)
          File "/opt/xensource/libexec/usb_scan.py", line 444, in parse_line
            if action.lower() == "allow":
        UnboundLocalError: local variable 'action' referenced before assignment
        

        After removing all empty lines, usb_scan.py scanned output properly, but it was giving me an empty array

        [23:53 xcp-ng-4 ~]# /opt/xensource/libexec/usb_scan.py -d
        []
        

        Since it as no longer crashing, I decided to go back to the default usb-policy.conf then try only adding my single allow rule without any extra lines and then test.

        cp /etc/xensource/usb-policy.conf.default /etc/xensource/usb-policy.conf
        

        I inserted a new line at line 10 just above the first rule and added my allow rule:

        ALLOW:vid=1050 pid=0407
        

        and that was all that was needed! Now I can see the device after running usb_scan.py

        [23:53 xcp-ng-4 ~]# /opt/xensource/libexec/usb_scan.py -d
        [{"path": "2-1.1", "version": "2.00", "vendor-id": "1050", "product-id": "0407", "vendor-desc": "Yubico.com", "product-desc": "Yubikey 4 OTP+U2F+CCID", "speed": "12", "serial": "", "description": "Yubico.com_Yubikey 4 OTP+U2F+CCID"}]
        

        I also learned that the last good output of xe usb-scan seems to be cached somewhere and is quietly returned without hesitation when usb_policy.py fails. Maybe it's logged somewhere, but I don't know.

        In any case, it was as simple as an empty line -- don't take anything for granted!

        Lastly, I did a bit of testing to confirm that for my Yubikey to be detected and allowed, the allow rule must be BEFORE the rule that denies HID Boot Keyboards.

        This results in detection:

        # When you change this file, run 'xe pusb-scan' to confirm
        # the file can be parsed correctly.
        #
        # Syntax is an ordered list of case insensitive rules where # is line comment
        #  and each rule is (ALLOW | DENY) : ( match )*
        #  and each match is (class|subclass|prot|vid|pid|rel) = hex-number
        # Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
        #
        # USB Hubs (class 09) are always denied, independently of the rules in this file
        DENY: vid=17e9 # All DisplayLink USB displays
        DENY: class=02 # Communications and CDC-Control
        ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
        ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
        ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
        # @jeff - allow passthrough of Yubikey 5 FIPS, "Yubikey 4 OTP+U2F+CCID"
        ALLOW:vid=1050 pid=0407
        DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
        DENY: class=03 subclass=01 prot=02 # HID Boot mice
        DENY: class=0a # CDC-Data
        DENY: class=0b # Smartcard
        DENY: class=e0 # Wireless controller
        DENY: class=ef subclass=04 # Miscellaneous network devices
        ALLOW: # Otherwise allow everything else
        

        This does not:

        # When you change this file, run 'xe pusb-scan' to confirm
        # the file can be parsed correctly.
        #
        # Syntax is an ordered list of case insensitive rules where # is line comment
        #  and each rule is (ALLOW | DENY) : ( match )*
        #  and each match is (class|subclass|prot|vid|pid|rel) = hex-number
        # Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
        #
        # USB Hubs (class 09) are always denied, independently of the rules in this file
        DENY: vid=17e9 # All DisplayLink USB displays
        DENY: class=02 # Communications and CDC-Control
        ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
        ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
        ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
        DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
        # @jeff - allow passthrough of Yubikey 5 FIPS, "Yubikey 4 OTP+U2F+CCID"
        ALLOW:vid=1050 pid=0407
        DENY: class=03 subclass=01 prot=02 # HID Boot mice
        DENY: class=0a # CDC-Data
        DENY: class=0b # Smartcard
        DENY: class=e0 # Wireless controller
        DENY: class=ef subclass=04 # Miscellaneous network devices
        ALLOW: # Otherwise allow everything else
        

        Thanks to everyone who took a look. Hopefully you don't get caught by this same gotcha!

        A 1 Reply Last reply Reply Quote 1
        • K Offline
          knightjoel
          last edited by

          Hello. I had a similar issue which I solved by adding my ALLOW line to the top of the list in the usb-policy.conf file. I didn't deep dive to find out why this was necessary in my case. Worth a try in your case as well.

          .joel

          T 1 Reply Last reply Reply Quote 0
          • T Offline
            techjeff @knightjoel
            last edited by

            @knightjoel Thanks for the suggestion. Since my original message, I've tried moving my allow rule to the top, before any Deny rules, after any deny rules, I even tried experimenting with commenting all of the deny rules to see if any of those would make a difference; unfortunately none of them made a difference.

            I've tried simply saving the file then initiating a xe pusb-scan on the host, I also tried rebooting to see if that would have an effect, but it doesn't seem to.

            1 Reply Last reply Reply Quote 0
            • T techjeff marked this topic as a question
            • T Offline
              techjeff
              last edited by

              Does anyone have any suggestions for troubleshooting or investigating this further? I didn't really change my process that has worked with several updates but now things are behaving differently..

              T 1 Reply Last reply Reply Quote 0
              • T Offline
                techjeff @techjeff
                last edited by techjeff

                tl;dr - empty line(s) in /etc/xensource/usb-policy.conf crashes /opt/xensource/libexec/usb_scan.py

                I did a bit of scanning through the xapi source, in particular https://github.com/xapi-project/xen-api/blob/master/python3/libexec/usb_scan.py

                I'm not a python expert, so I could generally follow the flow of things, but I wasn't totally sure what was happening at a detailed level. Then I did some googling and found this xenserver help doc regarding troubleshooting usb passthrough: https://support.citrix.com/external/article/235040/how-to-troubleshoot-xenserver-usb-passth.html

                This article suggested running /opt/xensource/libexec/usb_scan.py with the -d parameter for additional details and that lead me to discover that the script fails when it encounters an empty line in usb-policy.conf

                [23:46 xcp-ng-4 ~]# /opt/xensource/libexec/usb_scan.py -d
                Traceback (most recent call last):
                  File "/opt/xensource/libexec/usb_scan.py", line 681, in <module>
                    pusbs = make_pusbs_list(devices, interfaces)
                  File "/opt/xensource/libexec/usb_scan.py", line 660, in make_pusbs_list
                    policy = Policy()
                  File "/opt/xensource/libexec/usb_scan.py", line 384, in __init__
                    self.parse_line(line)
                  File "/opt/xensource/libexec/usb_scan.py", line 444, in parse_line
                    if action.lower() == "allow":
                UnboundLocalError: local variable 'action' referenced before assignment
                

                After removing all empty lines, usb_scan.py scanned output properly, but it was giving me an empty array

                [23:53 xcp-ng-4 ~]# /opt/xensource/libexec/usb_scan.py -d
                []
                

                Since it as no longer crashing, I decided to go back to the default usb-policy.conf then try only adding my single allow rule without any extra lines and then test.

                cp /etc/xensource/usb-policy.conf.default /etc/xensource/usb-policy.conf
                

                I inserted a new line at line 10 just above the first rule and added my allow rule:

                ALLOW:vid=1050 pid=0407
                

                and that was all that was needed! Now I can see the device after running usb_scan.py

                [23:53 xcp-ng-4 ~]# /opt/xensource/libexec/usb_scan.py -d
                [{"path": "2-1.1", "version": "2.00", "vendor-id": "1050", "product-id": "0407", "vendor-desc": "Yubico.com", "product-desc": "Yubikey 4 OTP+U2F+CCID", "speed": "12", "serial": "", "description": "Yubico.com_Yubikey 4 OTP+U2F+CCID"}]
                

                I also learned that the last good output of xe usb-scan seems to be cached somewhere and is quietly returned without hesitation when usb_policy.py fails. Maybe it's logged somewhere, but I don't know.

                In any case, it was as simple as an empty line -- don't take anything for granted!

                Lastly, I did a bit of testing to confirm that for my Yubikey to be detected and allowed, the allow rule must be BEFORE the rule that denies HID Boot Keyboards.

                This results in detection:

                # When you change this file, run 'xe pusb-scan' to confirm
                # the file can be parsed correctly.
                #
                # Syntax is an ordered list of case insensitive rules where # is line comment
                #  and each rule is (ALLOW | DENY) : ( match )*
                #  and each match is (class|subclass|prot|vid|pid|rel) = hex-number
                # Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
                #
                # USB Hubs (class 09) are always denied, independently of the rules in this file
                DENY: vid=17e9 # All DisplayLink USB displays
                DENY: class=02 # Communications and CDC-Control
                ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
                ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
                ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
                # @jeff - allow passthrough of Yubikey 5 FIPS, "Yubikey 4 OTP+U2F+CCID"
                ALLOW:vid=1050 pid=0407
                DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
                DENY: class=03 subclass=01 prot=02 # HID Boot mice
                DENY: class=0a # CDC-Data
                DENY: class=0b # Smartcard
                DENY: class=e0 # Wireless controller
                DENY: class=ef subclass=04 # Miscellaneous network devices
                ALLOW: # Otherwise allow everything else
                

                This does not:

                # When you change this file, run 'xe pusb-scan' to confirm
                # the file can be parsed correctly.
                #
                # Syntax is an ordered list of case insensitive rules where # is line comment
                #  and each rule is (ALLOW | DENY) : ( match )*
                #  and each match is (class|subclass|prot|vid|pid|rel) = hex-number
                # Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
                #
                # USB Hubs (class 09) are always denied, independently of the rules in this file
                DENY: vid=17e9 # All DisplayLink USB displays
                DENY: class=02 # Communications and CDC-Control
                ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
                ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
                ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
                DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
                # @jeff - allow passthrough of Yubikey 5 FIPS, "Yubikey 4 OTP+U2F+CCID"
                ALLOW:vid=1050 pid=0407
                DENY: class=03 subclass=01 prot=02 # HID Boot mice
                DENY: class=0a # CDC-Data
                DENY: class=0b # Smartcard
                DENY: class=e0 # Wireless controller
                DENY: class=ef subclass=04 # Miscellaneous network devices
                ALLOW: # Otherwise allow everything else
                

                Thanks to everyone who took a look. Hopefully you don't get caught by this same gotcha!

                A 1 Reply Last reply Reply Quote 1
                • T techjeff has marked this topic as solved
                • olivierlambertO Offline
                  olivierlambert Vates 🪐 Co-Founder CEO
                  last edited by

                  Pinging @Team-Documentation-Knowledge-Management and @Team-XAPI-Network to review this and see if it's a good idea to document stuff 🙂

                  T 1 Reply Last reply Reply Quote 2
                  • A Offline
                    andriy.sultanov Vates 🪐 XAPI & Network Team @techjeff
                    last edited by

                    @techjeff I'll fix the script to not choke on empty lines - thanks for the spot!

                    Our documentation (https://docs.xcp-ng.org/compute/#passing-through-keyboards-and-mice) does say to run usb_scan.py -d to verify the config file, though the error wasn't particularly helpful...

                    The config file also specifies its "syntax is an ordered list of rules", maybe the fact that the order is important could be worth emphasizing even more?

                    T 1 Reply Last reply Reply Quote 1
                    • T Offline
                      techjeff @andriy.sultanov
                      last edited by

                      @andriy.sultanov great, thank you for taking that on!

                      I must have skimmed over that part of the docs too quickly to notice the recommendation to run usb_scan.py.

                      I think it would be helpful to explain more verbosely how the order and specificity impact the final outcomes as it's not clear to me. It seems that if I make a more specific rule for my Yubikey before a more general rule that would block devices of the same class, it seems to work, but perhaps not in reverse?

                      I'm reminded of the apache Order directive where it can be AllowDeny or DenyAllow — my dyslexic brain has a hard time keeping track of binaries.

                      1 Reply Last reply Reply Quote 1
                      • T Offline
                        techjeff @olivierlambert
                        last edited by

                        @olivierlambert Thank you for bringing this to the attention of other folks 🙂

                        1 Reply Last reply Reply Quote 1
                        • First post
                          Last post