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.
# 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(a)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