Fri Dec 16 00:58:00 2011 UTC ()
Take softnet_lock and kernel lock in frag6_slowtimo and frag6_fasttimo,
similar to how it's done with other protocols.

If we don't do this sending ICMPv6 messages in this path can cause races
in network interface drivers.


(jakllsch)
diff -r1.50 -r1.51 src/sys/netinet6/frag6.c

cvs diff -r1.50 -r1.51 src/sys/netinet6/frag6.c (expand / switch to unified diff)

--- src/sys/netinet6/frag6.c 2011/11/04 00:22:33 1.50
+++ src/sys/netinet6/frag6.c 2011/12/16 00:57:59 1.51
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: frag6.c,v 1.50 2011/11/04 00:22:33 zoltan Exp $ */ 1/* $NetBSD: frag6.c,v 1.51 2011/12/16 00:57:59 jakllsch Exp $ */
2/* $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun Exp $ */ 2/* $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -21,27 +21,27 @@ @@ -21,27 +21,27 @@
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.50 2011/11/04 00:22:33 zoltan Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.51 2011/12/16 00:57:59 jakllsch Exp $");
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38#include <sys/malloc.h> 38#include <sys/malloc.h>
39#include <sys/mbuf.h> 39#include <sys/mbuf.h>
40#include <sys/domain.h> 40#include <sys/domain.h>
41#include <sys/protosw.h> 41#include <sys/protosw.h>
42#include <sys/socket.h> 42#include <sys/socket.h>
43#include <sys/socketvar.h> 43#include <sys/socketvar.h>
44#include <sys/errno.h> 44#include <sys/errno.h>
45#include <sys/time.h> 45#include <sys/time.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/syslog.h> 47#include <sys/syslog.h>
@@ -634,67 +634,79 @@ frag6_insque(struct ip6q *new, struct ip @@ -634,67 +634,79 @@ frag6_insque(struct ip6q *new, struct ip
634void 634void
635frag6_remque(struct ip6q *p6) 635frag6_remque(struct ip6q *p6)
636{ 636{
637 637
638 KASSERT(mutex_owned(&frag6_lock)); 638 KASSERT(mutex_owned(&frag6_lock));
639 639
640 p6->ip6q_prev->ip6q_next = p6->ip6q_next; 640 p6->ip6q_prev->ip6q_next = p6->ip6q_next;
641 p6->ip6q_next->ip6q_prev = p6->ip6q_prev; 641 p6->ip6q_next->ip6q_prev = p6->ip6q_prev;
642} 642}
643 643
644void 644void
645frag6_fasttimo(void) 645frag6_fasttimo(void)
646{ 646{
 647 mutex_enter(softnet_lock);
 648 KERNEL_LOCK(1, NULL);
 649
647 if (frag6_drainwanted) { 650 if (frag6_drainwanted) {
648 frag6_drain(); 651 frag6_drain();
649 frag6_drainwanted = 0; 652 frag6_drainwanted = 0;
650 } 653 }
 654
 655 KERNEL_UNLOCK_ONE(NULL);
 656 mutex_exit(softnet_lock);
651} 657}
652 658
653/* 659/*
654 * IPv6 reassembling timer processing; 660 * IPv6 reassembling timer processing;
655 * if a timer expires on a reassembly 661 * if a timer expires on a reassembly
656 * queue, discard it. 662 * queue, discard it.
657 */ 663 */
658void 664void
659frag6_slowtimo(void) 665frag6_slowtimo(void)
660{ 666{
661 struct ip6q *q6; 667 struct ip6q *q6;
662 668
 669 mutex_enter(softnet_lock);
 670 KERNEL_LOCK(1, NULL);
 671
663 mutex_enter(&frag6_lock); 672 mutex_enter(&frag6_lock);
664 q6 = ip6q.ip6q_next; 673 q6 = ip6q.ip6q_next;
665 if (q6) 674 if (q6)
666 while (q6 != &ip6q) { 675 while (q6 != &ip6q) {
667 --q6->ip6q_ttl; 676 --q6->ip6q_ttl;
668 q6 = q6->ip6q_next; 677 q6 = q6->ip6q_next;
669 if (q6->ip6q_prev->ip6q_ttl == 0) { 678 if (q6->ip6q_prev->ip6q_ttl == 0) {
670 IP6_STATINC(IP6_STAT_FRAGTIMEOUT); 679 IP6_STATINC(IP6_STAT_FRAGTIMEOUT);
671 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 680 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
672 frag6_freef(q6->ip6q_prev); 681 frag6_freef(q6->ip6q_prev);
673 } 682 }
674 } 683 }
675 /* 684 /*
676 * If we are over the maximum number of fragments 685 * If we are over the maximum number of fragments
677 * (due to the limit being lowered), drain off 686 * (due to the limit being lowered), drain off
678 * enough to get down to the new limit. 687 * enough to get down to the new limit.
679 */ 688 */
680 while (frag6_nfragpackets > (u_int)ip6_maxfragpackets && 689 while (frag6_nfragpackets > (u_int)ip6_maxfragpackets &&
681 ip6q.ip6q_prev) { 690 ip6q.ip6q_prev) {
682 IP6_STATINC(IP6_STAT_FRAGOVERFLOW); 691 IP6_STATINC(IP6_STAT_FRAGOVERFLOW);
683 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 692 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
684 frag6_freef(ip6q.ip6q_prev); 693 frag6_freef(ip6q.ip6q_prev);
685 } 694 }
686 mutex_exit(&frag6_lock); 695 mutex_exit(&frag6_lock);
687 696
 697 KERNEL_UNLOCK_ONE(NULL);
 698 mutex_exit(softnet_lock);
 699
688#if 0 700#if 0
689 /* 701 /*
690 * Routing changes might produce a better route than we last used; 702 * Routing changes might produce a better route than we last used;
691 * make sure we notice eventually, even if forwarding only for one 703 * make sure we notice eventually, even if forwarding only for one
692 * destination and the cache is never replaced. 704 * destination and the cache is never replaced.
693 */ 705 */
694 rtcache_free(&ip6_forward_rt); 706 rtcache_free(&ip6_forward_rt);
695 rtcache_free(&ipsrcchk_rt); 707 rtcache_free(&ipsrcchk_rt);
696#endif 708#endif
697 709
698} 710}
699 711
700void 712void