Re: Panic: UDP header not in one mbuf

看板DFBSD_kernel作者時間21年前 (2004/08/24 05:32), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串2/5 (看更多)
:I am not sure if this is the proper mailing list for this question; if :not, please direct me accordingly. : :On a DragonFly 1.1-Current machine (cvsupped and built 8/19/2004) I :receive the following output after a panic (with DDB enabled in kernel): : :panic: UDP header not in one mbuf :... : :I have been having issues of this nature for a while - I suspect an :issue I am having with bind (named) crashing is related to this. : :The machines are Supermicro 6013P-8 with dual P4 (Xeon) procs. ACPI is :disabled, HTT is not. The machines process a decent volume (65k pieces :daily) of email and use mimedefang/spamassassin/sendmail along with a :local caching instance of named. Sven, please try this patch. After examining the code path I found a hole where an embedded ip_len which is smaller then the actual packet survives the length test in ip_demux(), which means it can hit the assertion in udp_input(). -Matt Index: ip_demux.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_demux.c,v retrieving revision 1.26 diff -u -r1.26 ip_demux.c --- ip_demux.c 3 Aug 2004 00:04:13 -0000 1.26 +++ ip_demux.c 23 Aug 2004 21:21:14 -0000 @@ -109,6 +109,7 @@ { struct ip *ip; int iphlen; + int iplen; struct tcphdr *th; struct udphdr *uh; struct mbuf *m = *mptr; @@ -142,6 +143,7 @@ * first mbuf must entirely contain the extended IP header. */ iphlen = ip->ip_hl << 2; + iplen = ntohs(ip->ip_len); if (iphlen < sizeof(struct ip)) { /* minimum header length */ ipstat.ips_badhlen++; m_freem(m); @@ -161,10 +163,20 @@ * The TCP/IP or UDP/IP header must be entirely contained within * the first fragment of a packet. Packet filters will break if they * aren't. + * + * Since the packet will be trimmed to ip_len we must also make sure + * the potentially trimmed down length is still sufficient to hold + * the header(s). */ if ((ntohs(ip->ip_off) & IP_OFFMASK) == 0) { switch (ip->ip_p) { case IPPROTO_TCP: + if (iplen < iphlen + sizeof(struct tcphdr)) { + ++tcpstat.tcps_rcvshort; + m_freem(m); + *mptr = NULL; + return (NULL); + } if (m->m_len < iphlen + sizeof(struct tcphdr)) { m = m_pullup(m, iphlen + sizeof(struct tcphdr)); if (m == NULL) { @@ -176,6 +188,12 @@ } break; case IPPROTO_UDP: + if (iplen < iphlen + sizeof(struct udphdr)) { + ++udpstat.udps_hdrops; + m_freem(m); + *mptr = NULL; + return (NULL); + } if (m->m_len < iphlen + sizeof(struct udphdr)) { m = m_pullup(m, iphlen + sizeof(struct udphdr)); if (m == NULL) { @@ -187,6 +205,12 @@ } break; default: + if (iplen < iphlen) { + ++ipstat.ips_badlen; + m_freem(m); + *mptr = NULL; + return (NULL); + } break; } }
文章代碼(AID): #11Ac9K00 (DFBSD_kernel)
文章代碼(AID): #11Ac9K00 (DFBSD_kernel)