Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/berrange/tags/pull-2017-11-06-2…
Browse files Browse the repository at this point in the history
…' into staging

Pull IO 2017/11/06 v2

# gpg: Signature made Tue 07 Nov 2017 14:35:25 GMT
# gpg:                using RSA key 0xBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>"
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF

* remotes/berrange/tags/pull-2017-11-06-2:
  sockets: avoid leak of listen file descriptor

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Nov 7, 2017
2 parents a4f0537 + 10a7b7e commit 5ca7a3c
Showing 1 changed file with 29 additions and 23 deletions.
52 changes: 29 additions & 23 deletions util/qemu-sockets.c
Expand Up @@ -207,7 +207,7 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
char uaddr[INET6_ADDRSTRLEN+1];
char uport[33];
int rc, port_min, port_max, p;
int slisten = 0;
int slisten = -1;
int saved_errno = 0;
bool socket_created = false;
Error *err = NULL;
Expand Down Expand Up @@ -267,44 +267,50 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
uaddr,INET6_ADDRSTRLEN,uport,32,
NI_NUMERICHOST | NI_NUMERICSERV);

slisten = create_fast_reuse_socket(e);
if (slisten < 0) {
continue;
}

socket_created = true;
port_min = inet_getport(e);
port_max = saddr->has_to ? saddr->to + port_offset : port_min;
for (p = port_min; p <= port_max; p++) {
inet_setport(e, p);
rc = try_bind(slisten, saddr, e);
if (rc) {
if (errno == EADDRINUSE) {

slisten = create_fast_reuse_socket(e);
if (slisten < 0) {
/* First time we expect we might fail to create the socket
* eg if 'e' has AF_INET6 but ipv6 kmod is not loaded.
* Later iterations should always succeed if first iteration
* worked though, so treat that as fatal.
*/
if (p == port_min) {
continue;
} else {
error_setg_errno(errp, errno, "Failed to bind socket");
error_setg_errno(errp, errno,
"Failed to recreate failed listening socket");
goto listen_failed;
}
}
if (!listen(slisten, 1)) {
goto listen_ok;
}
if (errno != EADDRINUSE) {
error_setg_errno(errp, errno, "Failed to listen on socket");
goto listen_failed;
socket_created = true;

rc = try_bind(slisten, saddr, e);
if (rc < 0) {
if (errno != EADDRINUSE) {
error_setg_errno(errp, errno, "Failed to bind socket");
goto listen_failed;
}
} else {
if (!listen(slisten, 1)) {
goto listen_ok;
}
if (errno != EADDRINUSE) {
error_setg_errno(errp, errno, "Failed to listen on socket");
goto listen_failed;
}
}
/* Someone else managed to bind to the same port and beat us
* to listen on it! Socket semantics does not allow us to
* recover from this situation, so we need to recreate the
* socket to allow bind attempts for subsequent ports:
*/
closesocket(slisten);
slisten = create_fast_reuse_socket(e);
if (slisten < 0) {
error_setg_errno(errp, errno,
"Failed to recreate failed listening socket");
goto listen_failed;
}
slisten = -1;
}
}
error_setg_errno(errp, errno,
Expand Down

0 comments on commit 5ca7a3c

Please sign in to comment.