kern/172963: Kernel panic in udp_input()
Julien Charbon
jcharbon at verisign.com
Wed Oct 24 16:10:01 UTC 2012
The following reply was made to PR kern/172963; it has been noted by GNATS.
From: Julien Charbon <jcharbon at verisign.com>
To: bug-followup at FreeBSD.org
Cc:
Subject: Re: kern/172963: Kernel panic in udp_input()
Date: Wed, 24 Oct 2012 17:47:06 +0200
Below the patch used with previous instructions that highlights and logs this race condition:
Index: sys/netinet/in_pcb.c
===================================================================
--- sys/netinet/in_pcb.c (revision 32)
+++ sys/netinet/in_pcb.c (working copy)
@@ -1055,8 +1055,10 @@
INP_WLOCK_ASSERT(inp);
inp->inp_refcount--;
- if (inp->inp_refcount > 0)
+ if (inp->inp_refcount > 0) {
+ inp->inp_flags2 |= INP_FREED;
return (0);
+ }
in_pcbfree_internal(inp);
return (1);
}
Index: sys/netinet/in_pcb.h
===================================================================
--- sys/netinet/in_pcb.h (revision 32)
+++ sys/netinet/in_pcb.h (working copy)
@@ -443,6 +443,7 @@
*/
#define INP_LLE_VALID 0x00000001 /* cached lle is valid */
#define INP_RT_VALID 0x00000002 /* cached rtentry is valid */
+#define INP_FREED 0x00000004 /* inp no more valid */
#define INPLOOKUP_WILDCARD 1
#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c (revision 32)
+++ sys/netinet/udp_usrreq.c (working copy)
@@ -624,6 +624,13 @@
INP_RUNLOCK(inp);
goto badunlocked;
}
+ /* Check inp state */
+ if ((inp->inp_flags2 & INP_FREED) && (inp->inp_socket == NULL)) {
+ log(LOG_INFO, "udp_input(): Using freed inp %p inp->inp_refcount %d\n",
+ inp, inp->inp_refcount);
+ INP_RUNLOCK(inp);
+ goto badunlocked;
+ }
up = intoudpcb(inp);
if (up->u_tun_func == NULL) {
udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in);
@@ -797,6 +804,10 @@
for (i = 0; i < n; i++) {
inp = inp_list[i];
INP_WLOCK(inp);
+ if ((inp->inp_flags2 & INP_FREED) && (inp->inp_socket == NULL)) {
+ log(LOG_INFO, "udp_pcblist(): Using freed inp %p inp->inp_refcount %d\n",
+ inp, inp->inp_refcount);
+ }
if (!in_pcbrele(inp))
INP_WUNLOCK(inp);
}
@@ -1443,6 +1454,7 @@
inp = sotoinpcb(so);
inp->inp_vflag |= INP_IPV4;
inp->inp_ip_ttl = V_ip_defttl;
+ inp->inp_flags2 = 0;
error = udp_newudpcb(inp);
if (error) {
More information about the freebsd-bugs
mailing list