Permalink
Show file tree
Hide file tree
6 comments
on commit
sign in to comment.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
libvncclient: handle half-open TCP connections
When a connection is not reset properly at the TCP level (e.g. sudden power loss or process crash) the TCP connection becomes half-open and read() always returns -1 with errno = EAGAIN while select() always returns 0. This leads to an infinite loop and can be fixed by closing the connection after a certain number of retries (based on a timeout) has been exceeded.
- Loading branch information
Showing
3 changed files
with
21 additions
and
2 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
5743301There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice some Linux distros are backporting this patch because it fixes CVE-2020-14398. However, this modifies the size of the rfbClient struct, which is public ABI. Accordingly, this patch is not suitable for backport unless dependent packages are rebuilt.
We need to be very careful with libvncserver because it isn't maintaining library soname properly; i.e. different releases of the library with the same soname actually contain ABI changes.
5743301There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mcatanzaro please note that we're (now) very careful to just be adding to the end of the rfbClient struct, not removing members, not adding in between in order to preserver ABI compat. Thus, this patch is indeed suitable for backports.
5743301There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @bk138, since this struct is public and likely to be allocated on the stack, I think you need to remove padding bytes from the end of the struct if you want to avoid breaking the ABI, yes? Unfortunately there is no padding here.
If #420 is implemented, this problem will go away.
5743301There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always (at least that's the API) allocated on the heap, so the "internals" must be at the right place, but it doesn't do harm if it contains more members than expected its end.
Not really, as struct members will still be there?
5743301There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Er... if the entire struct is declared in a public header, how can you guarantee it is always allocated on the heap? Example failure case is:
If the application is compiled against older libvncserver but run against new libvncserver, then boom! you've clobbered whatever is next on the stack.
Now I see that all of your example code uses rfbGetClient() to allocate the rfbClient. Hm, OK, so everything that uses that will all be fine, and I guess realistic applications are supposed to do that? Looking at the implementation of rfbGetClient(), I guess so, since that seems like a lot of work to configure it properly otherwise. But it still violates the normal rules distros expect for ABI stability, and it's probably(?) going to be caught by distro ABI checkers, and will likely result in downstreams refusing to take the patch regardless. So if you want to be able to add new members to a public struct, then please only declare the struct in a header file, and define it only in a source file such that its data members are all private, and provide getter/setter functions for whatever fields need to be accessible. Then there's no question that it's safe.
If the struct members are no longer public (I assume that's what is intended by "sealed") and the struct can no longer be allocated on the stack, then you can change whatever you want whenever you want without breaking ABI. Otherwise, you're going to scare downstreams like me. At least, I fear a struct size change more than I do denial of service.
5743301There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would love to have this. This is more or less what #420 is about.
Sorry for scaring you, not my intention nor the original author's one, I guess. Let me propose #181 as a stop-gap solution.