virtio-devices: stop corrupting vsock commands #7195
Merged
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.
The
read_exact()call was introduced in 82ac114 ("virtio-devices: vsock: handle short read in muxer") to solve a crash when a connection disconnected without sending any data, but it introduced a problem of its own: because the socket is non-blocking,read_exact()may read some data, then returnErrorKind::WouldBlock. In that case, the data it read will be discarded. So for example if it read "CONNECT ", and then nothing else was available to read yet, "CONNECT " would be discarded, and so the next time this function was called, when epoll triggered again for the socket, only the following data would end up incommand.buf, causing an error due to just a port number being an invalid command.Contrary to that commit message, this code was actually designed to handle short reads just fine — in the case of a short read, it stores the data it has read in
command, and returnsError::UnixRead(ErrorKind::WouldBlock), which is ignored by the caller, and the function gets called again when there is more data to read, building upcommandpotentially over the course of several reads. The only thing it didn't handle correctly, as far as I can tell, was a 0-byte read, which happens when a client disconnects from the socket without writing anything. All that's needed to fix this is to avoid an invalid subtraction in that case, so this change reverts 82ac114, fixing the issue with partial commands being discarded, and instead handles the 0-byte read by usingslice::get, and treating an empty command as an incomplete command, which of course it is.