Download raw body.
replace sbmtxassertlocked with MUTEX_ASSERT_LOCKED
On Fri, Feb 14, 2025 at 02:11:32AM +0300, Vitaliy Makkoveev wrote:
> > On 14 Feb 2025, at 01:29, Alexander Bluhm <bluhm@openbsd.org> wrote:
> >
> > Hi,
> >
> > Working on socket buffer protection has been stable for a while.
> > I think it is time to convert this soft failure to mutex assertion.
> > Fail early, fail hard.
> >
> > MUTEX_ASSERT_LOCKED() cannot be used in header file due to missing
> > include dependencies. So I moved sbspace_locked() into .c file.
> > It is not more overhead than before when we called sbmtxassertlocked().
> > I am not a big fan of much code in header inline functions anyway.
> > The implementation is so trivial that I copied it to sbspace().
> >
>
> As you said, sbspace_locked() is trivial, do we really need assertion
> within?
The assertion is not about the trivial code in sbspace_locked(),
but the code that is calling it. And not in all callers it is
obvious that the mutex is held.
On the other hand, there are a lot of locking assertions around.
Not sure if we need all of them.
I am undecided. I tried both ways and ended with this diff.
bluhm
> > Index: kern/uipc_socket2.c
> > ===================================================================
> > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket2.c,v
> > diff -u -p -r1.177 uipc_socket2.c
> > --- kern/uipc_socket2.c 6 Feb 2025 13:39:31 -0000 1.177
> > +++ kern/uipc_socket2.c 13 Feb 2025 18:06:59 -0000
> > @@ -502,13 +502,6 @@ sosleep_nsec(struct socket *so, void *id
> > return ret;
> > }
> >
> > -void
> > -sbmtxassertlocked(struct sockbuf *sb)
> > -{
> > - if (splassert_ctl > 0 && mtx_owned(&sb->sb_mtx) == 0)
> > - splassert_fail(0, RW_WRITE, __func__);
> > -}
> > -
> > /*
> > * Wait for data to arrive at/drain from a socket buffer.
> > */
> > @@ -646,7 +639,7 @@ bad:
> > int
> > sbreserve(struct socket *so, struct sockbuf *sb, u_long cc)
> > {
> > - sbmtxassertlocked(sb);
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> >
> > if (cc == 0 || cc > sb_max)
> > return (1);
> > @@ -688,6 +681,14 @@ sbchecklowmem(void)
> > return (atomic_load_int(&sblowmem));
> > }
> >
> > +long
> > +sbspace_locked(struct sockbuf *sb)
> > +{
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> > +
> > + return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt);
> > +}
> > +
> > /*
> > * Free mbufs held by a socket, and reserved mbuf space.
> > */
> > @@ -790,10 +791,11 @@ sbappend(struct socket *so, struct sockb
> > {
> > struct mbuf *n;
> >
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> > +
> > if (m == NULL)
> > return;
> >
> > - sbmtxassertlocked(sb);
> > SBLASTRECORDCHK(sb, "sbappend 1");
> >
> > if ((n = sb->sb_lastrecord) != NULL) {
> > @@ -827,7 +829,7 @@ sbappend(struct socket *so, struct sockb
> > void
> > sbappendstream(struct socket *so, struct sockbuf *sb, struct mbuf *m)
> > {
> > - sbmtxassertlocked(sb);
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> > KDASSERT(m->m_nextpkt == NULL);
> > KASSERT(sb->sb_mb == sb->sb_lastrecord);
> >
> > @@ -873,7 +875,7 @@ sbappendrecord(struct socket *so, struct
> > {
> > struct mbuf *m;
> >
> > - sbmtxassertlocked(sb);
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> >
> > if (m0 == NULL)
> > return;
> > @@ -908,7 +910,7 @@ sbappendaddr(struct socket *so, struct s
> > struct mbuf *m, *n, *nlast;
> > int space = asa->sa_len;
> >
> > - sbmtxassertlocked(sb);
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> >
> > if (m0 && (m0->m_flags & M_PKTHDR) == 0)
> > panic("sbappendaddr");
> > @@ -957,7 +959,7 @@ sbappendcontrol(struct socket *so, struc
> > struct mbuf *m, *mlast, *n;
> > int eor = 0, space = 0;
> >
> > - sbmtxassertlocked(sb);
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> >
> > if (control == NULL)
> > panic("sbappendcontrol");
> > @@ -1082,7 +1084,7 @@ sbdrop(struct sockbuf *sb, int len)
> > struct mbuf *m, *mn;
> > struct mbuf *next;
> >
> > - sbmtxassertlocked(sb);
> > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx);
> >
> > next = (m = sb->sb_mb) ? m->m_nextpkt : NULL;
> > while (len > 0) {
> > Index: sys/socketvar.h
> > ===================================================================
> > RCS file: /data/mirror/openbsd/cvs/src/sys/sys/socketvar.h,v
> > diff -u -p -r1.149 socketvar.h
> > --- sys/socketvar.h 6 Feb 2025 13:39:31 -0000 1.149
> > +++ sys/socketvar.h 13 Feb 2025 18:06:24 -0000
> > @@ -224,8 +224,6 @@ soref(struct socket *so)
> > #define isspliced(so) ((so)->so_sp && (so)->so_sp->ssp_socket)
> > #define issplicedback(so) ((so)->so_sp && (so)->so_sp->ssp_soback)
> >
> > -void sbmtxassertlocked(struct sockbuf *);
> > -
> > /*
> > * Do we need to notify the other side when I/O is possible?
> > */
> > @@ -250,20 +248,12 @@ sb_notify(struct sockbuf *sb)
> > */
> >
> > static inline long
> > -sbspace_locked(struct sockbuf *sb)
> > -{
> > - sbmtxassertlocked(sb);
> > -
> > - return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt);
> > -}
> > -
> > -static inline long
> > sbspace(struct sockbuf *sb)
> > {
> > long ret;
> >
> > mtx_enter(&sb->sb_mtx);
> > - ret = sbspace_locked(sb);
> > + ret = lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt);
> > mtx_leave(&sb->sb_mtx);
> >
> > return ret;
> > @@ -389,6 +379,7 @@ void sbflush(struct sockbuf *);
> > void sbrelease(struct socket *, struct sockbuf *);
> > int sbcheckreserve(u_long, u_long);
> > int sbchecklowmem(void);
> > +long sbspace_locked(struct sockbuf *);
> > int sbreserve(struct socket *, struct sockbuf *, u_long);
> > int sbwait(struct sockbuf *);
> > void soinit(void);
> >
>
>
replace sbmtxassertlocked with MUTEX_ASSERT_LOCKED