From 994b02bdbe5594fd1a124bbce93b3f43338b7c2d Mon Sep 17 00:00:00 2001 From: tls Date: Thu, 1 Apr 2010 00:24:41 +0000 Subject: [PATCH] After discussion with ad@: it appears that KERNEL_LOCK also protects the driver output path (that is, ifp->if_output()). In the case of entry through the socket code, we are fine, because pru_usrreq takes KERNEL_LOCK. However, there are a few other ways to cause output which require protection: 1) direct calls to tcp_output() in tcp_input() 2) fast-forwarding code (ip_flow) -- protected elsewise against itself by the softnet lock. 3) *Possibly* the ARP code. I have currently persuaded myself that it is safe because of how it's called. 4) Possibly the ICMP code. This change addresses #1 and #2. --- sys/netinet/ip_flow.c | 6 ++++-- sys/netinet/tcp_input.c | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sys/netinet/ip_flow.c b/sys/netinet/ip_flow.c index e0e5ee7b84ab..5d7e23d35e8e 100644 --- a/sys/netinet/ip_flow.c +++ b/sys/netinet/ip_flow.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_flow.c,v 1.58 2009/03/15 22:16:09 cegger Exp $ */ +/* $NetBSD: ip_flow.c,v 1.59 2010/04/01 00:24:41 tls Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.58 2009/03/15 22:16:09 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.59 2010/04/01 00:24:41 tls Exp $"); #include #include @@ -301,12 +301,14 @@ ipflow_fastforward(struct mbuf *m) else dst = rtcache_getdst(&ipf->ipf_ro); + KERNEL_LOCK(1, NULL); if ((error = (*rt->rt_ifp->if_output)(rt->rt_ifp, m, dst, rt)) != 0) { if (error == ENOBUFS) ipf->ipf_dropped++; else ipf->ipf_errors++; } + KERNEL_UNLOCK_ONE(NULL); return 1; } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 1958aaeda91e..58085edef061 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_input.c,v 1.300 2010/01/26 18:09:07 pooka Exp $ */ +/* $NetBSD: tcp_input.c,v 1.301 2010/04/01 00:24:41 tls Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -145,7 +145,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.300 2010/01/26 18:09:07 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.301 2010/04/01 00:24:41 tls Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -1787,7 +1787,9 @@ after_listen: sowwakeup(so); if (so->so_snd.sb_cc) + KERNEL_LOCK(1, NULL); (void) tcp_output(tp); + KERNEL_UNLOCK_ONE(NULL); if (tcp_saveti) m_freem(tcp_saveti); return; @@ -1883,7 +1885,9 @@ after_listen: sorwakeup(so); tcp_setup_ack(tp, th); if (tp->t_flags & TF_ACKNOW) + KERNEL_LOCK(1, NULL); (void) tcp_output(tp); + KERNEL_UNLOCK_ONE(NULL); if (tcp_saveti) m_freem(tcp_saveti); return; @@ -2369,7 +2373,9 @@ after_listen: goto drop; } else if (tp->t_dupacks > tcprexmtthresh) { tp->snd_cwnd += tp->t_segsz; + KERNEL_LOCK(1, NULL); (void) tcp_output(tp); + KERNEL_UNLOCK_ONE(NULL); goto drop; } } else { @@ -2730,7 +2736,9 @@ dodata: /* XXX */ * Return any desired output. */ if (needoutput || (tp->t_flags & TF_ACKNOW)) { + KERNEL_LOCK(1, NULL); (void) tcp_output(tp); + KERNEL_UNLOCK_ONE(NULL); } if (tcp_saveti) m_freem(tcp_saveti); @@ -2767,7 +2775,9 @@ dropafterack_ratelim: dropafterack2: m_freem(m); tp->t_flags |= TF_ACKNOW; + KERNEL_LOCK(1, NULL); (void) tcp_output(tp); + KERNEL_UNLOCK_ONE(NULL); if (tcp_saveti) m_freem(tcp_saveti); return;