From 684de409acff8b1fe8bf188d75ff2f99c624387d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 Feb 2009 00:49:55 -0800 Subject: ipv6: Disallow rediculious flowlabel option sizes. Just like PKTINFO, limit the options area to 64K. Based upon report by Eric Sesterhenn and analysis by Roland Dreier. Signed-off-by: David S. Miller --- net/ipv6/ip6_flowlabel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index c62dd24..7712578 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -323,17 +323,21 @@ static struct ip6_flowlabel * fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *err_p) { - struct ip6_flowlabel *fl; + struct ip6_flowlabel *fl = NULL; int olen; int addr_type; int err; + olen = optlen - CMSG_ALIGN(sizeof(*freq)); + err = -EINVAL; + if (olen > 64 * 1024) + goto done; + err = -ENOMEM; fl = kzalloc(sizeof(*fl), GFP_KERNEL); if (fl == NULL) goto done; - olen = optlen - CMSG_ALIGN(sizeof(*freq)); if (olen > 0) { struct msghdr msg; struct flowi flowi; -- cgit v1.1 From efc683fc2a692735029067b4f939af2a3625e31d Mon Sep 17 00:00:00 2001 From: Gautam Kachroo Date: Fri, 6 Feb 2009 00:52:04 -0800 Subject: neigh: some entries can be skipped during dumping neightbl_dump_info and neigh_dump_table can skip entries if the *fill*info functions return an error. This results in an incomplete dump ((invoked by netlink requests for RTM_GETNEIGHTBL or RTM_GETNEIGH) nidx and idx should not be incremented if the current entry was not placed in the output buffer Signed-off-by: Gautam Kachroo Signed-off-by: David S. Miller --- net/core/neighbour.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f66c58d..278a142 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1994,8 +1994,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) if (!net_eq(neigh_parms_net(p), net)) continue; - if (nidx++ < neigh_skip) - continue; + if (nidx < neigh_skip) + goto next; if (neightbl_fill_param_info(skb, tbl, p, NETLINK_CB(cb->skb).pid, @@ -2003,6 +2003,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) RTM_NEWNEIGHTBL, NLM_F_MULTI) <= 0) goto out; + next: + nidx++; } neigh_skip = 0; @@ -2082,12 +2084,10 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, if (h > s_h) s_idx = 0; for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { - int lidx; if (dev_net(n->dev) != net) continue; - lidx = idx++; - if (lidx < s_idx) - continue; + if (idx < s_idx) + goto next; if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, @@ -2096,6 +2096,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, rc = -1; goto out; } + next: + idx++; } } read_unlock_bh(&tbl->lock); -- cgit v1.1 From 2783ef23128ad0a4b34e4121c1f7ff664785712f Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Fri, 6 Feb 2009 01:59:12 -0800 Subject: udp: Fix potential wrong ip_hdr(skb) pointers Like the UDP header fix, pskb_may_pull() can potentially alter the SKB buffer. Thus the saddr and daddr, pointers may point to the old skb->data buffer. I haven't seen corruptions, as its only seen if the old skb->data buffer were reallocated by another user and written into very quickly (or poison'd by SLAB debugging). Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- net/ipv4/udp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index cc3a0a0..c47c989 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1234,8 +1234,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, struct udphdr *uh; unsigned short ulen; struct rtable *rt = (struct rtable*)skb->dst; - __be32 saddr = ip_hdr(skb)->saddr; - __be32 daddr = ip_hdr(skb)->daddr; + __be32 saddr, daddr; struct net *net = dev_net(skb->dev); /* @@ -1259,6 +1258,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (udp4_csum_init(skb, uh, proto)) goto csum_error; + saddr = ip_hdr(skb)->saddr; + daddr = ip_hdr(skb)->daddr; + if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) return __udp4_lib_mcast_deliver(net, skb, uh, saddr, daddr, udptable); -- cgit v1.1 From 15bde72738f373aa060ececeda8e064e4f924360 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 6 Feb 2009 21:50:52 -0800 Subject: RxRPC: Fix a potential NULL dereference Fix a potential NULL dereference bug during error handling in rxrpc_kernel_begin_call(), whereby rxrpc_put_transport() may be handed a NULL pointer. This was found with a code checker (http://repo.or.cz/w/smatch.git/). Reported-by: Dan Carpenter Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/af_rxrpc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index d7d2bed..eac5e7b 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -284,13 +284,13 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, if (IS_ERR(trans)) { call = ERR_CAST(trans); trans = NULL; - goto out; + goto out_notrans; } } else { trans = rx->trans; if (!trans) { call = ERR_PTR(-ENOTCONN); - goto out; + goto out_notrans; } atomic_inc(&trans->usage); } @@ -315,6 +315,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, rxrpc_put_bundle(trans, bundle); out: rxrpc_put_transport(trans); +out_notrans: release_sock(&rx->sk); _leave(" = %p", call); return call; -- cgit v1.1 From b4bd07c20ba0c1fa7ad09ba257e0a5cfc2bf6bb3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 Feb 2009 22:06:43 -0800 Subject: net_dma: call dmaengine_get only if NET_DMA enabled Based upon a patch from Atsushi Nemoto -------------------- The commit 649274d993212e7c23c0cb734572c2311c200872 ("net_dma: acquire/release dma channels on ifup/ifdown") added unconditional call of dmaengine_get() to net_dma. The API should be called only if NET_DMA was enabled. -------------------- Signed-off-by: David S. Miller Acked-by: Dan Williams --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 5379b0c..a17e006 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1090,7 +1090,7 @@ int dev_open(struct net_device *dev) /* * Enable NET_DMA */ - dmaengine_get(); + net_dmaengine_get(); /* * Initialize multicasting status @@ -1172,7 +1172,7 @@ int dev_close(struct net_device *dev) /* * Shutdown NET_DMA */ - dmaengine_put(); + net_dmaengine_put(); return 0; } -- cgit v1.1 From beeebc92ee04bff6a722ebf85e23131faedd4479 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Fri, 6 Feb 2009 22:07:41 -0800 Subject: 9p: fix endian issues [attempt 3] When the changes were done to the protocol last release, some endian bugs crept in. This patch fixes those endian problems and has been verified to run on 32/64 bit and x86/ppc architectures. This version of the patch incorporates the correct annotations for endian variables. Signed-off-by: Eric Van Hensbergen Signed-off-by: David S. Miller --- net/9p/protocol.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/9p/protocol.c b/net/9p/protocol.c index dcd7666..fc70147 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include "protocol.h" @@ -160,29 +161,32 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) break; case 'w':{ int16_t *val = va_arg(ap, int16_t *); - if (pdu_read(pdu, val, sizeof(*val))) { + __le16 le_val; + if (pdu_read(pdu, &le_val, sizeof(le_val))) { errcode = -EFAULT; break; } - *val = cpu_to_le16(*val); + *val = le16_to_cpu(le_val); } break; case 'd':{ int32_t *val = va_arg(ap, int32_t *); - if (pdu_read(pdu, val, sizeof(*val))) { + __le32 le_val; + if (pdu_read(pdu, &le_val, sizeof(le_val))) { errcode = -EFAULT; break; } - *val = cpu_to_le32(*val); + *val = le32_to_cpu(le_val); } break; case 'q':{ int64_t *val = va_arg(ap, int64_t *); - if (pdu_read(pdu, val, sizeof(*val))) { + __le64 le_val; + if (pdu_read(pdu, &le_val, sizeof(le_val))) { errcode = -EFAULT; break; } - *val = cpu_to_le64(*val); + *val = le64_to_cpu(le_val); } break; case 's':{ @@ -362,19 +366,19 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) } break; case 'w':{ - int16_t val = va_arg(ap, int); + __le16 val = cpu_to_le16(va_arg(ap, int)); if (pdu_write(pdu, &val, sizeof(val))) errcode = -EFAULT; } break; case 'd':{ - int32_t val = va_arg(ap, int32_t); + __le32 val = cpu_to_le32(va_arg(ap, int32_t)); if (pdu_write(pdu, &val, sizeof(val))) errcode = -EFAULT; } break; case 'q':{ - int64_t val = va_arg(ap, int64_t); + __le64 val = cpu_to_le64(va_arg(ap, int64_t)); if (pdu_write(pdu, &val, sizeof(val))) errcode = -EFAULT; } -- cgit v1.1 From a51f42f3c940e5582c40454ece066d033bc7e24f Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 9 Feb 2009 14:33:03 -0800 Subject: netfilter: fix tuple inversion for Node information request The patch fixes a typo in the inverse mapping of Node Information request. Following draft-ietf-ipngwg-icmp-name-lookups-09, "Querier" sends a type 139 (ICMPV6_NI_QUERY) packet to "Responder" which answer with a type 140 (ICMPV6_NI_REPLY) packet. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index c455cf4..114a92e 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -49,8 +49,8 @@ static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, static const u_int8_t invmap[] = { [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1, [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1, - [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1, - [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1 + [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_REPLY + 1, + [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_QUERY +1 }; static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple, -- cgit v1.1 From 3f9007135c1dc896db9a9e35920aafc65b157230 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 9 Feb 2009 14:33:20 -0800 Subject: netfilter: nf_conntrack_ipv6: don't track ICMPv6 negotiation message This patch removes connection tracking handling for ICMPv6 messages related to Stateless Address Autoconfiguration, MLD, and MLDv2. They can not be tracked because they are massively using multicast (on pre-defined address). But they are not invalid and should not be detected as such. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'net') diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 114a92e..c323643 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -53,6 +53,17 @@ static const u_int8_t invmap[] = { [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_QUERY +1 }; +static const u_int8_t noct_valid_new[] = { + [ICMPV6_MGM_QUERY - 130] = 1, + [ICMPV6_MGM_REPORT -130] = 1, + [ICMPV6_MGM_REDUCTION - 130] = 1, + [NDISC_ROUTER_SOLICITATION - 130] = 1, + [NDISC_ROUTER_ADVERTISEMENT - 130] = 1, + [NDISC_NEIGHBOUR_SOLICITATION - 130] = 1, + [NDISC_NEIGHBOUR_ADVERTISEMENT - 130] = 1, + [ICMPV6_MLD2_REPORT - 130] = 1 +}; + static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *orig) { @@ -178,6 +189,7 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, { const struct icmp6hdr *icmp6h; struct icmp6hdr _ih; + int type; icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); if (icmp6h == NULL) { @@ -194,6 +206,15 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, return -NF_ACCEPT; } + type = icmp6h->icmp6_type - 130; + if (type >= 0 && type < sizeof(noct_valid_new) && + noct_valid_new[type]) { + skb->nfct = &nf_conntrack_untracked.ct_general; + skb->nfctinfo = IP_CT_NEW; + nf_conntrack_get(skb->nfct); + return NF_ACCEPT; + } + /* is not error message ? */ if (icmp6h->icmp6_type >= 128) return NF_ACCEPT; -- cgit v1.1 From c969aa7d2cd5621ad4129dae6b6551af422944c6 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 9 Feb 2009 14:33:57 -0800 Subject: netfilter: ctnetlink: allow changing NAT sequence adjustment in creation This patch fixes an inconsistency in the current ctnetlink code since NAT sequence adjustment bit can only be updated but not set in the conntrack entry creation. This patch is used by conntrackd to successfully recover newly created entries that represent connections with helpers and NAT payload mangling. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_netlink.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c32a7e8..9051bb4 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1215,6 +1215,16 @@ ctnetlink_create_conntrack(struct nlattr *cda[], } } +#ifdef CONFIG_NF_NAT_NEEDED + if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) { + err = ctnetlink_change_nat_seq_adj(ct, cda); + if (err < 0) { + rcu_read_unlock(); + goto err; + } + } +#endif + if (cda[CTA_PROTOINFO]) { err = ctnetlink_change_protoinfo(ct, cda); if (err < 0) { -- cgit v1.1 From 1f9da256163e3ff91a12d0b861091f0e525139df Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 9 Feb 2009 14:34:26 -0800 Subject: netfilter: ctnetlink: fix echo if not subscribed to any multicast group This patch fixes echoing if the socket that has sent the request to create/update/delete an entry is not subscribed to any multicast group. With the current code, ctnetlink would not send the echo message via unicast as nfnetlink_send() would be skip. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_netlink.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9051bb4..cb78aa0 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -434,7 +434,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, } else return NOTIFY_DONE; - if (!nfnetlink_has_listeners(group)) + if (!item->report && !nfnetlink_has_listeners(group)) return NOTIFY_DONE; skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); @@ -1502,7 +1502,8 @@ static int ctnetlink_expect_event(struct notifier_block *this, } else return NOTIFY_DONE; - if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) + if (!item->report && + !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) return NOTIFY_DONE; skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); -- cgit v1.1 From d4e2675a61890a84849a24affedf80d5cae8b199 Mon Sep 17 00:00:00 2001 From: Qu Haoran Date: Mon, 9 Feb 2009 14:34:56 -0800 Subject: netfilter: xt_sctp: sctp chunk mapping doesn't work When user tries to map all chunks given in argument, kernel works on a copy of the chunkmap, but at the end it doesn't check the copy, but the orginal one. Signed-off-by: Qu Haoran Signed-off-by: Nicolas Dichtel Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/xt_sctp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index e223cb4..a189ada9 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c @@ -105,7 +105,7 @@ match_packet(const struct sk_buff *skb, switch (chunk_match_type) { case SCTP_CHUNK_MATCH_ALL: - return SCTP_CHUNKMAP_IS_CLEAR(info->chunkmap); + return SCTP_CHUNKMAP_IS_CLEAR(chunkmapcopy); case SCTP_CHUNK_MATCH_ANY: return false; case SCTP_CHUNK_MATCH_ONLY: -- cgit v1.1 From 20461c1740cac5e02733221c9f653098a703f55a Mon Sep 17 00:00:00 2001 From: Noriaki TAKAMIYA Date: Mon, 9 Feb 2009 15:01:19 -0800 Subject: IPv6: fix to set device name when new IPv6 over IPv6 tunnel device is created. When the user creates IPv6 over IPv6 tunnel, the device name created by the kernel isn't set to t->parm.name, which is referred as the result of ioctl(). Signed-off-by: Noriaki TAKAMIYA Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 58e2b0d..d994c55 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -249,8 +249,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) } t = netdev_priv(dev); - ip6_tnl_dev_init(dev); t->parms = *p; + ip6_tnl_dev_init(dev); if ((err = register_netdevice(dev)) < 0) goto failed_free; -- cgit v1.1 From 4906f9985e310fc01f956256b0d58ac28b0dcb19 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 9 Feb 2009 15:07:18 -0800 Subject: bridge: Fix LRO crash with tun > Kernel BUG at drivers/net/tun.c:444 > invalid opcode: 0000 [1] SMP > last sysfs file: /class/net/lo/ifindex > CPU 0 > Modules linked in: tun ipt_MASQUERADE iptable_nat ip_nat xt_state ip_conntrack > nfnetlink ipt_REJECT xt_tcpudp iptable_filter d > Pid: 6912, comm: qemu-kvm Tainted: G 2.6.18-128.el5 #1 > RIP: 0010:[] [] > :tun:tun_chr_readv+0x2b1/0x3a6 > RSP: 0018:ffff8102202c5e48 EFLAGS: 00010246 > RAX: 0000000000000000 RBX: ffff8102202c5e98 RCX: 0000000004010000 > RDX: ffff810227063680 RSI: ffff8102202c5e9e RDI: ffff8102202c5e92 > RBP: 0000000000010ff6 R08: 0000000000000000 R09: 0000000000000001 > R10: ffff8102202c5e94 R11: 0000000000000202 R12: ffff8102275357c0 > R13: ffff81022755e500 R14: 0000000000000000 R15: ffff8102202c5ef8 > FS: 00002ae4398db980(0000) GS:ffffffff803ac000(0000) knlGS:0000000000000000 > CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b > CR2: 00002ae4ab514000 CR3: 0000000221344000 CR4: 00000000000026e0 > Process qemu-kvm (pid: 6912, threadinfo ffff8102202c4000, task > ffff81022e58d820) > Stack: 00000000498735cb ffff810229d1a3c0 0000000000000000 ffff81022e58d820 > ffffffff8008a461 ffff81022755e528 ffff81022755e528 ffffffff8009f925 > 000005ea05ea0000 ffff8102209d0000 00001051143e1600 ffffffff8003c00e > Call Trace: > [] default_wake_function+0x0/0xe > [] enqueue_hrtimer+0x55/0x70 > [] hrtimer_start+0xbc/0xce > [] :tun:tun_chr_read+0x1a/0x1f > [] vfs_read+0xcb/0x171 > [] sys_read+0x45/0x6e > [] system_call+0x7e/0x83 > > > Code: 0f 0b 68 40 62 6f 88 c2 bc 01 f6 42 0a 08 74 0c 80 4c 24 41 > RIP [] :tun:tun_chr_readv+0x2b1/0x3a6 > RSP > <0>Kernel panic - not syncing: Fatal exception This crashed when an LRO packet generated by bnx2x reached a tun device through the bridge. We're supposed to drop it at the bridge. However, because the check was placed in br_forward instead of __br_forward, it's only effective if we are sending the packet through a single port. This patch fixes it by moving the check into __br_forward. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_forward.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index bdd9cce..d2c27c8 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -67,6 +67,11 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) { struct net_device *indev; + if (skb_warn_if_lro(skb)) { + kfree_skb(skb); + return; + } + indev = skb->dev; skb->dev = to->dev; skb_forward_csum(skb); @@ -89,7 +94,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) /* called with rcu_read_lock */ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) { - if (!skb_warn_if_lro(skb) && should_deliver(to, skb)) { + if (should_deliver(to, skb)) { __br_forward(to, skb); return; } -- cgit v1.1