usbguard stops responding when recvmsg receives ENOBUFS
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
usbguard |
New
|
Unknown
|
|||
usbguard (Ubuntu) |
Fix Released
|
Undecided
|
Unassigned | ||
Focal |
Fix Committed
|
Medium
|
Heitor Alves de Siqueira |
Bug Description
[Impact]
usbguard-daemon will no longer process device events until restarted
[Test Plan]
1. Spin up a Focal VM with usbguard enabled
2. Run the script below:
while /bin/true ; do
sudo udevadm control --reload-rules
sudo udevadm trigger
sudo udevadm settle --timeout=3
done
3. journald logs will indicate the following errors:
usbguard-
usbguard-
[Where problems could occur]
The fix introduces an additional check in the usbguard event handler, so we should properly test this path. Potential regressions could cause USB devices to not be probed correctly, or usbguard dropping device events. We should also make sure the usbguard daemon is recovering from ENOBUFS and other errors correctly without needing to be restarted.
[Other Info]
The fix has been introduced upstream in version usbguard-0.7.7:
$ git describe --contains 5f297079b843
usbguard-0.7.7~2
As such, releases starting with Jammy already contain the fix:
$ rmadison usbguard
usbguard | 0.7.2+ds-1 | bionic/universe | source, amd64, arm64, armhf, i386, ppc64el, s390x
usbguard | 0.7.6+ds-1build1 | focal/universe | source, amd64, arm64, armhf, ppc64el, riscv64, s390x
usbguard | 1.1.1+ds-3 | jammy/universe | source, amd64, arm64, armhf, ppc64el, riscv64, s390x
usbguard | 1.1.2+ds-4 | mantic/universe | source, amd64, arm64, armhf, ppc64el, riscv64, s390x
usbguard | 1.1.2+ds-6 | noble/universe | source, amd64, arm64, armhf, ppc64el, riscv64, s390x
--
[Original description]
With 0.7.4+ds-1 from 19.10, usbguard may stop responding to events when recvmsg fails with ENOBUFS. To reproduce:
while /bin/true ; do
sudo udevadm control --reload-rules
sudo udevadm trigger
sudo udevadm settle --timeout=3
done
Eventually, this pops out in the journald logs:
usbguard-
usbguard-
and usbguard will no longer process events until restarted (sudo systemctl restart usbguard).
I then installed usbguard 0.7.5 from the desktop team's PPA[1], ran the loop and saw the equivalent error pop out:
usbguard-
usbguard-
This is coming from https:/
#ifdef ENOBUFS
/*
TRANS The kernel's buffers for I/O operations are all in use. In GNU, this
TRANS error is always synonymous with @code{ENOMEM}; you may get one or the
TRANS other from network operations. */
[ERR_REMAP (ENOBUFS)] = N_("No buffer space available"),
It seems that usbguard should be able to handle transient ENOBUFS scenarios with uevent storms and recover when the kernel's buffers are back in order. In my testing, I treated ENOBUFS similarly to EAGAIN/EWOULDBLOCK by logging a warning and simply returning[2]:
usbguard-
It appears usbguard continues to function (eg, if I do the loop for a long time, usbguard remains responsive and processes other uevents, but I'm not sure this is the correct approach since, for example, UEventDeviceMan
[1]https:/
[2]exploratory patch (do not commit in Ubuntu without upstream confirmation)
Index: usbguard-
=======
--- usbguard-
+++ usbguard-
@@ -468,6 +468,12 @@ namespace usbguard
<< "reading from uevent source would block thread execution";
return;
}
+ else if (saved_errno == ENOBUFS) {
+ USBGUARD_LOG(Error) << "ueventProcessRead: "
+ << "failed to read pending uevent (returning): "
+ << "rc=" << rc << " errno=" << saved_errno;
+ return;
+ }
else {
<< "failed to read pending uevent: "
description: | updated |
Changed in usbguard (Ubuntu): | |
status: | New → Confirmed |
Changed in usbguard: | |
status: | Unknown → New |
Changed in usbguard (Ubuntu Focal): | |
importance: | Undecided → Medium |
status: | New → In Progress |
assignee: | nobody → Heitor Alves de Siqueira (halves) |
description: | updated |
FYI, IMHO, this bug needs to be fixed as part of the MIR process in bug #1816548.