Skip to content

Commit

Permalink
slirp: avoid use-after-free in slirp_pollfds_poll() if soread() retur…
Browse files Browse the repository at this point in the history
…ns 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>
  • Loading branch information
Steven Luo authored and sthibaul committed Apr 7, 2016
1 parent b5ab677 commit bfb1ac1
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 8 deletions.
12 changes: 11 additions & 1 deletion slirp/slirp.c
Expand Up @@ -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
Expand All @@ -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;
}
}

/*
Expand Down
17 changes: 11 additions & 6 deletions slirp/socket.c
Expand Up @@ -260,10 +260,11 @@ int soreadbuf(struct socket *so, const char *buf, int size)
* 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);
Expand All @@ -276,11 +277,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;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion slirp/socket.h
Expand Up @@ -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 *);
Expand Down

0 comments on commit bfb1ac1

Please sign in to comment.