Skip to contentSkip to conversation

linux 2.[45].x: negative inode numbers in /proc/net/*

PROBLEM+PATCH Arnaud Giersch 2 participants 2 messages Feb 20, 2002 – Mar 5, 2002

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Hello,

I think I found a little but annoying bug in the /proc/net reporting functions for various types of sockets: when the inode numbers become large enough, they are printed as negative values.

For example in /proc/net/{udp,unix} (kernel 2.4.17, i686):

        $ cat /proc/net/udp
          sl  ...  inode
        [...]
          79: ...  -1834994132 2 dba94580
        [...]
        $ cat /proc/net/unix
        Num       ...  Inode Path
        [...]
        c35b1580: ...  -2123437312 /tmp/.X11-unix/X0
        ce571040: ...  -2123437313
        [...]

I found it because it causes netstat <= 1.60 to segfault (there was of course a bug in netstat too).

This can be reproduced using brute force: keep opening and closing sockets during enough time in order to have inode numbers become greater than 2^31 (this takes a few hours on my AMD Duron 800).

The problem exists apparently in all 2.4.x and 2.5.x kernel versions.

The reason is that the inode numbers are printed as signed long ("%ld" printf format) instead of unsigned long ("%lu" printf format) as it should be.

I grep'ed the kernel source net subdirectory in order to find other similar bugs. I found that it is present for {ipv4,ipv6}/{raw,udp} and unix sockets.

Here is my patch against kernel version 2.4.17:

<======================================================================>

net/ipv4/raw.c +1 -1
diff -Naur linux.orig/net/ipv4/raw.c linux/net/ipv4/raw.c
@@ -631,7 +631,7 @@
 	      srcp  = sp->num;
 
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
-		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
+		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
 		i, src, srcp, dest, destp, sp->state, 
 		atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
 		0, 0L, 0,
net/ipv4/udp.c +1 -1
diff -Naur linux.orig/net/ipv4/udp.c linux/net/ipv4/udp.c
@@ -957,7 +957,7 @@
 	destp = ntohs(sp->dport);
 	srcp  = ntohs(sp->sport);
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
-		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
+		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
 		i, src, srcp, dest, destp, sp->state, 
 		atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
 		0, 0L, 0,
net/ipv6/raw.c +1 -1
diff -Naur linux.orig/net/ipv6/raw.c linux/net/ipv6/raw.c
@@ -761,7 +761,7 @@
 	srcp  = sp->num;
 	sprintf(tmpbuf,
 		"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		"%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
+		"%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
 		i,
 		src->s6_addr32[0], src->s6_addr32[1],
 		src->s6_addr32[2], src->s6_addr32[3], srcp,
net/ipv6/udp.c +1 -1
diff -Naur linux.orig/net/ipv6/udp.c linux/net/ipv6/udp.c
@@ -916,7 +916,7 @@
 	srcp  = ntohs(sp->sport);
 	sprintf(tmpbuf,
 		"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		"%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
+		"%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
 		i,
 		src->s6_addr32[0], src->s6_addr32[1],
 		src->s6_addr32[2], src->s6_addr32[3], srcp,
net/unix/af_unix.c +1 -1
diff -Naur linux.orig/net/unix/af_unix.c linux/net/unix/af_unix.c
@@ -1742,7 +1742,7 @@
 	{
 		unix_state_rlock(s);
 
-		len+=sprintf(buffer+len,"%p: %08X %08X %08X %04X %02X %5ld",
+		len+=sprintf(buffer+len,"%p: %08X %08X %08X %04X %02X %5lu",
 			s,
 			atomic_read(&s->refcnt),
 			0,

<======================================================================>

Greetings

Signature · 1 line
Arnaud
#1 lore raw

From: Arnaud Giersch <[email protected]>
Date: 20 Feb 2002 21:06:39 +0100

I think I found a little but annoying bug in the /proc/net reporting functions for various types of sockets: when the inode numbers become large enough, they are printed as negative values.

Thanks, I've applied your patch.