Package: linux-image-2.6.18-6-mckinley Version: 2.6.18.dfsg.1-24etch3 hi, i've encountered a problem with BIND9 running on oldstable. we're running native IPv6 and serving DNSSEC-signed zones, so the problem appears to be related to IPv6/UDP fragmentation. when the problem manifests itself the named process stops serving DNS requests and the process becomes unkillable. i am fairly certain that this is the same bug: http://www.mail-archive.com/netdev@vger.kernel.org/msg21249.html in particular, see: http://www.mail-archive.com/netdev@vger.kernel.org/msg23619.html the bug fix (132a55f3c5c0b1a364d32f65595ad8838c30a60e) was merged to 2.6.19 but never added to 2.6.18. it would probably be a good idea to add this fix in an oldstable kernel update. here is the BUG() dmesg output: kernel BUG at net/ipv6/ip6_output.c:699! named[1992]: bugcheck! 0 [1] Modules linked in: button xt_tcpudp xt_state ip_conntrack nfnetlink iptable_filter ip_tables x_tables dm_snapshot dm_mirror dm_mod ipv6 loop shpchp pci_hotplug ext3 jbd mbcache ide_cd cdrom generic mptspi mptscsih ohci_hcd ehci_hcd mptbase cmd64x cciss scsi_transport_spi usbcore ide_core scsi_mod e1000 thermal processor fan Pid: 1992, CPU 0, comm: named psr : 0000101008526030 ifs : 8000000000000916 ip : [<a000000204195ee0>] Not tainted ip is at ip6_output+0x5e0/0x1400 [ipv6] unat: 0000000000000000 pfs : 0000000000000916 rsc : 0000000000000003 rnat: 0000000000000000 bsps: 0000000000000000 pr : 0000000000569959 ldrs: 0000000000000000 ccv : 0000000000000000 fpsr: 0009804c8a70033f csd : 0000000000000000 ssd : 0000000000000000 b0 : a000000204195ee0 b6 : a0000001000b30a0 b7 : a000000100283c40 f6 : 1003e00000000000000a0 f7 : 1003e20c49ba5e353f7cf f8 : 1003e00000000000004e2 f9 : 1003e000000000fa00000 f10 : 1003e000000003b9aca00 f11 : 1003e431bde82d7b634db r1 : a0000001008db0e0 r2 : ffffffffffff41c8 r3 : a00000010068cf38 r8 : 000000000000002c r9 : 0000000000000000 r10 : a0000001006f3350 r11 : 0000000000004000 r12 : e0000040f9117aa0 r13 : e0000040f9110000 r14 : 0000000000004000 r15 : a00000010068cf38 r16 : a00000010068cf40 r17 : 0000000000004000 r18 : e0000040f9110fd4 r19 : 0000000000000000 r20 : 0000000000000000 r21 : 0000000000000000 r22 : 0000000000000004 r23 : 0000000000000000 r24 : e0000040f9110fd4 r25 : 0000000000000750 r26 : 0000000000000730 r27 : 0000000000000073 r28 : 0000000000000073 r29 : 000000000027ffd8 r30 : 00000027ffd80000 r31 : 00000000000027d8 Call Trace: [<a000000100012f20>] show_stack+0x40/0xa0 sp=e0000040f9117630 bsp=e0000040f9111608 [<a000000100013820>] show_regs+0x840/0x880 sp=e0000040f9117800 bsp=e0000040f91115a8 [<a000000100034420>] die+0x1c0/0x2c0 sp=e0000040f9117800 bsp=e0000040f9111560 [<a000000100034570>] die_if_kernel+0x50/0x80 sp=e0000040f9117820 bsp=e0000040f9111530 [<a000000100035cb0>] ia64_bad_break+0x270/0x4a0 sp=e0000040f9117820 bsp=e0000040f9111508 [<a00000010000bc40>] ia64_leave_kernel+0x0/0x280 sp=e0000040f91178d0 bsp=e0000040f9111508 [<a000000204195ee0>] ip6_output+0x5e0/0x1400 [ipv6] sp=e0000040f9117aa0 bsp=e0000040f9111458 [<a0000002041979c0>] ip6_push_pending_frames+0x940/0xb80 [ipv6] sp=e0000040f9117ab0 bsp=e0000040f9111408 [<a0000002041c59e0>] udp_v6_push_pending_frames+0x6a0/0x700 [ipv6] sp=e0000040f9117ae0 bsp=e0000040f91113b8 [<a0000002041c8ad0>] udpv6_sendmsg+0xed0/0x14a0 [ipv6] sp=e0000040f9117ae0 bsp=e0000040f9111330 [<a00000010047b810>] inet_sendmsg+0xd0/0x100 sp=e0000040f9117b60 bsp=e0000040f91112f8 [<a0000001003add70>] sock_sendmsg+0x1f0/0x240 sp=e0000040f9117b60 bsp=e0000040f91112c0 [<a0000001003b2960>] sys_sendmsg+0x4a0/0x5a0 sp=e0000040f9117cc0 bsp=e0000040f9111228 [<a00000010000baa0>] ia64_ret_from_syscall+0x0/0x20 sp=e0000040f9117e30 bsp=e0000040f9111228 [<a000000000010620>] __start_ivt_text+0xffffffff00010620/0x400 sp=e0000040f9118000 bsp=e0000040f9111228 -- Robert Edmonds edmonds@debian.org
From 132a55f3c5c0b1a364d32f65595ad8838c30a60e Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Tue, 3 Oct 2006 14:34:00 -0700 Subject: [PATCH] [UDP6]: Fix flowi clobbering The udp6_sendmsg function uses a shared buffer to store the flow without taking any locks. This leads to races with SMP. This patch moves the flowi object onto the stack. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: James Morris <jmorris@namei.org> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv6/udp.c | 62 ++++++++++++++++++++++++++++---------------------------- 1 files changed, 31 insertions(+), 31 deletions(-) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9662561..552ec0f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -546,7 +546,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct in6_addr *daddr, *final_p = NULL, final; struct ipv6_txoptions *opt = NULL; struct ip6_flowlabel *flowlabel = NULL; - struct flowi *fl = &inet->cork.fl; + struct flowi fl; struct dst_entry *dst; int addr_len = msg->msg_namelen; int ulen = len; @@ -626,19 +626,19 @@ do_udp_sendmsg: } ulen += sizeof(struct udphdr); - memset(fl, 0, sizeof(*fl)); + memset(&fl, 0, sizeof(fl)); if (sin6) { if (sin6->sin6_port == 0) return -EINVAL; - fl->fl_ip_dport = sin6->sin6_port; + fl.fl_ip_dport = sin6->sin6_port; daddr = &sin6->sin6_addr; if (np->sndflow) { - fl->fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; - if (fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) { - flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel); + fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; + if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); if (flowlabel == NULL) return -EINVAL; daddr = &flowlabel->dst; @@ -656,32 +656,32 @@ do_udp_sendmsg: if (addr_len >= sizeof(struct sockaddr_in6) && sin6->sin6_scope_id && ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) - fl->oif = sin6->sin6_scope_id; + fl.oif = sin6->sin6_scope_id; } else { if (sk->sk_state != TCP_ESTABLISHED) return -EDESTADDRREQ; - fl->fl_ip_dport = inet->dport; + fl.fl_ip_dport = inet->dport; daddr = &np->daddr; - fl->fl6_flowlabel = np->flow_label; + fl.fl6_flowlabel = np->flow_label; connected = 1; } - if (!fl->oif) - fl->oif = sk->sk_bound_dev_if; + if (!fl.oif) + fl.oif = sk->sk_bound_dev_if; if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_txoptions)); opt->tot_len = sizeof(*opt); - err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass); + err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass); if (err < 0) { fl6_sock_release(flowlabel); return err; } - if ((fl->fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { - flowlabel = fl6_sock_lookup(sk, fl->fl6_flowlabel); + if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { + flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); if (flowlabel == NULL) return -EINVAL; } @@ -695,39 +695,39 @@ do_udp_sendmsg: opt = fl6_merge_options(&opt_space, flowlabel, opt); opt = ipv6_fixup_options(&opt_space, opt); - fl->proto = IPPROTO_UDP; - ipv6_addr_copy(&fl->fl6_dst, daddr); - if (ipv6_addr_any(&fl->fl6_src) && !ipv6_addr_any(&np->saddr)) - ipv6_addr_copy(&fl->fl6_src, &np->saddr); - fl->fl_ip_sport = inet->sport; + fl.proto = IPPROTO_UDP; + ipv6_addr_copy(&fl.fl6_dst, daddr); + if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) + ipv6_addr_copy(&fl.fl6_src, &np->saddr); + fl.fl_ip_sport = inet->sport; /* merge ip6_build_xmit from ip6_output */ if (opt && opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; - ipv6_addr_copy(&final, &fl->fl6_dst); - ipv6_addr_copy(&fl->fl6_dst, rt0->addr); + ipv6_addr_copy(&final, &fl.fl6_dst); + ipv6_addr_copy(&fl.fl6_dst, rt0->addr); final_p = &final; connected = 0; } - if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { - fl->oif = np->mcast_oif; + if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { + fl.oif = np->mcast_oif; connected = 0; } - security_sk_classify_flow(sk, fl); + security_sk_classify_flow(sk, &fl); - err = ip6_sk_dst_lookup(sk, &dst, fl); + err = ip6_sk_dst_lookup(sk, &dst, &fl); if (err) goto out; if (final_p) - ipv6_addr_copy(&fl->fl6_dst, final_p); + ipv6_addr_copy(&fl.fl6_dst, final_p); - if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto out; if (hlimit < 0) { - if (ipv6_addr_is_multicast(&fl->fl6_dst)) + if (ipv6_addr_is_multicast(&fl.fl6_dst)) hlimit = np->mcast_hops; else hlimit = np->hop_limit; @@ -763,7 +763,7 @@ back_from_confirm: do_append_data: up->len += ulen; err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, - sizeof(struct udphdr), hlimit, tclass, opt, fl, + sizeof(struct udphdr), hlimit, tclass, opt, &fl, (struct rt6_info*)dst, corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); if (err) @@ -774,10 +774,10 @@ do_append_data: if (dst) { if (connected) { ip6_dst_store(sk, dst, - ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? + ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? &np->daddr : NULL, #ifdef CONFIG_IPV6_SUBTREES - ipv6_addr_equal(&fl->fl6_src, &np->saddr) ? + ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? &np->saddr : #endif NULL); -- 1.6.3.3
Attachment:
signature.asc
Description: Digital signature