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

Queue macOS input reports so that large responses aren't dropped #84

Merged
merged 2 commits into from
May 15, 2024

Conversation

GregDomzalski
Copy link
Contributor

Description

This has been a longstanding bug in the SDK that has been haunting me since the FIDO device code was originally written. Apple's documentation on how async input reports are intended to work are about as clear as mud. But with some extra (temporary) debug logging I was able to finally reproduce the issue with enough visibility into what was actually happening. The implementation used by our own libfido2 library now makes a lot more sense as well.

Fundamentally, we were just using the IOHIDDeviceRegisterInputReportCallback and its corresponding callback incorrectly. The read buffer that we supply during the registration is just meant to be a place for macOS to cache the report data... I guess? The intended use still is not super clear to me.

But what was clear from the logs is that the report callback was getting called faster than we were calling GetReport to read said reports. And since we previously did not queue up any of the reports until they were read, it resulted in reports either getting dropped, or arriving before we ran the IO runloop. That would usually result in the CFRunLoopRunInMode call inside of GetReport to timeout. Not because the YubiKey was taking a long time, but because the report already came and went and we missed it.

So now, we pass a ConcurrentQueue into the native callback via a GCHandle. We queue the report that we see in the callback so that when GetReport is eventually called, we will have the report. We first attempt to read straight from the queue, and if there's nothing there, we run the runloop which should then cause macOS to read from the YubiKey. This behavior now much more closely matches libfido2.

Fixes (internal issue)

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

How has this been tested?

Ran some local FIDO2 tests as well as real-world use cases using our internally dependent software.

Test configuration:

  • Firmware version: 5.4.3
  • Yubikey model: YK5 ANFC

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have run dotnet format to format my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@GregDomzalski GregDomzalski requested a review from DennisDyallo May 8, 2024 00:07
@DennisDyallo DennisDyallo added the bug Something isn't working label May 8, 2024
Copy link
Collaborator

@DennisDyallo DennisDyallo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

if (_readHandle.IsAllocated)
{
_readHandle.Free();
}

if (_pinnedReportsQueue.IsAllocated)
{
_pinnedReportsQueue.Free();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Base automatically changed from bugfix/add-compat-flag-for-exclusivity to develop May 8, 2024 16:43
This addresses a bug where if a YubiKey command would result in multiple input reports being generated, we would get the callbacks but drop the results on the floor. This would generally result in the runloop timing out because we already had received the report via the callback but had no way of caching it.
@GregDomzalski GregDomzalski force-pushed the bugfix/macos-hid-callbacks branch from b8eefbc to 06edf90 Compare May 9, 2024 18:07
Copy link

github-actions bot commented May 9, 2024

Test Results: Windows

    2 files      2 suites   2s ⏱️
3 615 tests 3 615 ✅ 0 💤 0 ❌
3 617 runs  3 617 ✅ 0 💤 0 ❌

Results for commit 5c10887.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented May 9, 2024

Test Results: Ubuntu

    2 files      2 suites   5s ⏱️
3 607 tests 3 607 ✅ 0 💤 0 ❌
3 609 runs  3 609 ✅ 0 💤 0 ❌

Results for commit 5c10887.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented May 9, 2024

Test Results: MacOS

    2 files      2 suites   1s ⏱️
3 607 tests 3 607 ✅ 0 💤 0 ❌
3 609 runs  3 609 ✅ 0 💤 0 ❌

Results for commit 5c10887.

♻️ This comment has been updated with latest results.

Copy link

Code Coverage

Package Line Rate Branch Rate Complexity Health
Yubico.Core 42% 31% 4257
Yubico.YubiKey 51% 47% 18417
Summary 49% (31675 / 64317) 45% (8017 / 17979) 22674

Minimum allowed line rate is 40%

Copy link
Collaborator

@DennisDyallo DennisDyallo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@GregDomzalski GregDomzalski merged commit 5c10887 into develop May 15, 2024
22 checks passed
@GregDomzalski GregDomzalski deleted the bugfix/macos-hid-callbacks branch May 15, 2024 23:11
@DennisDyallo DennisDyallo mentioned this pull request Jun 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

Successfully merging this pull request may close these issues.

2 participants