Thanks to visit codestin.com
Credit goes to github.com

Skip to content

transports: smart: abort on early end of stream #3983

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

Merged
merged 3 commits into from
Nov 14, 2016

Conversation

pks-t
Copy link
Member

@pks-t pks-t commented Nov 1, 2016

I've started playing around with mitmproxy to test our online protocol and was able to force libgit2 into an infinite loop on first try. The issue occurs if we fetch from a remote via the smart protocol if the last flush packet from the remote is modified.

This PR fixes the infinite loop. I'm actually not sure why we only returned an EOF before when flush == 0, I couldn't find any reason here. One thing I could imagine is that we actually wanted to return 0 if the last received packet was actually a flush packet and the socket returned EOF so that we wouldn't produce an error if we received less flushes than expected. But we actually only use the function once and only check if the return code was an error, so we wouldn't handle positive values (e.g. there are outstanding flushes).

Yeah, so I'm quite clueless here. Anyway, the issue obviously requires a fix as it's remotely exploitable, so I'm putting this up for discussion here.

pks-t added 3 commits November 1, 2016 16:55
When reading a server's reference announcements via the smart
protocol, we expect the server to send multiple flushes before
the protocol is finished. If we fail to receive new data from the
socket, we will only return an end of stream error if we have not
seen any flush yet.

This logic is flawed in that we may run into an infinite loop
when receiving a server's reference announcement with a bogus
flush packet. E.g. assume the last flushing package is changed to
not be '0000' but instead any other value. In this case, we will
still await one more flush package and ignore the fact that we
are not receiving any data from the socket, causing an infinite
loop.

Fix the issue by always returning `GIT_EEOF` if the socket
indicates an end of stream.
When trying to receive packets from the remote, we loop until
either an error distinct to `GIT_EBUFS` occurs or until we
successfully parsed the packet. This does not honor the case
where we are looping over an already closed socket which has no
more data, leaving us in an infinite loop if we got a bogus
packet size or if the remote hang up.

Fix the issue by returning `GIT_EEOF` when we cannot read data
from the socket anymore.
@pks-t pks-t force-pushed the pks/smart-early-eof branch from f27997d to 62494bf Compare November 2, 2016 09:11
@pks-t
Copy link
Member Author

pks-t commented Nov 2, 2016

Got another case where we were looping endlessly in search for additional data.

@pks-t
Copy link
Member Author

pks-t commented Nov 7, 2016

Any comments on this PR? I don't feel like just merging it without anybody else having a look at it, but I feel like this PR should be merged due to its possible security implications.

@carlosmn
Copy link
Member

This makes sense. I suspect the code was trying to handle the case where it times out before reading, but we don't actually do that currently, so we should indeed consider a 0 to mean the server doesn't want to talk to us anymore.

@carlosmn carlosmn merged commit cc5966b into libgit2:master Nov 14, 2016
@pks-t pks-t deleted the pks/smart-early-eof branch November 15, 2016 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants