Remote-Url: https://zakaria.org/posts/2021-01-11-usbkiller.html Retrieved-at: 2021-08-15 11:33:45.000848+00:00 usbkillis a kill-switch that shuts down your computer on any USB change. It does this by watching the output oflsusband when there is a change it runsshutdown -h now.Simple, right? One thing to note is thatlsusbis not included in OpenBSD’s base packages, buthotplugd(8)is.hotplugdSo what ishotplugd, and how can it be useful? Theman pagedoes a good job of explaining it. Simply put: when any device is attached to or detached from your machinehotplugdwill execute a script.To see how simple it is to write a hotplug script we can start by simply logging device attach events. First, start by enabling and startinghotplugd(as root):# rcctl enable hotplugd # rcctl start hotplugd hotplugd(ok)Next we will write the script that is executed on a device attach event:# mkdir -p /etc/hotplug # $EDITOR /etc/hotplug/attachIn this file we will log the device class and name:#!/bin/sh DEVCLASS=$1 DEVNAME=$2 # log attach event logger -t hotplug "$DEVCLASS:$DEVNAME attached"To see this in action in another terminal type$ tail -f /var/log/messagesThen connect a USB device to your machine and you should see messages tagged ‘hotplug’. This is what I get when I plug in my Logitech USB adapter for my wireless mouse (which I usually don’t use):Jan 11 11:48:32 x1 hotplug: 0:uhid3 attached Jan 11 11:48:32 x1 hotplug: 5:wsmouse2 attached Jan 11 11:48:32 x1 hotplug: 0:ums0 attached Jan 11 11:48:32 x1 hotplug: 0:uhid1 attached Jan 11 11:48:32 x1 hotplug: 5:wskbd1 attached Jan 11 11:48:32 x1 hotplug: 0:uhid0 attached Jan 11 11:48:32 x1 hotplug: 0:uhid4 attached Jan 11 11:48:32 x1 hotplug: 0:uhid2 attached Jan 11 11:48:32 x1 hotplug: 0:uhidev1 attached Jan 11 11:48:32 x1 hotplug: 0:uhidev2 attached Jan 11 11:48:32 x1 hotplug: 0:ukbd0 attached Jan 11 11:48:32 x1 hotplug: 0:uhidev0 attached Jan 11 11:48:32 x1 hotplug: 0:uhid5 attached Jan 11 11:48:32 x1 hotplug: 0:uhid6 attachedSite note: What is happening here? Why have so many events popped up after inserting one USB device? My theory is that because it’s aUnifying Receiver, it allows more than one Logitech HID to be connected to a single receiver, so it must register a bunch of HIDs to the kernel.The ‘kill’ partNow that we’ve seen howhotplugdworks, we can work on thekillpart ofusbkill.We want to shutdown the machine on a device attach or detach event, but we also want to be able to arm and disarm thekillpart, since I might need to plug something in once in a while. Make the/etc/hotplug/attachscript as so:#!/bin/sh arm_file=/tmp/arm_usbkill DEVCLASS="$1" DEVNAME="$2" logger -t "${0##*/}" "${DEVCLASS}:${DEVNAME} attached" if [ -f "$arm_file" ]; then shutdown -p now else logger -t "${0##*/}" "unarmed - aborted shutdown" fiIf the/tmp/arm_usbkillfile exists then the machine will shutdown, if it doesn’t exist it will just add a log entry to syslog.hotplugalso supports running a different script,/etc/hotplug/detachon detach events. Since both scripts are exactly the same I’ve symlinked the attach script to the location of the detach script.# ln -s /etc/hotplug/attach /etc/hotplug/detachThe${0##*/}logger tag gets substituted to the filename of the script being executed (in this case it is eitherattachordetach).One thing to note is that this setup will execute the shutdown command onanydevice change event. This includes USBs but also includes network devices, disk drives, and serial line interfaces1. If that is a problem, you can implement a device class-based whitelist by checking$DEVCLASS:#!/bin/sh # class whitelist (space-separated) class_whitelist="0 2 3 5" # arm file arm_file=/tmp/arm_usbkill DEVCLASS="$1" DEVNAME="$2" whitelisted() { for class in $class_whitelist; do if [ "$class" = "$1" ]; then return 0 fi done return 1 } logger -t "${0##*/}" "${DEVCLASS}:${DEVNAME} attached" if [ -f "$arm_file" ]; then if whitelisted "$DEVCLASS"; then logger -t "${0##*/}" "whitelisted - aborted shutdown" exit 0 fi shutdown -p now else logger -t "${0##*/}" "unarmed - aborted shutdown" fiBut this is not really useful to me since I use a laptop and I’m not attaching and detaching network devices or disk drives.One disadvantage of this setup is the inability to whitelist devices based on their USB IDs like you can withusbkill. This could be acheived through a much more complicated script usingusbdevsto get USB IDs, but as of yet I have no need for that.Arming and disarmingTo arm and disarm this script all you have to do is create or remove the$arm_filerespectively. Here are some shell functions to add to your shell rc to make it easier:# arm/disarm usbkill arm() { touch /tmp/arm_usbkill && printf 'armed\\n' || printf 'error arming\\n' } disarm() { rm -f /tmp/arm_usbkill && printf 'disarmed\\n' || printf 'error disarming\\n' }The script can be armed or disarmed by any regular user which may or may not be preferable to you (and isn’t the case forusbkill, which requires root to run).Originally I had added theuchgflag to the file to lock it. But this proved to be counterproductive since it wasn’t cleared from/tmpon reboot and whenhotplugdwould first start up, it would immediately shutdown the machine again. That was fun to fix (not).Why?So why do all this? Why not justpkg_add usbutils, download + runusbkilland be done?Well for starters that isn’t as fun. The main reason is that all this works in a default OpenBSD install - no additional packages needed. Why install a program to solve a problem when the default tools and services can solve the problem just as (if not more) elegantly?SEE ALSOUsbkill the OpenBSD Way • 2021-01-11