bugfix: Handle zero-len packets from ADB to avoid BSOD #602
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.
This PR addresses BSOD issue while using ADB, but also other with tools as reported in #248 (comment)
The code change is small but diagnosing the issue was a substantial effort.
Here is the analysis:
Hyper-V VM with Debian 11 (unstable) guest
Host: Windows 10 (Version 10.0.19045 Build 19045)
ADB for Android Nougat
Custom ADB device
ADB tool that I’ve used to reproduce the issue was an older version e.g. from Android Nougat
In this version of the tool data is sent in chunks of size 256k.
Dimitar Stankov provided me with custom build of this ADB version with reduced chunk size of 16k,
because I’ve suspected that chunk size goes beyond VboxUSB limits. Chunk size turned out not to be the case eventually.
Dimitar supported me also with enabling ADB trace logging and also added some prints in the custom-built version.
In the logs I’ve noticed a pattern
So here it’s observable that after every chunk of 16k data, there is a chunk with 0 len of data.
Looking at ADB source code I found the following:
https://android.googlesource.com/platform/system/core/+/refs/heads/nougat-release/adb/usb_linux.cpp
Here the interesting part is sending “zero-markers”. It turned out that for older version(s) of adb tool and adb protocol
these zero-markers are required to signify the end of a bulk transfer, so the recipient device to know. In my case
these makers are sent, as I’ve observed in the adb traces. And here is where the problem stars.
In usbipd-win implementation when a zero-length packet is received, a zero length buffer (var buf) is created.
Also later on a valid gcHandle pointer is created and set to urb.buf property. After that this URB is passed to
VboxUSB driver.
In VboxUSB during initialization of internal structures a urb.buf (non-null) with length 0 is passed to IoAllocateMdl.
In file src/VBox/HostDrivers/VBoxUSB/win/dev/VBoxUsbRt.cpp
Unfortunately IoAllocateMdl returns non-null pointer in this case, which is kind of undefined behavior.
Everything after this call passes as if it was a valid URB passed to VboxUSB.
OnCompletion follows after some time and then BSOD happens during freeing pointer returned by IoAllocateMdl.
Actually similar issue was reported some time ago here: https://learn.microsoft.com/en-us/answers/questions/1167623/ioallocatemdl-bug
Google search the function IoAllocateMdl also resulted in reports of similar BSOD cases with IoAllocateMdl from year 2005.
At the end fixing this undesirable code path is just by setting null pointer to urb.buf in C# code.
This is the long story short. Acknowledgements to Dimitar Stankov [email protected] for his support during investigation of the issue.
Related issues: #461 #410 #248