]> git.proxmox.com Git - mirror_qemu.git/commitdiff
slirp: avoid use-after-free in slirp_pollfds_poll() if soread() returns an error
authorSteven Luo <steven+qemu@steven676.net>
Thu, 7 Apr 2016 05:04:32 +0000 (22:04 -0700)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Thu, 7 Apr 2016 08:27:42 +0000 (10:27 +0200)
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>
slirp/slirp.c
slirp/socket.c
slirp/socket.h

index fef526c5ad5f84e773ed00d677003fb7ba181b5a..9f4bea3d3bf6765b81d1b317c9e1f129ea70c957 100644 (file)
@@ -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;
+                    }
                 }
 
                 /*
index b836c42b8e11953930b98e4af45c4544b0c706f7..7f022a676992b72936aa32a7b95f3ceb231ad9c6 100644 (file)
@@ -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,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;
 }
 
 /*
index e9c9b053dcc4bd9f69432417f47ee8c4d9452b3c..7dca5069732465aa100e9c6d799971d7c47aa543 100644 (file)
@@ -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 *);