aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Luo <steven+qemu@steven676.net>2016-04-06 22:04:32 -0700
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2016-04-07 10:27:42 +0200
commitcbe476c8f001e1757c8fcd7f49ee7b51caf4e0da (patch)
tree18699161edb6f053197e355f3dc1dd3e9e8ce1ea
parent804f441a9d6998a57040bf36685a17a6436b2ea8 (diff)
downloadslirp-cbe476c8f001e1757c8fcd7f49ee7b51caf4e0da.zip
slirp-cbe476c8f001e1757c8fcd7f49ee7b51caf4e0da.tar.gz
slirp-cbe476c8f001e1757c8fcd7f49ee7b51caf4e0da.tar.bz2
slirp: avoid use-after-free in slirp_pollfds_poll() if soread() returns an error
Samuel Thibault pointed out that it's possible that slirp_pollfds_poll() will try to use a socket even after soread() returns an error, resulting in an use-after-free if the socket was removed while handling the error. Avoid this by refusing to continue to work with the socket in this case. Signed-off-by: Steven Luo <steven+qemu@steven676.net> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
-rw-r--r--slirp.c12
-rw-r--r--socket.c17
-rw-r--r--socket.h2
3 files changed, 23 insertions, 8 deletions
diff --git a/slirp.c b/slirp.c
index f48e119..f7324c8 100644
--- a/slirp.c
+++ b/slirp.c
@@ -530,7 +530,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
@@ -549,6 +554,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/socket.c b/socket.c
index a86ae12..48d6b77 100644
--- a/socket.c
+++ b/socket.c
@@ -261,9 +261,10 @@ err:
* so when OOB data arrives, we soread() it and everything
* in the send buffer is sent as urgent data
*/
-void sorecvoob(struct socket *so)
+int sorecvoob(struct socket *so)
{
struct tcpcb *tp = sototcpcb(so);
+ int ret;
DEBUG_CALL("sorecvoob");
DEBUG_ARG("so = %p", so);
@@ -276,11 +277,15 @@ void 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/socket.h b/socket.h
index dc28728..41b54c8 100644
--- a/socket.h
+++ b/socket.h
@@ -132,7 +132,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 *);