Release mbuf(9) chain with a simple m_freem(9) loop in sorflush().
authormvs <mvs@openbsd.org>
Thu, 18 Feb 2021 11:40:19 +0000 (11:40 +0000)
committermvs <mvs@openbsd.org>
Thu, 18 Feb 2021 11:40:19 +0000 (11:40 +0000)
Passing local copy of socket to sbrelease() is too complicated to just
free receive buffer. We don't allocate large object on the stack. Also
we don't pass unlocked socket to soassertlocked() within sbdrop(). This
was not triggered because we lock the whole layer with one lock.

Also sorflush() is now private to kern/uipc_socket.c, so it's definition
was made to be in accordance.

ok claudio@ mpi@

sys/kern/uipc_socket.c
sys/sys/socketvar.h

index b629ba7..71f2a49 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket.c,v 1.254 2021/01/17 05:23:34 visa Exp $  */
+/*     $OpenBSD: uipc_socket.c,v 1.255 2021/02/18 11:40:19 mvs Exp $   */
 /*     $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $        */
 
 /*
@@ -66,6 +66,7 @@ void  sotask(void *);
 void   soreaper(void *);
 void   soput(void *);
 int    somove(struct socket *, int);
+void   sorflush(struct socket *);
 
 void   filt_sordetach(struct knote *kn);
 int    filt_soread(struct knote *kn, long hint);
@@ -1116,8 +1117,8 @@ void
 sorflush(struct socket *so)
 {
        struct sockbuf *sb = &so->so_rcv;
+       struct mbuf *m;
        const struct protosw *pr = so->so_proto;
-       struct socket aso;
        int error;
 
        sb->sb_flags |= SB_NOINTR;
@@ -1126,14 +1127,14 @@ sorflush(struct socket *so)
        KASSERT(error == 0);
        socantrcvmore(so);
        sbunlock(so, sb);
-       aso.so_proto = pr;
-       aso.so_rcv = *sb;
+       m = sb->sb_mb;
        memset(&sb->sb_startzero, 0,
             (caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero);
        sb->sb_timeo_nsecs = INFSLP;
        if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
-               (*pr->pr_domain->dom_dispose)(aso.so_rcv.sb_mb);
-       sbrelease(&aso, &aso.so_rcv);
+               (*pr->pr_domain->dom_dispose)(m);
+       while (m != NULL)
+               m = m_freem(m);
 }
 
 #ifdef SOCKET_SPLICE
index c5c1b44..9f6f248 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: socketvar.h,v 1.92 2021/01/17 05:23:34 visa Exp $     */
+/*     $OpenBSD: socketvar.h,v 1.93 2021/02/18 11:40:20 mvs Exp $      */
 /*     $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $  */
 
 /*-
@@ -325,7 +325,6 @@ int soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio,
            struct mbuf **mp0, struct mbuf **controlp, int *flagsp,
            socklen_t controllen);
 int    soreserve(struct socket *so, u_long sndcc, u_long rcvcc);
-void   sorflush(struct socket *so);
 int    sosend(struct socket *so, struct mbuf *addr, struct uio *uio,
            struct mbuf *top, struct mbuf *control, int flags);
 int    sosetopt(struct socket *so, int level, int optname, struct mbuf *m);