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>
This commit is contained in:
parent
b5ab677189
commit
bfb1ac1402
|
@ -534,7 +534,12 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
|
||||||
* test for G_IO_IN below if this succeeds
|
* test for G_IO_IN below if this succeeds
|
||||||
*/
|
*/
|
||||||
if (revents & G_IO_PRI) {
|
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
|
* Check sockets for reading
|
||||||
|
@ -553,6 +558,11 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
tcp_output(sototcpcb(so));
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -260,10 +260,11 @@ err:
|
||||||
* so when OOB data arrives, we soread() it and everything
|
* so when OOB data arrives, we soread() it and everything
|
||||||
* in the send buffer is sent as urgent data
|
* in the send buffer is sent as urgent data
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
sorecvoob(struct socket *so)
|
sorecvoob(struct socket *so)
|
||||||
{
|
{
|
||||||
struct tcpcb *tp = sototcpcb(so);
|
struct tcpcb *tp = sototcpcb(so);
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUG_CALL("sorecvoob");
|
DEBUG_CALL("sorecvoob");
|
||||||
DEBUG_ARG("so = %p", so);
|
DEBUG_ARG("so = %p", so);
|
||||||
|
@ -276,11 +277,15 @@ sorecvoob(struct socket *so)
|
||||||
* urgent data, or the read() doesn't return all the
|
* urgent data, or the read() doesn't return all the
|
||||||
* urgent data.
|
* urgent data.
|
||||||
*/
|
*/
|
||||||
soread(so);
|
ret = soread(so);
|
||||||
|
if (ret > 0) {
|
||||||
tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
|
tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
|
||||||
tp->t_force = 1;
|
tp->t_force = 1;
|
||||||
tcp_output(tp);
|
tcp_output(tp);
|
||||||
tp->t_force = 0;
|
tp->t_force = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -127,7 +127,7 @@ struct socket *solookup(struct socket **, struct socket *,
|
||||||
struct socket *socreate(Slirp *);
|
struct socket *socreate(Slirp *);
|
||||||
void sofree(struct socket *);
|
void sofree(struct socket *);
|
||||||
int soread(struct socket *);
|
int soread(struct socket *);
|
||||||
void sorecvoob(struct socket *);
|
int sorecvoob(struct socket *);
|
||||||
int sosendoob(struct socket *);
|
int sosendoob(struct socket *);
|
||||||
int sowrite(struct socket *);
|
int sowrite(struct socket *);
|
||||||
void sorecvfrom(struct socket *);
|
void sorecvfrom(struct socket *);
|
||||||
|
|
Loading…
Reference in New Issue