1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# Sudoers grants for the TinyUSB HIL rig agent user. Generic-by-UID: grants target "#1000", the
# first regular account on Debian/Ubuntu (the rig agent user) — no username hardcoded, no edit
# needed. If your agent user is a different UID, change #1000 accordingly (e.g. #1001), or swap
# to a group with "%groupname". The actions-runner path is wildcarded (/home/*/) since a UID
# doesn't name a home directory.
#
# Deploy (from the repo root, needs your password once):
# sudo install -m0440 -oroot -groot test/hil/tinyusb-sudoer /etc/sudoers.d/tinyusb-sudoer
# sudo visudo -c
#
# The referenced helper scripts are versioned under .claude/skills/ and installed with:
# sudo install -m0755 -oroot -groot .claude/skills/usb-recover/scripts/usb_recover.sh /usr/local/sbin/
# sudo install -m0755 -oroot -groot .claude/skills/usb-debug/scripts/usb_dyndbg.sh /usr/local/sbin/
#
# What each grant is for:
# dmesg - read kernel log (USB events, usbtest results)
# uhubctl - hub port power control (only works on buses with ppps)
# usb_recover.sh - narrow sysfs USB reset helper (see .claude/skills/usb-recover)
# usb_dyndbg.sh - kernel dynamic-debug toggle for USB modules (see .claude/skills/usb-debug)
# tee usbtest sysfs paths - bind/unbind the usbtest host driver (test/hil/usbtest.py)
# tee .../driver/unbind - steal the interface from a foreign driver before binding usbtest
# modprobe usbtest - load the usbtest module on demand
# testusb - run test cases when the device node is not user-writable (no udev
# rule); with the shipped 99-tinyusb udev rule the node is 0666 and
# this grant is unused
# systemctl stop/start - stop/start the CI GitHub Actions runner service around manual hardware
# actions.runner.* runs so it doesn't reflash boards mid-test (see the hil skill). Granted
# on the root-owned systemctl unit (actions.runner.<owner>-<repo>.<name>
# .service), NOT on ~/actions-runner/svc.sh — that script lives in the
# runner user's writable home, so sudo on it would equal passwordless root.
# Find the unit: systemctl list-units 'actions.runner.*'
# (controller re-bind after a driverless pci-rebind is handled by usb_recover.sh pci-bind, which
# is already covered by the usb_recover.sh grant above — no extra sudoers rule needed.)
# systemctl reboot --force - last-resort USB recovery when a testusb D-state URB is unkillable and
# neither pci-reset (ENOTTY on Renesas) nor pci-bind can revive the
# controller (see the usb-recover skill). --force is required: a graceful
# reboot blocks in shutdown waiting for the wedged D-state process to
# terminate (it never does), so plain reboot stalls; --force terminates
# services and reboots immediately. Plain reboot kept for non-wedge use.
# An @reboot one-shot resumes the working session afterwards.
# NB: '#1000' below is a UID specifier (sudoers(5) User_List syntax), NOT a comment — these
# lines are live grants for uid 1000.
#1000 ALL=(root) NOPASSWD: /usr/bin/dmesg, /sbin/uhubctl
#1000 ALL=(root) NOPASSWD: /usr/local/sbin/usb_recover.sh
#1000 ALL=(root) NOPASSWD: /usr/local/sbin/usb_dyndbg.sh
#1000 ALL=(root) NOPASSWD: /usr/bin/systemctl stop actions.runner.*, /usr/bin/systemctl start actions.runner.*
#1000 ALL=(root) NOPASSWD: /usr/local/bin/testusb *
#1000 ALL=(root) NOPASSWD: /usr/bin/systemctl reboot --force, /usr/bin/systemctl reboot
#1000 ALL=(root) NOPASSWD: /usr/bin/tee /sys/bus/usb/drivers/usbtest/new_id, /usr/bin/tee /sys/bus/usb/drivers/usbtest/remove_id, /usr/bin/tee /sys/bus/usb/drivers/usbtest/bind, /usr/bin/tee /sys/bus/usb/drivers/usbtest/unbind, /usr/bin/tee /sys/bus/usb/devices/*/driver/unbind, /usr/bin/tee /sys/module/usbtest/parameters/pattern, /usr/sbin/modprobe usbtest
|