diff options
author | Steven Luo <steven+qemu@steven676.net> | 2016-04-06 22:04:32 -0700 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2016-04-07 10:27:42 +0200 |
commit | cbe476c8f001e1757c8fcd7f49ee7b51caf4e0da (patch) | |
tree | 18699161edb6f053197e355f3dc1dd3e9e8ce1ea | |
parent | 804f441a9d6998a57040bf36685a17a6436b2ea8 (diff) | |
download | slirp-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.c | 12 | ||||
-rw-r--r-- | socket.c | 17 | ||||
-rw-r--r-- | socket.h | 2 |
3 files changed, 23 insertions, 8 deletions
@@ -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; + } } /* @@ -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; } /* @@ -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 *); |