Commit bfb1ac14 authored by Steven Luo's avatar Steven Luo Committed by Samuel Thibault
Browse files

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: default avatarSteven Luo <steven+qemu@steven676.net>
Signed-off-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
parent b5ab6771
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -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;
                    }
                }

                /*
+11 −6
Original line number Diff line number Diff line
@@ -260,10 +260,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,13 +277,17 @@ sorecvoob(struct socket *so)
	 * urgent data, or the read() doesn't return all the
	 * urgent data.
	 */
	soread(so);
	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;
}

/*
 * Send urgent data
 * There's a lot duplicated code here, but...
+1 −1
Original line number Diff line number Diff line
@@ -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 *);