From 6708c9e5cc9bfc7c9a00ce9c0fdd0b1d4952b3d1 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 1 May 2013 22:36:49 +0000 Subject: net: use netdev_features_t in skb_needs_linearize() Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 4040673f806..40b1fadaf63 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2456,7 +2456,7 @@ EXPORT_SYMBOL(netif_skb_features); * 2. skb is fragmented and the device does not support SG. */ static inline int skb_needs_linearize(struct sk_buff *skb, - int features) + netdev_features_t features) { return skb_is_nonlinear(skb) && ((skb_has_frag_list(skb) && -- cgit v1.2.3 From b29d3145183da4e07d4b570fa8acdd3ac4a5c572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 1 May 2013 23:06:42 +0000 Subject: net: vlan,ethtool: netdev_features_t is more than 32 bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 2 +- net/core/ethtool.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 8af508536d3..3a8c8fd63c8 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -628,7 +628,7 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev, netdev_features_t features) { struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; - u32 old_features = features; + netdev_features_t old_features = features; features &= real_dev->vlan_features; features |= NETIF_F_RXCSUM; diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 5a934ef90f8..22efdaa76eb 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1421,7 +1421,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) void __user *useraddr = ifr->ifr_data; u32 ethcmd; int rc; - u32 old_features; + netdev_features_t old_features; if (!dev || !netif_device_present(dev)) return -ENODEV; -- cgit v1.2.3 From e616071094c214a274fb66d0b297f8b25a1a34d7 Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Wed, 1 May 2013 12:04:44 +0000 Subject: tipc: cosmetic: clean up comments and break a long line Signed-off-by: Gerlando Falauto Signed-off-by: David S. Miller --- net/tipc/bcast.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 25e159c2feb..0e2f4324f54 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -584,8 +584,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, { int bp_index; - /* - * Prepare broadcast link message for reliable transmission, + /* Prepare broadcast link message for reliable transmission, * if first time trying to send it; * preparation is skipped for broadcast link protocol messages * since they are sent in an unreliable manner and don't need it @@ -613,11 +612,12 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; if (!p) - break; /* no more bearers to try */ + break; /* No more bearers to try */ - tipc_nmap_diff(&bcbearer->remains, &p->nodes, &bcbearer->remains_new); + tipc_nmap_diff(&bcbearer->remains, &p->nodes, + &bcbearer->remains_new); if (bcbearer->remains_new.count == bcbearer->remains.count) - continue; /* bearer pair doesn't add anything */ + continue; /* Nothing added by bearer pair */ if (!tipc_bearer_blocked(p)) tipc_bearer_send(p, buf, &p->bcast_addr); @@ -628,13 +628,14 @@ static int tipc_bcbearer_send(struct sk_buff *buf, /* unable to send on either bearer */ continue; + /* Swap bearers for next packet */ if (s) { bcbearer->bpairs[bp_index].primary = s; bcbearer->bpairs[bp_index].secondary = p; } if (bcbearer->remains_new.count == 0) - break; /* all targets reached */ + break; /* All targets reached */ bcbearer->remains = bcbearer->remains_new; } -- cgit v1.2.3 From 77861d9c00900c0105b9d66ecf9fa612a43f8df5 Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Wed, 1 May 2013 12:04:45 +0000 Subject: tipc: tipc_bcbearer_send(): simplify bearer selection Signed-off-by: Gerlando Falauto Signed-off-by: David S. Miller --- net/tipc/bcast.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 0e2f4324f54..d9d848d488e 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -610,23 +610,23 @@ static int tipc_bcbearer_send(struct sk_buff *buf, for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary; struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; + struct tipc_bearer *b = p; if (!p) break; /* No more bearers to try */ - tipc_nmap_diff(&bcbearer->remains, &p->nodes, + if (tipc_bearer_blocked(p)) { + if (!s || tipc_bearer_blocked(s)) + continue; /* Can't use either bearer */ + b = s; + } + + tipc_nmap_diff(&bcbearer->remains, &b->nodes, &bcbearer->remains_new); if (bcbearer->remains_new.count == bcbearer->remains.count) continue; /* Nothing added by bearer pair */ - if (!tipc_bearer_blocked(p)) - tipc_bearer_send(p, buf, &p->bcast_addr); - else if (s && !tipc_bearer_blocked(s)) - /* unable to send on primary bearer */ - tipc_bearer_send(s, buf, &s->bcast_addr); - else - /* unable to send on either bearer */ - continue; + tipc_bearer_send(b, buf, &b->bcast_addr); /* Swap bearers for next packet */ if (s) { -- cgit v1.2.3 From 488fc9af8267d0cd9036bc9db9f5dbbfde6de208 Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Wed, 1 May 2013 12:04:46 +0000 Subject: tipc: pskb_copy() buffers when sending on more than one bearer When sending packets, TIPC bearers use skb_clone() before writing their hardware header. This will however NOT copy the data buffer. So when the same packet is sent over multiple bearers (to reach multiple nodes), the same socket buffer data will be treated by multiple tipc_media drivers which will write their own hardware header through dev_hard_header(). Most of the time this is not a problem, because by the time the packet is processed by the second media, it has already been sent over the first one. However, when the first transmission is delayed (e.g. because of insufficient bandwidth or through a shaper), the next bearer will overwrite the hardware header, resulting in the packet being sent: a) with the wrong source address, when bearers of the same type, e.g. ethernet, are involved b) with a completely corrupt header, or even dropped, when bearers of different types are involved. So when the same socket buffer is to be sent multiple times, send a pskb_copy() instead (from the second instance on), and release it afterwards (the bearer will skb_clone() it anyway). Signed-off-by: Gerlando Falauto Signed-off-by: David S. Miller --- net/tipc/bcast.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index d9d848d488e..e5f3da50782 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -611,6 +611,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary; struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; struct tipc_bearer *b = p; + struct sk_buff *tbuf; if (!p) break; /* No more bearers to try */ @@ -626,7 +627,17 @@ static int tipc_bcbearer_send(struct sk_buff *buf, if (bcbearer->remains_new.count == bcbearer->remains.count) continue; /* Nothing added by bearer pair */ - tipc_bearer_send(b, buf, &b->bcast_addr); + if (bp_index == 0) { + /* Use original buffer for first bearer */ + tipc_bearer_send(b, buf, &b->bcast_addr); + } else { + /* Avoid concurrent buffer access */ + tbuf = pskb_copy(buf, GFP_ATOMIC); + if (!tbuf) + break; + tipc_bearer_send(b, tbuf, &b->bcast_addr); + kfree_skb(tbuf); /* Bearer keeps a clone */ + } /* Swap bearers for next packet */ if (s) { -- cgit v1.2.3 From 83401eb4990ff6af55aeed8f49681558544192e6 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 2 May 2013 14:23:28 +0000 Subject: bridge: fix race with topology change timer A bridge should only send topology change notice if it is not the root bridge. It is possible for message age timer to elect itself as a new root bridge, and still have a topology change timer running but waiting for bridge lock on other CPU. Solve the race by checking if we are root bridge before continuing. This was the root cause of the cases where br_send_tcn_bpdu would OOPS. Reported-by: JerryKang Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_stp_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index c3530a81a33..950663d4d33 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c @@ -107,7 +107,7 @@ static void br_tcn_timer_expired(unsigned long arg) br_debug(br, "tcn timer expired\n"); spin_lock(&br->lock); - if (br->dev->flags & IFF_UP) { + if (!br_is_root_bridge(br) && (br->dev->flags & IFF_UP)) { br_transmit_tcn(br); mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time); -- cgit v1.2.3 From 9b3eb5edf33897dc9128aa27300066153d4f8b9c Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 2 May 2013 16:14:19 +0000 Subject: gre: Fix GREv4 TCPv6 segmentation. For ipv6 traffic, GRE can generate packet with strange GSO bits, e.g. ipv4 packet with SKB_GSO_TCPV6 flag set. Therefore following patch relaxes check in inet gso handler to allow such packet for segmentation. This patch also fixes wrong skb->protocol set that was done in gre_gso_segment() handler. Reported-by: Steinar H. Gunderson CC: Eric Dumazet Signed-off-by: Pravin B Shelar Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 1 + net/ipv4/gre.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index c61b3bb87a1..d01be2a3ae5 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1293,6 +1293,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, SKB_GSO_DODGY | SKB_GSO_TCP_ECN | SKB_GSO_GRE | + SKB_GSO_TCPV6 | SKB_GSO_UDP_TUNNEL | 0))) goto out; diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index d2d5a99fba0..cc22363965d 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c @@ -121,6 +121,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, int ghl = GRE_HEADER_SECTION; struct gre_base_hdr *greh; int mac_len = skb->mac_len; + __be16 protocol = skb->protocol; int tnl_hlen; bool csum; @@ -150,7 +151,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, /* setup inner skb. */ if (greh->protocol == htons(ETH_P_TEB)) { - struct ethhdr *eth = eth_hdr(skb); + struct ethhdr *eth = (struct ethhdr *)skb_inner_mac_header(skb); skb->protocol = eth->h_proto; } else { skb->protocol = greh->protocol; @@ -199,6 +200,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, skb_reset_mac_header(skb); skb_set_network_header(skb, mac_len); skb->mac_len = mac_len; + skb->protocol = protocol; } while ((skb = skb->next)); out: return segs; -- cgit v1.2.3 From 0d05535d413322341f89c77f32936b4df296ac5a Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 2 May 2013 16:17:02 +0000 Subject: vxlan: Fix TCPv6 segmentation. This patch set correct skb->protocol so that inner packet can lookup correct gso handler. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/ipv4/udp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6abbe645512..0ae038a4c7a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2311,8 +2311,10 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, struct sk_buff *segs = ERR_PTR(-EINVAL); int mac_len = skb->mac_len; int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); - int outer_hlen; + struct ethhdr *inner_eth = (struct ethhdr *)skb_inner_mac_header(skb); + __be16 protocol = skb->protocol; netdev_features_t enc_features; + int outer_hlen; if (unlikely(!pskb_may_pull(skb, tnl_hlen))) goto out; @@ -2322,6 +2324,8 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, skb_reset_mac_header(skb); skb_set_network_header(skb, skb_inner_network_offset(skb)); skb->mac_len = skb_inner_network_offset(skb); + inner_eth = (struct ethhdr *)skb_mac_header(skb); + skb->protocol = inner_eth->h_proto; /* segment inner packet. */ enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); @@ -2358,6 +2362,7 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, } skb->ip_summed = CHECKSUM_NONE; + skb->protocol = protocol; } while ((skb = skb->next)); out: return segs; -- cgit v1.2.3 From 8da3056c04bfc5f69f840ab038a38389e2de8189 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 3 May 2013 02:57:00 +0000 Subject: packet: tpacket_v3: do not trigger bug() on wrong header status Jakub reported that it is fairly easy to trigger the BUG() macro from user space with TPACKET_V3's RX_RING by just giving a wrong header status flag. We already had a similar situation in commit 7f5c3e3a80e6654 (``af_packet: remove BUG statement in tpacket_destruct_skb'') where this was the case in the TX_RING side that could be triggered from user space. So really, don't use BUG() or BUG_ON() unless there's really no way out, and i.e. don't use it for consistency checking when there's user space involved, no excuses, especially not if you're slapping the user with WARN + dump_stack + BUG all at once. The two functions are of concern: prb_retire_current_block() [when block status != TP_STATUS_KERNEL] prb_open_block() [when block_status != TP_STATUS_KERNEL] Calls to prb_open_block() are guarded by ealier checks if block_status is really TP_STATUS_KERNEL (racy!), but the first one BUG() is easily triggable from user space. System behaves still stable after they are removed. Also remove that yoda condition entirely, since it's already guarded. Reported-by: Jakub Zawadzki Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/packet/af_packet.c | 53 ++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 30 deletions(-) (limited to 'net') diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index dd5cd49b0e0..8ec1bca7f85 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -742,36 +742,33 @@ static void prb_open_block(struct tpacket_kbdq_core *pkc1, smp_rmb(); - if (likely(TP_STATUS_KERNEL == BLOCK_STATUS(pbd1))) { + /* We could have just memset this but we will lose the + * flexibility of making the priv area sticky + */ - /* We could have just memset this but we will lose the - * flexibility of making the priv area sticky - */ - BLOCK_SNUM(pbd1) = pkc1->knxt_seq_num++; - BLOCK_NUM_PKTS(pbd1) = 0; - BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - getnstimeofday(&ts); - h1->ts_first_pkt.ts_sec = ts.tv_sec; - h1->ts_first_pkt.ts_nsec = ts.tv_nsec; - pkc1->pkblk_start = (char *)pbd1; - pkc1->nxt_offset = pkc1->pkblk_start + BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - BLOCK_O2FP(pbd1) = (__u32)BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - BLOCK_O2PRIV(pbd1) = BLK_HDR_LEN; - pbd1->version = pkc1->version; - pkc1->prev = pkc1->nxt_offset; - pkc1->pkblk_end = pkc1->pkblk_start + pkc1->kblk_size; - prb_thaw_queue(pkc1); - _prb_refresh_rx_retire_blk_timer(pkc1); + BLOCK_SNUM(pbd1) = pkc1->knxt_seq_num++; + BLOCK_NUM_PKTS(pbd1) = 0; + BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - smp_wmb(); + getnstimeofday(&ts); - return; - } + h1->ts_first_pkt.ts_sec = ts.tv_sec; + h1->ts_first_pkt.ts_nsec = ts.tv_nsec; - WARN(1, "ERROR block:%p is NOT FREE status:%d kactive_blk_num:%d\n", - pbd1, BLOCK_STATUS(pbd1), pkc1->kactive_blk_num); - dump_stack(); - BUG(); + pkc1->pkblk_start = (char *)pbd1; + pkc1->nxt_offset = pkc1->pkblk_start + BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); + + BLOCK_O2FP(pbd1) = (__u32)BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); + BLOCK_O2PRIV(pbd1) = BLK_HDR_LEN; + + pbd1->version = pkc1->version; + pkc1->prev = pkc1->nxt_offset; + pkc1->pkblk_end = pkc1->pkblk_start + pkc1->kblk_size; + + prb_thaw_queue(pkc1); + _prb_refresh_rx_retire_blk_timer(pkc1); + + smp_wmb(); } /* @@ -862,10 +859,6 @@ static void prb_retire_current_block(struct tpacket_kbdq_core *pkc, prb_close_block(pkc, pbd, po, status); return; } - - WARN(1, "ERROR-pbd[%d]:%p\n", pkc->kactive_blk_num, pbd); - dump_stack(); - BUG(); } static int prb_curr_blk_in_use(struct tpacket_kbdq_core *pkc, -- cgit v1.2.3