Bug 1058

Summary: system crashes when sending IP packet with bad length
Product: Base System Reporter: Paul Traina <pst>
Component: kernAssignee: pst
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 2.2-CURRENT   
Hardware: Any   
OS: Any   

Description Paul Traina 1996-03-04 06:20:01 UTC
I was porting in the new LBL traceroute code.  There is a questionable
bug in the code -- it sets the IP packet's TL field in network order not
host order, I believe that to be a bug...

The system crashed because it walked off the end of the mbuf chain because
it thought it had a nice long packet to send.  The system should NOT crash.
I'll fix traceroute, but someone needs to fix the kernel (I may fix it too.)

Fix: 

Check IP header length against mbuf size in raw_ip.c, return einval if
the packet would run off the end of the mbuf chain.
How-To-Repeat: 
get ftp://ftp.ee.lbl.gov/traceroute-1.2.tar.gz, compile it and run it


Script started on Sun Mar  3 10:35:07 1996
GDB is free software and you are welcome to 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.
GDB 4.13 (i386-unknown-freebsd), 
Copyright 1994 Free Software Foundation, Inc...
IdlePTD 3a9000
current pcb at 1bfdf4
panic: m_copym
#0  boot (howto=260) at ../../i386/i386/machdep.c:940
940					dumppcb.pcb_ptd = rcr3();
(kgdb) where
#0  boot (howto=260) at ../../i386/i386/machdep.c:940
#1  0xf0118304 in panic ()
#2  0xf01013de in db_fncall ()
#3  0xf010110e in db_command ()
#4  0xf010128d in db_command_loop ()
#5  0xf01035d4 in db_trap ()
#6  0xf0175b6a in kdb_trap ()
#7  0xf017d8ac in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = 40, 
      tf_esi = -267233635, tf_ebp = -272630424, tf_isp = -272630452, 
      tf_ebx = 256, tf_edx = 0, tf_ecx = -266904219, tf_eax = 18, 
      tf_trapno = 3, tf_err = 0, tf_eip = -266904173, tf_cs = 8, 
      tf_eflags = 582, tf_esp = -266904235, tf_ss = -267287894})
    at ../../i386/i386/trap.c:400
#8  0xf01763c1 in calltrap ()
#9  0xf01182fe in panic ()
#10 0xf01256fe in m_copym ()
#11 0xf014b004 in ip_output (m0=0xf0bdc480, opt=0x0, ro=0xf0ba9a2c, flags=34, 
    imo=0x0) at ../../netinet/ip_output.c:421
#12 0xf014c18f in rip_output (m=0xf0bdc480, so=0xf0bde200, dst=2919318955)
    at ../../netinet/raw_ip.c:179
#13 0xf014c5a8 in rip_usrreq (so=0xf0bde200, req=9, m=0xf0bdc480, 
    nam=0xf0baa280, control=0x0) at ../../netinet/raw_ip.c:400
#14 0xf0126d4a in sosend ()
#15 0xf012941b in sendit ()
---Type <return> to continue, or q <return> to quit---
#16 0xf01294f8 in sendto ()
#17 0xf017e32e in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi = 1, 
      tf_esi = -272639016, tf_ebp = -272639116, tf_isp = -272629788, 
      tf_ebx = 1, tf_edx = 825877907, tf_ecx = 45056, tf_eax = 133, 
      tf_trapno = 12, tf_err = 646, tf_eip = 134605509, tf_cs = 31, 
      tf_eflags = 646, tf_esp = -272639152, tf_ss = 39})
    at ../../i386/i386/trap.c:919
#18 0xf017640d in Xsyscall ()
#19 0x2039 in ?? ()
#20 0x1096 in ?? ()
(kgdb) up
#1  0xf0118304 in panic ()
(kgdb) up
#2  0xf01013de in db_fncall ()
(kgdb) up
#3  0xf010110e in db_command ()
(kgdb) up
#4  0xf010128d in db_command_loop ()
(kgdb) up
#5  0xf01035d4 in db_trap ()
(kgdb) up
#6  0xf0175b6a in kdb_trap ()
(kgdb) up
#7  0xf017d8ac in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = 40, 
      tf_esi = -267233635, tf_ebp = -272630424, tf_isp = -272630452, 
      tf_ebx = 256, tf_edx = 0, tf_ecx = -266904219, tf_eax = 18, 
      tf_trapno = 3, tf_err = 0, tf_eip = -266904173, tf_cs = 8, 
      tf_eflags = 582, tf_esp = -266904235, tf_ss = -267287894})
    at ../../i386/i386/trap.c:400
400				if (kdb_trap (type, 0, &frame))
(kgdb) up
#8  0xf01763c1 in calltrap ()
(kgdb) up
#9  0xf01182fe in panic ()
(kgdb) up
#10 0xf01256fe in m_copym ()
(kgdb) up
#11 0xf014b004 in ip_output (m0=0xf0bdc480, opt=0x0, ro=0xf0ba9a2c, flags=34, 
    imo=0x0) at ../../netinet/ip_output.c:421
421			m->m_next = m_copy(m0, off, len);
(kgdb) print len
$1 = 1496
(kgdb) print of
No symbol "of" in current context.
(kgdb) print off
$2 = 1496
(kgdb) print m0
$3 = (struct mbuf *) 0xf0bdc480
(kgdb) up
#12 0xf014c18f in rip_output (m=0xf0bdc480, so=0xf0bde200, dst=2919318955)
    at ../../netinet/raw_ip.c:179
179		return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions));
(kgdb) print flags
$4 = 34
(kgdb) print /x flags
$5 = 0x22
(kgdb) up
#13 0xf014c5a8 in rip_usrreq (so=0xf0bde200, req=9, m=0xf0bdc480, 
    nam=0xf0baa280, control=0x0) at ../../netinet/raw_ip.c:400
400			error = rip_output(m, so, dst);
(kgdb) up
#14 0xf0126d4a in sosend ()
(kgdb) up
#15 0xf012941b in sendit ()
(kgdb) up
#16 0xf01294f8 in sendto ()
(kgdb) up
#17 0xf017e32e in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi = 1, 
      tf_esi = -272639016, tf_ebp = -272639116, tf_isp = -272629788, 
      tf_ebx = 1, tf_edx = 825877907, tf_ecx = 45056, tf_eax = 133, 
      tf_trapno = 12, tf_err = 646, tf_eip = 134605509, tf_cs = 31, 
      tf_eflags = 646, tf_esp = -272639152, tf_ss = 39})
    at ../../i386/i386/trap.c:919
919		error = (*callp->sy_call)(p, args, rval);
(kgdb) up
#18 0xf017640d in Xsyscall ()
(kgdb) down
#17 0xf017e32e in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi = 1, 
      tf_esi = -272639016, tf_ebp = -272639116, tf_isp = -272629788, 
      tf_ebx = 1, tf_edx = 825877907, tf_ecx = 45056, tf_eax = 133, 
      tf_trapno = 12, tf_err = 646, tf_eip = 134605509, tf_cs = 31, 
      tf_eflags = 646, tf_esp = -272639152, tf_ss = 39})
    at ../../i386/i386/trap.c:919
919		error = (*callp->sy_call)(p, args, rval);
(kgdb) down
#16 0xf01294f8 in sendto ()
(kgdb) down
#15 0xf012941b in sendit ()
(kgdb) down
#14 0xf0126d4a in sosend ()
(kgdb) down
#13 0xf014c5a8 in rip_usrreq (so=0xf0bde200, req=9, m=0xf0bdc480, 
    nam=0xf0baa280, control=0x0) at ../../netinet/raw_ip.c:400
400			error = rip_output(m, so, dst);
(kgdb) print so
$6 = (struct socket *) 0xf0bde200
(kgdb) print *so
$7 = {so_type = 3, so_options = 0, so_linger = 0, so_state = 128, 
  so_pcb = 0xf0ba9a00 "\200o½ðøò\eð\200o½ð\200\017±ðüò\eð", 
  so_proto = 0xf01ad7f0, so_head = 0x0, so_q0 = 0x0, so_q = 0x0, so_q0len = 0, 
  so_qlen = 0, so_qlimit = 0, so_timeo = 0, so_error = 0, so_pgid = 0, 
  so_oobmark = 0, so_rcv = {sb_cc = 0, sb_hiwat = 8192, sb_mbcnt = 0, 
    sb_mbmax = 65536, sb_lowat = 1, sb_mb = 0x0, sb_sel = {si_pid = 0, 
      si_flags = 0}, sb_flags = 0, sb_timeo = 0}, so_snd = {sb_cc = 0, 
    sb_hiwat = 40, sb_mbcnt = 0, sb_mbmax = 320, sb_lowat = 40, sb_mb = 0x0, 
    sb_sel = {si_pid = 0, si_flags = 0}, sb_flags = 1, sb_timeo = 0}, 
  so_tpcb = 0x0, so_upcall = 0, so_upcallarg = 0x0}
(kgdb) print *dst
$8 = 74581447
(kgdb) print dst
$9 = 1
(kgdb) print /x dst
$10 = 0x1
(kgdb) print *m
$11 = {m_hdr = {mh_next = 0x0, mh_nextpkt = 0x0, mh_len = 40, 
    mh_data = 0xf0bdc4d8 "", mh_type = 1, mh_flags = 2}, M_dat = {MH = {
      MH_pkthdr = {len = 40, rcvif = 0x0}, MH_dat = {MH_ext = {ext_buf = 0x0, 
          ext_free = 0, ext_size = 4038968480}, 
        MH_databuf = "\000\000\000\000\000\000\000\000 Ä½ð\001\000\000\000\001\000\000\000\000\000\000\000\210\001", '\000' <repeats 37 times>, "(\000X\000\000\001\021\000\000«El!«E\001®\200­\202\233\000\024\000\000\001\001\000\000\223å91Òÿ\004"}}, 
    M_databuf = "(", '\000' <repeats 15 times>, " Ä½ð\001\000\000\000\001\000\000\000\000\000\000\000\210\001", '\000' <repeats 37 times>, "(\000X\000\000\001\021\000\000«El!«E\001®\200­\202\233\000\024\000\000\001\001\000\000\223å91Òÿ\004"}}
(kgdb) pr  down
#12 0xf014c18f in rip_output (m=0xf0bdc480, so=0xf0bde200, dst=2919318955)
    at ../../netinet/raw_ip.c:179
179		return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions));
(kgdb) print opts
$12 = (struct mbuf *) 0x0
(kgdb) print *inp    inp
$13 = (struct inpcb *) 0xf0ba9a00
(kgdb) print inp->inpo _route
$14 = {ro_rt = 0xf0b77d00, ro_dst = {sa_len = 16 '\020', sa_family = 2 '\002', 
    sa_data = "\000\000«E\001®\000\000\000\000\000\000\000"}}
(kgdb) print flags
$15 = 34
(kgdb) print inp->inp_moptions
$16 = (struct ip_moptions *) 0x0
(kgdb) down
#11 0xf014b004 in ip_output (m0=0xf0bdc480, opt=0x0, ro=0xf0ba9a2c, flags=34, 
    imo=0x0) at ../../netinet/ip_output.c:421
421			m->m_next = m_copy(m0, off, len);
(kgdb) list
416			if (off + len >= (u_short)ip->ip_len)
417				len = (u_short)ip->ip_len - off;
418			else
419				mhip->ip_off |= IP_MF;
420			mhip->ip_len = htons((u_short)(len + mhlen));
421			m->m_next = m_copy(m0, off, len);
422			if (m->m_next == 0) {
423				(void) m_free(m);
424				error = ENOBUFS;	/* ??? */
425				ipstat.ips_odropped++;
(kgdb) print m0
$17 = (struct mbuf *) 0xf0bdc480
(kgdb) print mhip->ip_len
$18 = -5115
(kgdb) print mhip
$19 = (struct ip *) 0xf0bdc0ac
(kgdb) print *mhip
$20 = {ip_hl = 0 '\000', ip_v = 0 '\000', ip_tos = 0 '\000', ip_len = -5115, 
  ip_id = 22528, ip_off = 8379, ip_ttl = 1 '\001', ip_p = 17 '\021', 
  ip_sum = 0, ip_src = {s_addr = 560743851}, ip_dst = {s_addr = 2919318955}}
(kgdb) print len
$21 = 1496
(kgdb) print mhlen
$22 = 20
(kgdb) print /x m *mhip     mhip->(kgdb) [Kprint /x *mhip
$23 = {ip_hl = 0x0, ip_v = 0x0, ip_tos = 0x0, ip_len = 0xec05, ip_id = 0x5800, 
  ip_off = 0x20bb, ip_ttl = 0x1, ip_p = 0x11, ip_sum = 0x0, ip_src = {
    s_addr = 0x216c45ab}, ip_dst = {s_addr = 0xae0145ab}}
(kgdb) where
#0  boot (howto=260) at ../../i386/i386/machdep.c:940
#1  0xf0118304 in panic ()
#2  0xf01013de in db_fncall ()
#3  0xf010110e in db_command ()
#4  0xf010128d in db_command_loop ()
#5  0xf01035d4 in db_trap ()
#6  0xf0175b6a in kdb_trap ()
#7  0xf017d8ac in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = 40, 
      tf_esi = -267233635, tf_ebp = -272630424, tf_isp = -272630452, 
      tf_ebx = 256, tf_edx = 0, tf_ecx = -266904219, tf_eax = 18, 
      tf_trapno = 3, tf_err = 0, tf_eip = -266904173, tf_cs = 8, 
      tf_eflags = 582, tf_esp = -266904235, tf_ss = -267287894})
    at ../../i386/i386/trap.c:400
#8  0xf01763c1 in calltrap ()
#9  0xf01182fe in panic ()
#10 0xf01256fe in m_copym ()
#11 0xf014b004 in ip_output (m0=0xf0bdc480, opt=0x0, ro=0xf0ba9a2c, flags=34, 
    imo=0x0) at ../../netinet/ip_output.c:421
#12 0xf014c18f in rip_output (m=0xf0bdc480, so=0xf0bde200, dst=2919318955)
    at ../../netinet/raw_ip.c:179
#13 0xf014c5a8 in rip_usrreq (so=0xf0bde200, req=9, m=0xf0bdc480, 
    nam=0xf0baa280, control=0x0) at ../../netinet/raw_ip.c:400
#14 0xf0126d4a in sosend ()
#15 0xf012941b in sendit ()
---Type <return> to continue, or q <return> to quit--- 
#16 0xf01294f8 in sendto ()
#17 0xf017e32e in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi = 1, 
      tf_esi = -272639016, tf_ebp = -272639116, tf_isp = -272629788, 
      tf_ebx = 1, tf_edx = 825877907, tf_ecx = 45056, tf_eax = 133, 
      tf_trapno = 12, tf_err = 646, tf_eip = 134605509, tf_cs = 31, 
      tf_eflags = 646, tf_esp = -272639152, tf_ss = 39})
    at ../../i386/i386/trap.c:919
#18 0xf017640d in Xsyscall ()
#19 0x2039 in ?? ()
#20 0x1096 in ?? ()
(kgdb) up
#12 0xf014c18f in rip_output (m=0xf0bdc480, so=0xf0bde200, dst=2919318955)
    at ../../netinet/raw_ip.c:179
179		return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions));
(kgdb) down
#11 0xf014b004 in ip_output (m0=0xf0bdc480, opt=0x0, ro=0xf0ba9a2c, flags=34, 
    imo=0x0) at ../../netinet/ip_output.c:421
421			m->m_next = m_copy(m0, off, len);
(kgdb) list 400
395		 */
396		m0 = m;
397		mhlen = sizeof (struct ip);
398		for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
399			MGETHDR(m, M_DONTWAIT, MT_HEADER);
400			if (m == 0) {
401				error = ENOBUFS;
402				ipstat.ips_odropped++;
403				goto sendorfree;
404			}
(kgdb) 
405			m->m_data += max_linkhdr;
406			mhip = mtod(m, struct ip *);
407			*mhip = *ip;
408			if (hlen > sizeof (struct ip)) {
409				mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
410				mhip->ip_hl = mhlen >> 2;
411			}
412			m->m_len = mhlen;
413			mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
414			if (ip->ip_off & IP_MF)
(kgdb) print *ip
$24 = {ip_hl = 0 '\000', ip_v = 0 '\000', ip_tos = 0 '\000', ip_len = 10240, 
  ip_id = 22528, ip_off = 0, ip_ttl = 1 '\001', ip_p = 17 '\021', ip_sum = 0, 
  ip_src = {s_addr = 560743851}, ip_dst = {s_addr = 2919318955}}
(kgdb) print heln    l hlen
$25 = 0
(kgdb) print len
$26 = 1496
(kgdb) quit
bash# exit

Script done on Sun Mar  3 10:40:35 1996
Comment 1 pst freebsd_committer freebsd_triage 1996-03-04 22:36:50 UTC
Responsible Changed
From-To: freebsd-bugs->pst

Comment 2 pst freebsd_committer freebsd_triage 1996-03-13 08:09:20 UTC
State Changed
From-To: open->closed