diff options
author | Daniel Stenberg <daniel@haxx.se> | 2023-02-19 11:03:21 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2023-02-20 08:11:49 +0100 |
commit | a6506f266c386f5c3229e414b36546ace97003cc (patch) | |
tree | 0cca5fbba5df7cddcdaf4aeb62b6d764b33b39dd /lib | |
parent | 41dfb7f516c8a9659782df695528c9d32b5653d6 (diff) | |
download | curl-a6506f266c386f5c3229e414b36546ace97003cc.tar.gz |
socketpair: allow EWOULDBLOCK when reading the pair check bytes
Reported-by: Gunamoi Software
Co-authored-by: Jay Satiro
Fixes #10561
Closes #10562
Diffstat (limited to 'lib')
-rw-r--r-- | lib/socketpair.c | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/lib/socketpair.c b/lib/socketpair.c index f814146ad..b94c9843e 100644 --- a/lib/socketpair.c +++ b/lib/socketpair.c @@ -85,9 +85,22 @@ int Curl_socketpair(int domain, int type, int protocol, socks[0] = socks[1] = CURL_SOCKET_BAD; +#if defined(WIN32) || defined(__CYGWIN__) + /* don't set SO_REUSEADDR on Windows */ + (void)reuse; +#ifdef SO_EXCLUSIVEADDRUSE + { + int exclusive = 1; + if(setsockopt(listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, + (char *)&exclusive, (curl_socklen_t)sizeof(exclusive)) == -1) + goto error; + } +#endif +#else if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, (curl_socklen_t)sizeof(reuse)) == -1) goto error; +#endif if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1) goto error; if(getsockname(listener, &a.addr, &addrlen) == -1 || @@ -113,14 +126,52 @@ int Curl_socketpair(int domain, int type, int protocol, goto error; else { struct curltime check; - struct curltime now = Curl_now(); + struct curltime start = Curl_now(); + char *p = (char *)✓ + size_t s = sizeof(check); /* write data to the socket */ - swrite(socks[0], &now, sizeof(now)); + swrite(socks[0], &start, sizeof(start)); /* verify that we read the correct data */ - if((sizeof(now) != sread(socks[1], &check, sizeof(check)) || - memcmp(&now, &check, sizeof(check)))) - goto error; + do { + ssize_t nread; + + pfd[0].fd = socks[1]; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + (void)Curl_poll(pfd, 1, 1000); /* one second */ + + nread = sread(socks[1], p, s); + if(nread == -1) { + int sockerr = SOCKERRNO; + /* Don't block forever */ + if(Curl_timediff(Curl_now(), start) > (60 * 1000)) + goto error; + if( +#ifdef WSAEWOULDBLOCK + /* This is how Windows does it */ + (WSAEWOULDBLOCK == sockerr) +#else + /* errno may be EWOULDBLOCK or on some systems EAGAIN when it + returned due to its inability to send off data without + blocking. We therefore treat both error codes the same here */ + (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) || + (EINTR == sockerr) || (EINPROGRESS == sockerr) +#endif + ) { + continue; + } + goto error; + } + s -= nread; + if(s) { + p += nread; + continue; + } + if(memcmp(&start, &check, sizeof(check))) + goto error; + break; + } while(1); } sclose(listener); |