From owner-freebsd-net@FreeBSD.ORG Tue Apr 1 20:40:54 2008 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 211851065670 for ; Tue, 1 Apr 2008 20:40:54 +0000 (UTC) (envelope-from andre@freebsd.org) Received: from c00l3r.networx.ch (c00l3r.networx.ch [62.48.2.2]) by mx1.freebsd.org (Postfix) with ESMTP id 6E5F08FC2D for ; Tue, 1 Apr 2008 20:40:53 +0000 (UTC) (envelope-from andre@freebsd.org) Received: (qmail 44895 invoked from network); 1 Apr 2008 19:49:22 -0000 Received: from localhost (HELO [127.0.0.1]) ([127.0.0.1]) (envelope-sender ) by c00l3r.networx.ch (qmail-ldap-1.03) with SMTP for ; 1 Apr 2008 19:49:22 -0000 Message-ID: <47F29DE0.6080500@freebsd.org> Date: Tue, 01 Apr 2008 22:41:04 +0200 From: Andre Oppermann User-Agent: Thunderbird 1.5.0.14 (Windows/20071210) MIME-Version: 1.0 To: Mark Atkinson References: <20080401191246.GA1491@fnop.net> <47F29471.10901@freebsd.org> In-Reply-To: <47F29471.10901@freebsd.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit Cc: freebsd-net@freebsd.org, rpaulo@freebsd.org Subject: Re: panic: tcp_addoptions: TCP options too long w/ with TCP_SIGNATURE support X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Apr 2008 20:40:54 -0000 Andre Oppermann wrote: > Mark Atkinson wrote: >> Rui Paulo wrote: >> >>> Hi, >>> >>> On Tue, Apr 01, 2008 at 09:08:35AM -0700, Mark Atkinson wrote: >>>> I have a 8-CURRENT kernel compiled with the following options, from >>>> about >>>> march 5th. >>>> >>>> options IPSEC >>>> options TCP_SIGNATURE #include support for RFC 2385 >>>> device crypto >>>> device cryptodev >>>> >>>> device pf >>>> device pflog >>>> >>>> device vlan >>>> >>>> I also have a external server supporting MD5 tcp signatures. If I give >>>> the following command: >>>> >>>> /usr/src/tools/regression/netinet/tcpconnect/tcpconnect client >>>> 172.16.1.145 7 1 tcpmd5 >>>> >>>> panic: tcp_addoptions: TCP options too long >>> Could you please use gdb or add a printf to find the value of optlen ? >>> >> >> $ kgdb kernel.debug /var/crash/vmcore.2 >> [GDB will not be able to debug user-mode threads: >> /usr/lib/libthread_db.so: >> Undefined symbol "ps_pglobal_lookup"] >> GNU gdb 6.1.1 [FreeBSD] >> Copyright 2004 Free Software Foundation, Inc. >> GDB is free software, covered by the GNU General Public License, and >> you are >> welcome to change it and/or distribute copies of it under certain >> conditions. >> Type "show copying" to see the conditions. >> There is absolutely no warranty for GDB. Type "show warranty" for >> details. >> This GDB was configured as "i386-marcel-freebsd". >> Reading symbols from /boot/kernel/acpi.ko...Reading symbols >> from /boot/kernel/acpi.ko.symbols...done. >> done. >> Loaded symbols for /boot/kernel/acpi.ko >> Reading symbols from /boot/kernel/ipfw.ko...Reading symbols >> from /boot/kernel/ipfw.ko.symbols...done. >> done. >> Loaded symbols for /boot/kernel/ipfw.ko >> >> Unread portion of the kernel message buffer: >> panic: tcp_addoptions: TCP options too long >> cpuid = 1 >> KDB: enter: panic >> Physical memory: 2034 MB >> Dumping 79 MB: 64 48 32 16 >> >> #0 doadump () at pcpu.h:195 >> 195 __asm __volatile("movl %%fs:0,%0" : "=r" (td)); >> (kgdb) bt >> #0 doadump () at pcpu.h:195 >> #1 0xc04c7159 in db_fncall (dummy1=1017, dummy2=0, dummy3=1019, >> dummy4=0xe7b808b0 "ø\003") at /usr/src/sys/ddb/db_command.c:516 >> #2 0xc04c76dc in db_command (last_cmdp=0xc0c5c7b4, cmd_table=0x0, >> dopager=1) at /usr/src/sys/ddb/db_command.c:413 >> #3 0xc04c77ea in db_command_loop () at /usr/src/sys/ddb/db_command.c:466 >> #4 0xc04c8fec in db_trap (type=3, code=0) at >> /usr/src/sys/ddb/db_main.c:228 >> #5 0xc07cf325 in kdb_trap (type=3, code=0, tf=0xe7b80a58) >> at /usr/src/sys/kern/subr_kdb.c:510 >> #6 0xc0ac8d5f in trap (frame=0xe7b80a58) >> at /usr/src/sys/i386/i386/trap.c:643 >> #7 0xc0aad7cb in calltrap () at /usr/src/sys/i386/i386/exception.s:146 >> #8 0xc07cf4aa in kdb_enter (why=0xc0b62ce8 "panic", msg=0xc0b62ce8 >> "panic") >> at cpufunc.h:60 >> #9 0xc07a67cc in panic (fmt=0xc0b78840 "%s: TCP options too long") >> at /usr/src/sys/kern/kern_shutdown.c:556 >> #10 0xc08e8207 in tcp_addoptions (to=0xe7b80ba4, >> optp=0xe7b80bc0 "\002\004\005´\001\003\003\003\001\001\b\n") >> at /usr/src/sys/netinet/tcp_output.c:1402 >> #11 0xc08e8c79 in tcp_output (tp=0xc576d570) >> at /usr/src/sys/netinet/tcp_output.c:693 >> #12 0xc08f4f35 in tcp_usr_connect (so=0xc5709794, nam=0xc5260280, >> td=0xc5729210) at tcp_offload.h:251 >> #13 0xc07ff092 in soconnect (so=0xc5709794, nam=0xc5260280, >> td=0xc5729210) >> at /usr/src/sys/kern/uipc_socket.c:765 >> #14 0xc0805436 in kern_connect (td=0xc5729210, fd=3, sa=0xc5260280) >> at /usr/src/sys/kern/uipc_syscalls.c:560 >> #15 0xc08055a6 in connect (td=0xc5729210, uap=0xe7b80cfc) >> at /usr/src/sys/kern/uipc_syscalls.c:524 >> #16 0xc0ac8513 in syscall (frame=0xe7b80d38) >> at /usr/src/sys/i386/i386/trap.c:1026 >> #17 0xc0aad830 in Xint0x80_syscall () >> at /usr/src/sys/i386/i386/exception.s:203 >> #18 0x00000033 in ?? () >> Previous frame inner to this frame (corrupt stack?) >> (kgdb) frame 10 >> #10 0xc08e8207 in tcp_addoptions (to=0xe7b80ba4, >> optp=0xe7b80bc0 "\002\004\005´\001\003\003\003\001\001\b\n") >> at /usr/src/sys/netinet/tcp_output.c:1402 >> 1402 KASSERT(optlen <= TCP_MAXOLEN, ("%s: TCP options too >> long", >> __func__)); >> (kgdb) p optlen >> $1 = 44 >> (kgdb) > > The order of the TCP options was changed recently to fix another problem. > This has caused sub-optimal padding and this overflow as not all options > fit. The tcp_addoptions() loop is not bound internally. Correction: It is bound but not for all options (only SACK and Signature). > http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/netinet/tcp_output.c?rev=1.146 Before: MSS (4) + NOP (1) + Window scale (3) + SACK permitted (2) + Timestamp (10) + Signature (18) = 38 bytes out of a maximum of 40. After: MSS (4) + NOP (1) + Window scale (3) + NOP (2) + Timestamp (10) + NOP (2) + Signature (18) + SACK permitted (2) + EOL (1) + PAD (1) = 44 bytes out of a maximum of 40. With the attached patch it will omit the SACK permitted option (disabling SACK) and limiting it to 40 bytes. -- Andre ==== //depot/projects/tcp_reass/netinet/tcp_output.c#5 (text+ko) ==== @@ -1279,12 +1279,16 @@ for (mask = 1; mask < TOF_MAXOPT; mask <<= 1) { if ((to->to_flags & mask) != mask) continue; + if (optlen == TCP_MAXOLEN) + break; switch (to->to_flags & mask) { case TOF_MSS: while (optlen % 4) { optlen += TCPOLEN_NOP; *optp++ = TCPOPT_NOP; } + if (TCP_MAXOLEN - optlen < TCPOLEN_MAXSEG) + continue; optlen += TCPOLEN_MAXSEG; *optp++ = TCPOPT_MAXSEG; *optp++ = TCPOLEN_MAXSEG; @@ -1297,6 +1301,8 @@ optlen += TCPOLEN_NOP; *optp++ = TCPOPT_NOP; } + if (TCP_MAXOLEN - optlen < TCPOLEN_WINDOW) + continue; optlen += TCPOLEN_WINDOW; *optp++ = TCPOPT_WINDOW; *optp++ = TCPOLEN_WINDOW; @@ -1307,6 +1313,8 @@ optlen += TCPOLEN_NOP; *optp++ = TCPOPT_NOP; } + if (TCP_MAXOLEN - optlen < TCPOLEN_SACK_PERMITTED) + continue; optlen += TCPOLEN_SACK_PERMITTED; *optp++ = TCPOPT_SACK_PERMITTED; *optp++ = TCPOLEN_SACK_PERMITTED; @@ -1316,6 +1324,8 @@ optlen += TCPOLEN_NOP; *optp++ = TCPOPT_NOP; } + if (TCP_MAXOLEN - optlen < TCPOLEN_TIMESTAMP) + continue; optlen += TCPOLEN_TIMESTAMP; *optp++ = TCPOPT_TIMESTAMP; *optp++ = TCPOLEN_TIMESTAMP; @@ -1352,7 +1362,7 @@ optlen += TCPOLEN_NOP; *optp++ = TCPOPT_NOP; } - if (TCP_MAXOLEN - optlen < 2 + TCPOLEN_SACK) + if (TCP_MAXOLEN - optlen < TCPOLEN_SACKHDR + TCPOLEN_SACK) continue; optlen += TCPOLEN_SACKHDR; *optp++ = TCPOPT_SACK;