Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!nntp.coast.net!news2.acs.oakland.edu!condor.ic.net!news.sojourn.com!cancer.vividnet.com!hunter.premier.net!news-peer.gsl.net!news.gsl.net!news.sgi.com!news.mathworks.com!newsfeed.internetmci.com!news.itjit.ad.jp!news.ipro.ad.jp!netlaputa.or.jp!spinnews!spin-hsd0-tky!inet-tsb!tis2!newshost.rdc.toshiba!cilab.rdc.toshiba!jinmei From: jinmei@isl.rdc.toshiba.co.jp (JINMEI Tatuya) Newsgroups: comp.bugs.4bsd Subject: un-freed mbuf in ip_output Date: 02 Oct 1996 13:35:25 +0900 Organization: Research & Development Center, Toshiba Corp., Kawasaki, Japan. Lines: 78 Sender: jinmei@sunsword.isl.rdc.toshiba.co.jp Message-ID: <52srh5$hip@monaco.csl.rdc.toshiba.co.jp> NNTP-Posting-Host: sunsword.isl.rdc.toshiba.co.jp Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Is this an well-known feature?: If we encounter some error in the ip_output function in ip_output.c of Net/3, we go to bad: label at the end of the functin and free the outgoing packet: bad: m_freem(m0); goto done; But sometimes m0 is not the entire outgoing packet. When IP options are passed to ip_output(), it calls ip_insertoptions(), which may modify the passed mbuf. For example, if the length of the option is larger than 20 bytes, ip_insertoptions() allocates a new mbuf, links it to the passed mbuf and return the new mbuf(say "m"). At this point, m and m0 differ. If we encounter an error(e.g. there is no route to the destination) and go to bad label under such a situation, only m0 is freed so m is still in the kernel memory. For example, if we compile the code at the end of the article and run the binary on 4.4 BSD(with unreachable destination as the 1st argument), an mbuf is un-freed. I apologize in advance if the feature is well-known or there is a more appropriate NG than this group. If so, please let me know. JINMEI, Tatuya Comm. and Info. Systems Research Labs. Toshiba R&D Center jinmei@isl.rdc.toshiba.co.jp #include <sys/types.h> #include <sys/socket.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> #include <stdio.h> main(argc, argv) int argc; char *argv[]; { struct sockaddr_in sin; int i, s; char opts[40]; if (argc == 1) { exit(-1); } if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(-1); } for (i = 0; i < 40; i++) opts[i] = IPOPT_NOP; if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, (void *)opts, 40) == -1) { perror("setsockopt"); exit(-1); } sin.sin_family = AF_INET; sin.sin_port = 21; sin.sin_len = sizeof(sin); inet_aton(argv[1], &sin.sin_addr); if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) { perror("connect"); exit(-1); } close(s); exit(0); }