connect() hangs on a listen()ing AF_UNIX socket
Corinna Vinschen
corinna-cygwin@cygwin.com
Fri Aug 22 20:16:00 GMT 2014
On Aug 22 20:32, Christian Franke wrote:
> Corinna Vinschen wrote:
> >On Aug 21 21:14, Christian Franke wrote:
> >>Easier and may work for Postfix: Add a Cygwin specific socket option like
> >>SO_DONT_NEED_PEERCRED which is set immediately after Postfix calls
> >>socket(AF_UNIX, SOCK_STREAM). If set, no handshake occurs on
> >>connect()/accept(). getpeerid()/SO_PEERCRED should fail then.
> >Well, it's not *only* SO_PEERCRED. Another, the older part of the
> >handshake, is about recognizing the peer. Since AF_UNIX sockets don't
> >exist on Windows, Cygwin is using AF_INET sockets under the hood, and
> >so *any* Windows process could accidentally connect to a Cygwin AF_UNIX
> >socket. The handshake also aims to avoid this scenario. Only if the
> >handshake worked, the peers can be sure to talk to another Cygwin
> >process assuming an AF_UNIX socket.
> >
> >A Cygwin-specific socket option which switches off the handshake would
> >disallow this peer recognition. How bad is that? I'm not sure.
>
> Good question.
>
> >Another potential solution might be to defer the AF_UNIX handshake to
> >the first send/recv:
> >
> >Whatever the peers do, there is a certain protocol used. That means,
> >there's an implicit understanding who's going to do the first send and
> >who's doing the first recv. So, after connect/accept, both sides of the
> >sockets go into "connected_but_handshake_missing" mode. On the first
> >send/recv, the handshake gets started and if it fails, send/recv
> >return ECONNRESET.
>
> Is an actual handshake really required? It would possibly be sufficient that
> each peer sends its secret+credential and then expects a correct
> secret+credential from the other peer before sending anything.
>
> After actual connect()/accept():
>
> send our secret+cred (should not block due to TCP queuing).
So both peers send their credentials...
> if (! nonblocking recv peer secret+cred)
> set_state(connected_but_secret_missing)
> else
> set_state(connected)
This will almost always result in connected_but_secret_missing. It's
probably ok to drop the recv attempt here entirely.
> Before actual send()/recv()/getpeerid():
>
> if (state == connected_but_secret_missing) {
> if (! recv peer secret+cred)
> abort_connection(ECONNRESET)
> else
> set_state(connected)
> }
Sounds like a nice idea. We should try that. I'm just not sure how
much time I have left to work on this before my vaca next month. Do you
have fun to look into that? We have waited so long for postfix, I guess
a couple more weeks won't really hurt.
Otherwise the easy solution you suggested before would be rather quickly
implemented...
> AFAICS this should provide the behavior required for postfix: client
> connect() succeeds before server accept().
> It adds the following unusual behavior: client send() and getpeereid() wait
> for server accept().
Same with recv. Well, that might be unusual, but in most cases send
recv and getpeereid will be called after a connect/accept. It's as
much a trade-off as the connect/accept requirement today. As a resort
we'd still have the "easy" solution removing the credential exchange
entirely.
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin/attachments/20140822/193fd0f7/attachment.sig>
More information about the Cygwin
mailing list