[Crash-utility] [PATCH] Fix a segfault by "net" command

Dave Anderson anderson at redhat.com
Wed Nov 22 21:44:02 UTC 2017



----- Original Message -----
> 
> 
> ----- Original Message -----
> > Hi Dave,
> > 
> > When a network device has a lot of IP addresses, the "net" command
> > can generate a segmentation fault due to a buffer overflow without
> > this patch.  I have seen several vmcores like that in customer support.
> 
> Thanks, Kasuhito -- I will give the patch a test run next week after the
> holiday.

Actually, before I test the patch, can you fix get_device_address() and its
three callers now that you have changed the function's return type:

  $  make warn
  TARGET: X86_64
   CRASH: 7.2.1rc20
     GDB: 7.6

  cc -c -g -DX86_64 -DLZO -DSNAPPY -DGDB_7_6  build_data.c -Wall -O2 -Wstrict-prototypes -Wmissing-prototypes -fstack-protector -Wformat-security 
  cc -c -g -DX86_64 -DLZO -DSNAPPY -DGDB_7_6  net.c -Wall -O2 -Wstrict-prototypes -Wmissing-prototypes -fstack-protector -Wformat-security 
  net.c: In function 'get_device_address':
  net.c:899:3: warning: 'return' with no value, in function returning non-void [-Wreturn-type]
     return;
     ^
...

Thanks,
  Dave





> 
> Dave
> 
> > 
> >   # for i in {1..250} ; do ifconfig eth1:$i 192.168.1.$i ; done
> >   # crash
> >   ...
> >   crash> net
> >      NET_DEVICE     NAME   IP ADDRESS(ES)
> >   ffff88007faab000  lo     127.0.0.1
> >   ffff88003e097000  eth0   192.168.122.182
> >   ffff88003e12b000  eth1   192.168.1.1, 192.168.1.2, ..., 192.168.1.250
> >   ffff88003e12e000  eth2
> >   Segmentation fault (core dumped)
> > 
> > Signed-off-by: Kazuhito Hagio <k-hagio at ab.jp.nec.com>
> > ---
> >  net.c | 48 +++++++++++++++++++++++++++++++++++-------------
> >  1 file changed, 35 insertions(+), 13 deletions(-)
> > 
> > diff --git a/net.c b/net.c
> > index bb86963..7b70dc4 100644
> > --- a/net.c
> > +++ b/net.c
> > @@ -70,7 +70,7 @@ static void show_net_devices_v3(ulong);
> >  static void print_neighbour_q(ulong, int);
> >  static void get_netdev_info(ulong, struct devinfo *);
> >  static void get_device_name(ulong, char *);
> > -static void get_device_address(ulong, char *);
> > +static long get_device_address(ulong, char **, long);
> >  static void get_sock_info(ulong, char *);
> >  static void dump_arp(void);
> >  static void arp_state_to_flags(unsigned char);
> > @@ -441,7 +441,8 @@ show_net_devices(ulong task)
> >  {
> >  	ulong next;
> >  	long flen;
> > -	char buf[BUFSIZE];
> > +	char *buf;
> > +	long buflen = BUFSIZE;
> >  
> >  	if (symbol_exists("dev_base_head")) {
> >  		show_net_devices_v2(task);
> > @@ -459,6 +460,7 @@ show_net_devices(ulong task)
> >  	if (!net->netdevice || !next)
> >  		return;
> >  
> > +	buf = GETBUF(buflen);
> >  	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
> >  
> >  	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
> > @@ -472,12 +474,14 @@ show_net_devices(ulong task)
> >  		get_device_name(next, buf);
> >  		fprintf(fp, "%-6s ", buf);
> >  
> > -		get_device_address(next, buf);
> > +		buflen = get_device_address(next, &buf, buflen);
> >  		fprintf(fp, "%s\n", buf);
> >  
> >          	readmem(next+net->dev_next, KVADDR, &next,
> >  			sizeof(void *), "(net_)device.next", FAULT_ON_ERROR);
> >  	} while (next);
> > +
> > +	FREEBUF(buf);
> >  }
> >  
> >  static void
> > @@ -485,13 +489,15 @@ show_net_devices_v2(ulong task)
> >  {
> >  	struct list_data list_data, *ld;
> >  	char *net_device_buf;
> > -	char buf[BUFSIZE];
> > +	char *buf;
> > +	long buflen = BUFSIZE;
> >  	int ndevcnt, i;
> >  	long flen;
> >  
> >  	if (!net->netdevice) /* initialized in net_init() */
> >  		return;
> >  
> > +	buf = GETBUF(buflen);
> >  	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
> >  
> >  	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
> > @@ -521,12 +527,13 @@ show_net_devices_v2(ulong task)
> >  		get_device_name(ld->list_ptr[i], buf);
> >  		fprintf(fp, "%-6s ", buf);
> >  
> > -		get_device_address(ld->list_ptr[i], buf);
> > +		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
> >  		fprintf(fp, "%s\n", buf);
> >  	}
> >  	
> >  	FREEBUF(ld->list_ptr);
> >  	FREEBUF(net_device_buf);
> > +	FREEBUF(buf);
> >  }
> >  
> >  static void
> > @@ -535,13 +542,15 @@ show_net_devices_v3(ulong task)
> >  	ulong nsproxy_p, net_ns_p;
> >  	struct list_data list_data, *ld;
> >  	char *net_device_buf;
> > -	char buf[BUFSIZE];
> > +	char *buf;
> > +	long buflen = BUFSIZE;
> >  	int ndevcnt, i;
> >  	long flen;
> >  
> >  	if (!net->netdevice) /* initialized in net_init() */
> >  		return;
> >  
> > +	buf = GETBUF(buflen);
> >  	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
> >  
> >  	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
> > @@ -581,12 +590,13 @@ show_net_devices_v3(ulong task)
> >  		get_device_name(ld->list_ptr[i], buf);
> >  		fprintf(fp, "%-6s ", buf);
> >  
> > -		get_device_address(ld->list_ptr[i], buf);
> > +		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
> >  		fprintf(fp, "%s\n", buf);
> >  	}
> >  	
> >  	FREEBUF(ld->list_ptr);
> >  	FREEBUF(net_device_buf);
> > +	FREEBUF(buf);
> >  }
> >  
> >  /*
> > @@ -869,13 +879,18 @@ get_device_name(ulong devaddr, char *buf)
> >   *  in_ifaddr->ifa_next points to the next in_ifaddr in the list (if any).
> >   *
> >   */
> > -static void
> > -get_device_address(ulong devaddr, char *buf)
> > +static long
> > +get_device_address(ulong devaddr, char **bufp, long buflen)
> >  {
> >  	ulong ip_ptr, ifa_list;
> >  	struct in_addr ifa_address;
> > +	char *buf;
> > +	char buf2[BUFSIZE];
> > +	long pos = 0;
> >  
> > -	BZERO(buf, BUFSIZE);
> > +	buf = *bufp;
> > +	BZERO(buf, buflen);
> > +	BZERO(buf2, BUFSIZE);
> >  
> >          readmem(devaddr + net->dev_ip_ptr, KVADDR,
> >          	&ip_ptr, sizeof(ulong), "ip_ptr", FAULT_ON_ERROR);
> > @@ -891,13 +906,20 @@ get_device_address(ulong devaddr, char *buf)
> >          		&ifa_address, sizeof(struct in_addr), "ifa_address",
> >  			FAULT_ON_ERROR);
> >  
> > -		sprintf(&buf[strlen(buf)], "%s%s",
> > -			strlen(buf) ? ", " : "",
> > -			inet_ntoa(ifa_address));
> > +		sprintf(buf2, "%s%s", pos ? ", " : "", inet_ntoa(ifa_address));
> > +		if (pos + strlen(buf2) >= buflen) {
> > +			RESIZEBUF(*bufp, buflen, buflen * 2);
> > +			buf = *bufp;
> > +			BZERO(buf + buflen, buflen);
> > +			buflen *= 2;
> > +		}
> > +		BCOPY(buf2, &buf[pos], strlen(buf2));
> > +		pos += strlen(buf2);
> >  
> >          	readmem(ifa_list + OFFSET(in_ifaddr_ifa_next), KVADDR,
> >          		&ifa_list, sizeof(ulong), "ifa_next", FAULT_ON_ERROR);
> >  	}
> > +	return buflen;
> >  }
> >  
> >  /*
> > --
> > 1.8.3.1
> > 
> > --
> > Crash-utility mailing list
> > Crash-utility at redhat.com
> > https://www.redhat.com/mailman/listinfo/crash-utility
> > 
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
> 




More information about the Crash-utility mailing list