[Bug 264428] [tcp] Crash in sbsndptr

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 03 Jun 2022 09:18:55 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264428

            Bug ID: 264428
           Summary: [tcp] Crash in sbsndptr
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: ram.gupta.19@gmail.com

Following is the analysis of the crash seen in sbsndptr in the stack. 

#0  0x0000ffff8ead225c in raise () from /usr/lib/libc.so.6
#1  0x0000ffff8ead3310 in abort () from /usr/lib/libc.so.6
#2  0x000000000097b238 in panic (fmt=fmt@entry=0xb7b9e0 "%s: sockbuf %p and
mbuf %p clashing") at uinet_kern_shutdown.c:48
#3  0x0000000000915df4 in sbsndptr (sb=sb@entry=0x40003fff5188, off=<optimized
out>, off@entry=462, len=len@entry=462,
    moff=moff@entry=0xffff79eb64c8) at
/root/open_source/uinet/sys/kern/uipc_sockbuf.c:1025
#4  0x0000000000963d24 in tcp_output (tp=tp@entry=0x40003ffed000) at
/root/open_source/uinet/sys/netinet/tcp_output.c:873
#5  0x0000000000970994 in tcp_output_send (tp=0x40003ffed000) at
/root/open_source/uinet/sys/netinet/tcp_offload.h:282
#6  tcp_usr_send (so=0x40003fff5000, flags=0, m=<optimized out>, nam=0x0,
control=<optimized out>, td=0xffff79ebb280)
    at /root/open_source/uinet/sys/netinet/tcp_usrreq.c:887
#7  0x00000000009185dc in sosend_generic (so=0x40003fff5000,
addr=0xffff00000001, uio=0xffff79eb65f8, top=0x40003fd72000, control=0x1ce,
    flags=0, td=0xffff79eb65b0) at
/root/open_source/uinet/sys/kern/uipc_socket.c:1528
#8  0x00000000009187a0 in sosend (so=<optimized out>, addr=<optimized out>,
uio=uio@entry=0xffff79eb6608, top=top@entry=0x0,
    control=control@entry=0x0, flags=flags@entry=0, td=<optimized out>) at
/root/open_source/uinet/sys/kern/uipc_socket.c:1574

The issue happens when trailing space becomes less than segment size. . This is
where the problem starts as below 

1)      Sbcompress instead of incrementing mbuf len, sets the input mbuf to the
sb->mb_tail next pointer. 
2)      It also calls sballoc where a new mbuf is stored in the socket buf.
This mbuf is stored in sb->sb_mb pointer of send sockbuf.
3)      At this point, the len is 462B, offset is 462B and sb_cc is 924B (one
seg wating for ack and other to be sent) and sb_sndptroff is 462 
4)      When sbsndptr is called, it gets the new mbuf stored in step 2 which
does not have m->next pointer at this point of time. 
5)      Offset calculated is  (off - sb_sndptroff + len – 1) but since m->next
pointer is null, panic is caused. 

Since the mbuf flag is not set to M_HOLE, Trailing space remains constant
rather than increasing for accommodating new mbuf. 

static void
sbdrop_internal(struct sockbuf *sb, int len)
{
…
              if (m->m_len > len) {
            m->m_len -= len;   -> Increase TS
            if (!(m->m_flags & M_HOLE)) {
                m->m_data += len;  -> Equalizes the TS 
            }

Where TS is 

(m)->m_ext.ext_buf + (m)->m_ext.ext_size - ((m)->m_data + (m)->m_len)

So in nutshell, this condition hits in the following case where segment is
being trying to be sent 

1)      TS shrinks to lower than m->m_len. (This condition is rare to happen if
all acks for a particular mbuf are received at any point of time. If rcv’ed,
mbuf is freed and sockbuf mbuf pointer is null. This resets the TS from 2048) 
2)      Unacknowledged data is one ACK away (off will be 462) 
3)      Length to be sent (462B) 

So the question is, on high pps environment, should m_flags be set to M_HOLE so
TS can adjust dynamically. 

Thanks,
Raman

-- 
You are receiving this mail because:
You are the assignee for the bug.