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

Support resetting device on attach #36

Merged
merged 3 commits into from
May 29, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ install-vm:
install qubes-rpc/qubes.USB $(DESTDIR)/etc/qubes-rpc
install -d $(DESTDIR)/usr/lib/qubes
install src/usb-* $(DESTDIR)/usr/lib/qubes
install -d $(DESTDIR)/usr/lib/udev/rules.d
install src/*.rules $(DESTDIR)/usr/lib/udev/rules.d
install -d $(DESTDIR)/etc/qubes/suspend-pre.d
ln -s ../../../usr/lib/qubes/usb-detach-all \
$(DESTDIR)/etc/qubes/suspend-pre.d/usb-detach-all.sh
Expand Down
2 changes: 2 additions & 0 deletions rpm_spec/qubes-usb-proxy.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ make install-vm DESTDIR=${RPM_BUILD_ROOT}
/usr/lib/qubes/usb-import
/usr/lib/qubes/usb-export
/usr/lib/qubes/usb-detach-all
/usr/lib/qubes/usb-reset
/usr/lib/udev/rules.d/80-qubes-usb-reset.rules

%changelog
@CHANGELOG@
3 changes: 3 additions & 0 deletions src/80-qubes-usb-reset.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Nitrokey 3 Bootloader, requires reset on attach
# See https://github.com/QubesOS/qubes-issues/issues/8953
SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="20a0", ENV{ID_MODEL_ID}=="42dd", ENV{QUBES_USB_RESET}="1"
22 changes: 20 additions & 2 deletions src/usb-export
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,32 @@ modprobe usbip-host
# Request that both IN and OUT be handled on a single (stdin) socket
kill -USR1 "$QREXEC_AGENT_PID" || exit 1

attach_to_usbip=true
# Unbind the device from the driver
if [ -d "$devpath/driver" ]; then
printf %s "$busid" > "$devpath/driver/unbind" || exit 1
old_driver=$(readlink -f "$devpath/driver")
if [ "$old_driver" != "$SYS_USBIP_HOST" ]; then
printf %s "$busid" > "$devpath/driver/unbind" || exit 1
else
attach_to_usbip=
fi
fi

# Bind to the usbip-host driver
printf 'add %s' "$busid" > "$SYS_USBIP_HOST/match_busid" || exit 1
echo "$busid" > "$SYS_USBIP_HOST/bind" || exit 1
if [ -n "$attach_to_usbip" ]; then
echo "$busid" > "$SYS_USBIP_HOST/bind" || exit 1

# optionally reset the device to clear any state from previous driver
reset_on_attach=$(udevadm info --query=property \
--value --property=QUBES_USB_RESET --path="$devpath")
if [ -f /run/qubes-service/usb-reset-on-attach ]; then
reset_on_attach=1
fi
if [ -n "$reset_on_attach" ]; then
/usr/lib/qubes/usb-reset "$devpath"
fi
fi

# One more safety check - make sure the device is available
read status < "$devpath/usbip_status"
Expand Down
25 changes: 25 additions & 0 deletions src/usb-reset
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/python3

import sys
import os
import fcntl
from pathlib import Path

# from /usr/include/linux/usbdevice_fs.h
# _IO('U', 20)
USBDEVFS_RESET = 0x5514

def main():
if len(sys.argv) != 2:
print("Usage: usb-reset sysfs-devpath", file=sys.stderr())
exit(2)
devpath = sys.argv[1]
uevent = (Path(devpath) / "uevent").read_text()
devname = [line.partition("=")[2]
for line in uevent.splitlines()
if line.startswith("DEVNAME=")][0]
with (Path("/dev") / devname).open("w") as dev_f:
fcntl.ioctl(dev_f, USBDEVFS_RESET, 0)

if __name__ == "__main__":
main()