diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-04-07 12:15:33 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-04-07 12:15:33 +0100 |
commit | e380023898479b57d38c0569c02f7bd41090181b (patch) | |
tree | 69074146889b2d4d05d871fde0fbfd43c63c383d | |
parent | 0f9d6bd210f21e5f8f80be51996f397536520f40 (diff) | |
parent | 6625d83a6eb3b51a622d72adce713cab75cbf2e7 (diff) |
Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging
slirp updates
# gpg: Signature made Thu 07 Apr 2016 12:02:23 BST using RSA key ID FB6B2F1D
# gpg: Good signature from "Samuel Thibault <samuel.thibault@gnu.org>"
# gpg: aka "Samuel Thibault <sthibault@debian.org>"
# gpg: aka "Samuel Thibault <samuel.thibault@inria.fr>"
# gpg: aka "Samuel Thibault <samuel.thibault@labri.fr>"
# gpg: aka "Samuel Thibault <samuel.thibault@ens-lyon.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 900C B024 B679 31D4 0F82 304B D017 8C76 7D06 9EE6
# Subkey fingerprint: F632 74CD C630 0873 CB3D 29D9 E3E5 1CE8 FB6B 2F1D
* remotes/thibault/tags/samuel-thibault:
slirp: handle deferred ECONNREFUSED on non-blocking TCP sockets
slirp: Propagate host TCP RST to the guest.
slirp: avoid use-after-free in slirp_pollfds_poll() if soread() returns an error
slirp: don't crash when tcp_sockclosed() is called with a NULL tp
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | slirp/slirp.c | 12 | ||||
-rw-r--r-- | slirp/socket.c | 34 | ||||
-rw-r--r-- | slirp/socket.h | 2 | ||||
-rw-r--r-- | slirp/tcp_input.c | 6 | ||||
-rw-r--r-- | slirp/tcp_subr.c | 7 |
5 files changed, 50 insertions, 11 deletions
diff --git a/slirp/slirp.c b/slirp/slirp.c index fef526c5ad..9f4bea3d3b 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -534,7 +534,12 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) * test for G_IO_IN below if this succeeds */ if (revents & G_IO_PRI) { - sorecvoob(so); + ret = sorecvoob(so); + if (ret < 0) { + /* Socket error might have resulted in the socket being + * removed, do not try to do anything more with it. */ + continue; + } } /* * Check sockets for reading @@ -553,6 +558,11 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) if (ret > 0) { tcp_output(sototcpcb(so)); } + if (ret < 0) { + /* Socket error might have resulted in the socket being + * removed, do not try to do anything more with it. */ + continue; + } } /* diff --git a/slirp/socket.c b/slirp/socket.c index b836c42b8e..bd97b2d682 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -176,9 +176,24 @@ soread(struct socket *so) if (nn < 0 && (errno == EINTR || errno == EAGAIN)) return 0; else { + int err; + socklen_t slen = sizeof err; + + err = errno; + if (nn == 0) { + getsockopt(so->s, SOL_SOCKET, SO_ERROR, + &err, &slen); + } + DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); sofcantrcvmore(so); - tcp_sockclosed(sototcpcb(so)); + + if (err == ECONNRESET || err == ECONNREFUSED + || err == ENOTCONN || err == EPIPE) { + tcp_drop(sototcpcb(so), err); + } else { + tcp_sockclosed(sototcpcb(so)); + } return -1; } } @@ -260,10 +275,11 @@ err: * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data */ -void +int sorecvoob(struct socket *so) { struct tcpcb *tp = sototcpcb(so); + int ret; DEBUG_CALL("sorecvoob"); DEBUG_ARG("so = %p", so); @@ -276,11 +292,15 @@ sorecvoob(struct socket *so) * urgent data, or the read() doesn't return all the * urgent data. */ - soread(so); - tp->snd_up = tp->snd_una + so->so_snd.sb_cc; - tp->t_force = 1; - tcp_output(tp); - tp->t_force = 0; + ret = soread(so); + if (ret > 0) { + tp->snd_up = tp->snd_una + so->so_snd.sb_cc; + tp->t_force = 1; + tcp_output(tp); + tp->t_force = 0; + } + + return ret; } /* diff --git a/slirp/socket.h b/slirp/socket.h index e9c9b053dc..7dca506973 100644 --- a/slirp/socket.h +++ b/slirp/socket.h @@ -127,7 +127,7 @@ struct socket *solookup(struct socket **, struct socket *, struct socket *socreate(Slirp *); void sofree(struct socket *); int soread(struct socket *); -void sorecvoob(struct socket *); +int sorecvoob(struct socket *); int sosendoob(struct socket *); int sowrite(struct socket *); void sorecvfrom(struct socket *); diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 1fcca3040e..5433e7fe9c 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -725,6 +725,12 @@ findso: so->so_ti = ti; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; tp->t_state = TCPS_SYN_RECEIVED; + /* + * Initialize receive sequence numbers now so that we can send a + * valid RST if the remote end rejects our connection. + */ + tp->irs = ti->ti_seq; + tcp_rcvseqinit(tp); tcp_template(tp); } return; diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index dbfd2c673b..32ff452e93 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -356,6 +356,10 @@ tcp_sockclosed(struct tcpcb *tp) DEBUG_CALL("tcp_sockclosed"); DEBUG_ARG("tp = %p", tp); + if (!tp) { + return; + } + switch (tp->t_state) { case TCPS_CLOSED: @@ -374,8 +378,7 @@ tcp_sockclosed(struct tcpcb *tp) tp->t_state = TCPS_LAST_ACK; break; } - if (tp) - tcp_output(tp); + tcp_output(tp); } /* |