mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "David S. Miller" <davem@redhat.com>
To: Dawson Engler <engler@csl.Stanford.EDU>
Cc: linux-kernel@vger.kernel.org, mc@cs.Stanford.EDU, SteveW@ACM.org,
	philb@gnu.org
Subject: Re: [CHECKER] 84 bugs in 2.4.4/2.4.4-ac8 where NULL pointers are deref'd
Date: Tue, 29 May 2001 15:36:44 -0700 (PDT)	[thread overview]
Message-ID: <15124.9340.77101.588276@pizda.ninka.net> (raw)
In-Reply-To: <200105292149.OAA29781@csl.Stanford.EDU>
In-Reply-To: <200105292149.OAA29781@csl.Stanford.EDU>


[ Steve: Just skim down to the decnet bug, you should have a look
         at it.

  Philip: Similarly, skim down to the econet bug. ]

Dawson Engler writes:
 > [BUG]  sends sk raw to a bunch of other routines.  doesn't seem good.
 > /u2/engler/mc/oses/linux/2.4.4-ac8/net/ipv4/ip_output.c:520:ip_build_xmit_slow: ERROR:INTERNAL_NULL:502:520: [type=set] (set at line 502) Dereferencing NULL ptr "sk" illegally!
 > 
 > 	/*
 > 	 *	Begin outputting the bytes.
 > 	 */
 > 
 > Start --->
 > 	id = (sk ? sk->protinfo.af_inet.id++ : 0);
 > 
 > 	... DELETED 12 lines ...
 > 
 > 
 > 		/*
 > 		 *	Fill in the control structures
 > 		 */
 > 
 > Error --->
 > 		skb->priority = sk->priority;
 > 		skb->dst = dst_clone(&rt->u.dst);
 > 		skb_reserve(skb, hh_len);

Actually, sk is not allowed to be NULL here, the "(sk ?" bit is bogus
and was cut and pasted from elsewhere.  I've removed it in my tree.

And if you look a couple lines previous it is blindly dereferenced,
this should have been a clue :-)

 > ---------------------------------------------------------
 > [BUG]  hard to follow but seems like it.
 > /u2/engler/mc/oses/linux/2.4.4-ac8/net/ipv4/fib_frontend.c:272:fib_validate_source: ERROR:INTERNAL_NULL:239:272: [type=set] (set at line 239) Dereferencing NULL ptr "itag" illegally!
 > 	if (fib_lookup(&key, &res))
 > 		goto last_resort;
 > 	if (res.type != RTN_UNICAST)
 > 		goto e_inval_res;
 > 	*spec_dst = FIB_RES_PREFSRC(res);
 > Start --->
 > 	if (itag)
 > 
 > 	... DELETED 27 lines ...
 > 
 > 
 > last_resort:
 > 	if (rpf)
 > 		goto e_inval;
 > 	*spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
 > Error --->
 > 	*itag = 0;
 > 	return 0;

Another case like the previous, no caller sends in a NULL itag.
Check removed in my sources...

 > [BUG] contradiction
 > /u2/engler/mc/oses/linux/2.4.4/net/ipv4/ip_options.c:257:ip_options_compile: ERROR:INTERNAL_NULL:252:257: [type=set] (set at line 252) Dereferencing NULL ptr "skb" illegally! [val=500]
 > 	int l;
 > 	unsigned char * iph;
 > 	unsigned char * optptr;
 > 	int optlen;
 > 	unsigned char * pp_ptr = NULL;
 > Start --->
 > 	struct rtable *rt = skb ? (struct rtable*)skb->dst : NULL;
 > 
 > 	if (!opt) {
 > 		opt = &(IPCB(skb)->opt);
 > 		memset(opt, 0, sizeof(struct ip_options));
 > Error --->
 > 		iph = skb->nh.raw;
 > 		opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr);
 > 		optptr = iph + sizeof(struct iphdr);
 > 		opt->is_data = 0;

How is this a contradiction?  The first thing sets 'rt' to NULL or
not, then we test '!opt' not '!rt' which is what I think you are
seeing :-)

If SKB is NULL, opt must be non-NULL and also opt->is_data must be
set in this case.  That is the invariant, and even though not %100
explicitly tested, this is what the comment above is trying to say.
At best the missing minor checks should be BUG() checks because they
are illegal states.

 > [BUG] contradiction
 > /u2/engler/mc/oses/linux/2.4.4/net/core/neighbour.c:317:neigh_create: ERROR:INTERNAL_NULL:312:317: [type=set] (set at line 312) Dereferencing NULL ptr "parms" illegally! [val=500]
 > 		return ERR_PTR(error);
 > 	}
 > 
 > 	/* Device specific setup. */
 > 	if (n->parms && n->parms->neigh_setup &&
 > Start --->
 > 	    (error = n->parms->neigh_setup(n)) < 0) {
 > 		neigh_release(n);
 > 		return ERR_PTR(error);
 > 	}
 > 
 > Error --->
 > 	n->confirmed = jiffies - (n->parms->base_reachable_time<<1);
 > 
 > 	hash_val = tbl->hash(pkey, dev);

I've added the obvious check, but I suspect the more correct fix is
to disallow NULL n->parms (and as a consequence disallow NULL
tbl->constructor since that constructor is the thing that hooks
in the n->parms).

Really, I didn't catch anyone sending a NULL parms in during a
quick perusal, and honestly it would crash instantly on non-x86
systems if it were NULL.  (Unfortunately, at least during boot,
the NULL address is actually mapped in the kernel on x86 :-( ).

 > ---------------------------------------------------------
 > [BUG] contradicts
 > /u2/engler/mc/oses/linux/2.4.4/net/ipv4/ip_input.c:325:ip_rcv_finish: ERROR:INTERNAL_NULL:319:325: [type=set] (set at line 319) Dereferencing NULL ptr "dst" illegally! [val=600]
 > 
 > 	/*
 > 	 *	Initialise the virtual path cache for the packet. It describes
 > 	 *	how the packet travels inside Linux networking.
 > 	 */ 
 > Start --->
 > 	if (skb->dst == NULL) {
 > 		if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))
 > 			goto drop; 
 > 	}
 > 
 > #ifdef CONFIG_NET_CLS_ROUTE
 > Error --->
 > 	if (skb->dst->tclassid) {
 > 		struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
 > 		u32 idx = skb->dst->tclassid;
 > 		st[idx&0xFF].o_packets++;

This one is OK.

The side effect of a successful ip_route_input call is that skb->dst
gets set to a non-NULL value.

 > ---------------------------------------------------------
 > [BUG] contradicts.
 > /u2/engler/mc/oses/linux/2.4.4/net/ipv4/devinet.c:544:devinet_ioctl: ERROR:INTERNAL_NULL:537:544: [type=set] (set at line 537) Dereferencing NULL ptr "ifa" illegally! [val=700]
 > 		for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
 > 			if (strcmp(ifr.ifr_name, ifa->ifa_label) == 0)
 > 				break;
 > 	}
 > 
 > Start --->
 > 	if (ifa == NULL && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) {
 > 		ret = -EADDRNOTAVAIL;
 > 		goto done;
 > 	}
 > 
 > 	switch(cmd) {
 > 		case SIOCGIFADDR:	/* Get interface address */
 > Error --->
 > 			sin->sin_addr.s_addr = ifa->ifa_local;
 > 			goto rarok;
 > 
 > 		case SIOCGIFBRDADDR:	/* Get the broadcast address */
 > ---------------------------------------------------------
 > [BUG] should be ||?
 > /u2/engler/mc/oses/linux/2.4.4/net/decnet/dn_dev.c:500:dn_dev_ioctl: ERROR:INTERNAL_NULL:493:500: [type=set] (set at line 493) Dereferencing NULL ptr "ifa" illegally! [val=700]
 > 		for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next)
 > 			if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
 > 				break;
 > 	}
 > 
 > Start --->
 > 	if (ifa == NULL && cmd != SIOCSIFADDR) {
 > 		ret = -EADDRNOTAVAIL;
 > 		goto done;
 > 	}
 > 
 > 	switch(cmd) {
 > 		case SIOCGIFADDR:
 > Error --->
 > 			*((dn_address *)sdn->sdn_nodeaddr) = ifa->ifa_local;
 > 			goto rarok;
 > 
 > 		case SIOCSIFADDR:

Checker is wrong in these two cases.

The "error" code you point to cannot be reached if cmd == SIOCGIFADDR
(for the dn_dev.c, likewise SIOCSIFADDR+SIOCSIFFLAGS in the devinet.c
case). In the dn_dev.c case, SIOCSIFADDR in that switch statement may
run if ifa == NULL.

Something is screwed with checker's flow graphs perhaps?  Else it
isn't doing exhaustive enough reachability determination.

 > ---------------------------------------------------------
 > [BUG] contradicts
 > /u2/engler/mc/oses/linux/2.4.4/net/decnet/dn_route.c:808:dn_route_output_slow: ERROR:INTERNAL_NULL:798:808: [type=set] (set at line 798) Dereferencing NULL ptr "neigh" illegally! [val=1000]
 > 	
 > 	rt->key.saddr  = src;
 > 	rt->rt_saddr   = src;
 > 	rt->key.daddr  = dst;
 > 	rt->rt_daddr   = dst;
 > Start --->
 > 	rt->key.oif    = neigh ? neigh->dev->ifindex : -1;
 > 	rt->key.iif    = 0;
 > 	rt->key.fwmark = 0;
 > 
 > 	rt->u.dst.neighbour = neigh;
 > 	rt->u.dst.dev = neigh ? neigh->dev : NULL;
 > 	rt->u.dst.lastuse = jiffies;
 > 	rt->u.dst.output = dn_output;
 > 	rt->u.dst.input  = dn_rt_bug;
 > 
 > Error --->
 > 	if (dn_dev_islocal(neigh->dev, rt->rt_daddr))
 > 		rt->u.dst.input = dn_nsp_rx;
 > 
 > 	hash = dn_hash(rt->key.saddr, rt->key.daddr);

Yeah, this one is wrong, I'll leave this to Steve Whitehouse though,
the DecNET maintainer.

 > [BUG]  seems like it, unless there is a weird DP going on.
 > /u2/engler/mc/oses/linux/2.4.4/net/econet/af_econet.c:310:econet_sendmsg: ERROR:INTERNAL_NULL:268:310: [type=set] (set at line 268) Dereferencing NULL ptr "saddr" illegally! [val=4200]
 > 
 > 	/*
 > 	 *	Get and verify the address. 
 > 	 */
 > 	 
 > Start --->
 > 	if (saddr == NULL) {
 > 
 > 	... DELETED 36 lines ...
 > 
 > 		skb_reserve(skb, (dev->hard_header_len+15)&~15);
 > 		skb->nh.raw = skb->data;
 > 		
 > 		eb = (struct ec_cb *)&skb->cb;
 > 		
 > Error --->
 > 		eb->cookie = saddr->cookie;
 > 		eb->sec = *saddr;
 > 		eb->sent = ec_tx_done;

Yep, this one is correct.  I don't know enough about econet to fix it
though... Philip?

Later,
David S. Miller
davem@redhat.com

  parent reply	other threads:[~2001-05-29 22:37 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-05-29 21:49 Dawson Engler
2001-05-29 22:36 ` Alexander Viro
2001-05-29 22:36 ` David S. Miller [this message]
2001-05-29 22:56   ` Steve Whitehouse
2001-05-29 23:09   ` Dawson Engler
2001-05-30  5:17 ` Andreas Dilger
2001-05-30  5:45   ` Alexander Viro
2001-05-30  6:49     ` Andreas Dilger
2001-05-30  6:58       ` Alexander Viro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=15124.9340.77101.588276@pizda.ninka.net \
    --to=davem@redhat.com \
    --cc=SteveW@ACM.org \
    --cc=engler@csl.Stanford.EDU \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mc@cs.Stanford.EDU \
    --cc=philb@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®