*BSD News Article 79730


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);
}