Linux: add a 2 second read timeout for USB HID#360
Open
micolous wants to merge 1 commit into
Open
Conversation
b2f9993 to
9bc5797
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a 2 second
read()timeout for USB HID on Linux.Potentially fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1958831
Background
There are a few projects which extend Firefox/
authenticator-rs' CTAP2 transport support by usinguhid(and similar) to simulate a USB HID authenticator and proxying commands (eg: BTLE, PC/SC, TPM).Unfortunately, some of these transports are slower and less reliable than USB, and simulated devices may not even send
CTAPHID_KEEPALIVEas frequently as suggested by the spec (100 ms). Sometimes they stop responding entirely, rather than reporting an error. A misbehaving device can cause an application using this library to hang, potentially indefinitely.I've written a tester for Linux which looks like a USB HID authenticator but never responds sends any replies (or always replies with
CTAPHID_KEEPALIVE), which causesauthenticator_rsand (current) Firefox to hang: https://github.com/micolous/webauthn-toys/tree/main/fido_tarpitWhile
authenticator-rshas a ~20 second timeout where the device will be "removed", the slowread()won't ever be interrupted, and it won't proceed to send further commands to a working authenticator. In Firefox, the browser just entirely stops responding after a WebAuthn request.In this PR
This PR applies a 2 second timeout on all USB HID reads on Linux by
poll()ing before eachread()(ie: 20x recommended time). Authenticators can still respond withCTAPHID_KEEPALIVEbefore this timeout, and get extra time.Applications can still pass a
keep_aliveparameter to impose further deadlines on some requests, and interrupt unreasonably slow authenticators.I tested this against about a dozen USB HID U2F and FIDO2 authenticators from many vendors, and they all easily meet the timeout.
Not addressed by this PR
An authenticator can still stall indefinitely by sending
CTAPHID_KEEPALIVEin response toCTAPHID_INIT(which isn't allowed by the spec) or aCTAPHID_CBORauthenticatorGetInforequest, and trigger lock-ups.I started investigating solutions in https://github.com/micolous/authenticator-rs/tree/ctap2/1958831-ignore-unexpected-timeouts, but that will require more invasive changes across all platforms (as it would require all requests become cancellable).
Only macOS applies any timeout on
read(). Other platforms may wish to consider similar changes, but testing these is hard :)Potential breakages
This PR will potentially break really slow (physical and virtual) devices. As noted above, these do not meet the CTAP specification's recommendations.
Virtual devices with slow transports should attempt to send and cache an
authenticatorGetInforequest on application start-up or user activity (wake/unlock screen), and only present a virtual device when the transport is actually usable. They must also return an error on transport-level errors or timeouts.authenticator-rswill discover new devices that become present during a registration/authentication ceremony, so a virtual device doesn't have to be present at all times if it is the only FIDO USB HID.