diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-02 21:16:41 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-02 21:16:41 -0400 |
| commit | cae61ba37b4c2672704cbd8a626fbd85be7e67d9 (patch) | |
| tree | 035a181a7c079ff3c4f073c8d5abfc9da8c4a407 /net | |
| parent | ca755175f245b91f72cfa474aaa8acd9c26996f4 (diff) | |
| parent | 418c96ac151a16a5094a95d14252c92c1d47ec67 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
1) Unbreak zebra and other netlink apps, from Eric W Biederman.
2) Some new qmi_wwan device IDs, from Aleksander Morgado.
3) Fix info leak in DCB netlink handler of qlcnic driver, from Dan
Carpenter.
4) inet_getid() and ipv6_select_ident() do not generate monotonically
increasing ID numbers, fix from Eric Dumazet.
5) Fix memory leak in __sk_prepare_filter(), from Leon Yu.
6) Netlink leftover bytes warning message is user triggerable, rate
limit it. From Michal Schmidt.
7) Fix non-linear SKB panic in ipvs, from Peter Christensen.
8) Congestion window undo needs to be performed even if only never
retransmitted data is SACK'd, fix from Yuching Cheng.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (24 commits)
net: filter: fix possible memory leak in __sk_prepare_filter()
net: ec_bhf: Add runtime dependencies
tcp: fix cwnd undo on DSACK in F-RTO
netlink: Only check file credentials for implicit destinations
ipheth: Add support for iPad 2 and iPad 3
team: fix mtu setting
net: fix inet_getid() and ipv6_select_ident() bugs
net: qmi_wwan: interface #11 in Sierra Wireless MC73xx is not QMI
net: qmi_wwan: add additional Sierra Wireless QMI devices
bridge: Prevent insertion of FDB entry with disallowed vlan
netlink: rate-limit leftover bytes warning and print process name
bridge: notify user space after fdb update
net: qmi_wwan: add Netgear AirCard 341U
net: fix wrong mac_len calculation for vlans
batman-adv: fix NULL pointer dereferences
net/mlx4_core: Reset RoCE VF gids when guest driver goes down
emac: aggregation of v1-2 PLB errors for IER register
emac: add missing support of 10mbit in emac/rgmii
can: only rename enabled led triggers when changing the netdev name
ipvs: Fix panic due to non-linear skb
...
Diffstat (limited to 'net')
| -rw-r--r-- | net/batman-adv/multicast.c | 6 | ||||
| -rw-r--r-- | net/bluetooth/l2cap_core.c | 4 | ||||
| -rw-r--r-- | net/bridge/br_fdb.c | 8 | ||||
| -rw-r--r-- | net/bridge/br_input.c | 4 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 7 | ||||
| -rw-r--r-- | net/bridge/br_vlan.c | 28 | ||||
| -rw-r--r-- | net/core/dev.c | 35 | ||||
| -rw-r--r-- | net/core/filter.c | 7 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 11 | ||||
| -rw-r--r-- | net/ipv6/output_core.c | 11 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 15 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 7 |
12 files changed, 104 insertions, 39 deletions
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 8c7ca811de6e..96b66fd30f96 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c | |||
| @@ -415,7 +415,7 @@ batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv) | |||
| 415 | hlist_for_each_entry_rcu(tmp_orig_node, | 415 | hlist_for_each_entry_rcu(tmp_orig_node, |
| 416 | &bat_priv->mcast.want_all_ipv4_list, | 416 | &bat_priv->mcast.want_all_ipv4_list, |
| 417 | mcast_want_all_ipv4_node) { | 417 | mcast_want_all_ipv4_node) { |
| 418 | if (!atomic_inc_not_zero(&orig_node->refcount)) | 418 | if (!atomic_inc_not_zero(&tmp_orig_node->refcount)) |
| 419 | continue; | 419 | continue; |
| 420 | 420 | ||
| 421 | orig_node = tmp_orig_node; | 421 | orig_node = tmp_orig_node; |
| @@ -442,7 +442,7 @@ batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv) | |||
| 442 | hlist_for_each_entry_rcu(tmp_orig_node, | 442 | hlist_for_each_entry_rcu(tmp_orig_node, |
| 443 | &bat_priv->mcast.want_all_ipv6_list, | 443 | &bat_priv->mcast.want_all_ipv6_list, |
| 444 | mcast_want_all_ipv6_node) { | 444 | mcast_want_all_ipv6_node) { |
| 445 | if (!atomic_inc_not_zero(&orig_node->refcount)) | 445 | if (!atomic_inc_not_zero(&tmp_orig_node->refcount)) |
| 446 | continue; | 446 | continue; |
| 447 | 447 | ||
| 448 | orig_node = tmp_orig_node; | 448 | orig_node = tmp_orig_node; |
| @@ -493,7 +493,7 @@ batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv) | |||
| 493 | hlist_for_each_entry_rcu(tmp_orig_node, | 493 | hlist_for_each_entry_rcu(tmp_orig_node, |
| 494 | &bat_priv->mcast.want_all_unsnoopables_list, | 494 | &bat_priv->mcast.want_all_unsnoopables_list, |
| 495 | mcast_want_all_unsnoopables_node) { | 495 | mcast_want_all_unsnoopables_node) { |
| 496 | if (!atomic_inc_not_zero(&orig_node->refcount)) | 496 | if (!atomic_inc_not_zero(&tmp_orig_node->refcount)) |
| 497 | continue; | 497 | continue; |
| 498 | 498 | ||
| 499 | orig_node = tmp_orig_node; | 499 | orig_node = tmp_orig_node; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a1e5bb7d06e8..dc4d301d3a72 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
| @@ -7519,9 +7519,9 @@ int __init l2cap_init(void) | |||
| 7519 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, | 7519 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, |
| 7520 | NULL, &l2cap_debugfs_fops); | 7520 | NULL, &l2cap_debugfs_fops); |
| 7521 | 7521 | ||
| 7522 | debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs, | 7522 | debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs, |
| 7523 | &le_max_credits); | 7523 | &le_max_credits); |
| 7524 | debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs, | 7524 | debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs, |
| 7525 | &le_default_mps); | 7525 | &le_default_mps); |
| 7526 | 7526 | ||
| 7527 | bt_6lowpan_init(); | 7527 | bt_6lowpan_init(); |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 9203d5a1943f..474d36f93342 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
| @@ -487,6 +487,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
| 487 | { | 487 | { |
| 488 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; | 488 | struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; |
| 489 | struct net_bridge_fdb_entry *fdb; | 489 | struct net_bridge_fdb_entry *fdb; |
| 490 | bool fdb_modified = false; | ||
| 490 | 491 | ||
| 491 | /* some users want to always flood. */ | 492 | /* some users want to always flood. */ |
| 492 | if (hold_time(br) == 0) | 493 | if (hold_time(br) == 0) |
| @@ -507,10 +508,15 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
| 507 | source->dev->name); | 508 | source->dev->name); |
| 508 | } else { | 509 | } else { |
| 509 | /* fastpath: update of existing entry */ | 510 | /* fastpath: update of existing entry */ |
| 510 | fdb->dst = source; | 511 | if (unlikely(source != fdb->dst)) { |
| 512 | fdb->dst = source; | ||
| 513 | fdb_modified = true; | ||
| 514 | } | ||
| 511 | fdb->updated = jiffies; | 515 | fdb->updated = jiffies; |
| 512 | if (unlikely(added_by_user)) | 516 | if (unlikely(added_by_user)) |
| 513 | fdb->added_by_user = 1; | 517 | fdb->added_by_user = 1; |
| 518 | if (unlikely(fdb_modified)) | ||
| 519 | fdb_notify(br, fdb, RTM_NEWNEIGH); | ||
| 514 | } | 520 | } |
| 515 | } else { | 521 | } else { |
| 516 | spin_lock(&br->hash_lock); | 522 | spin_lock(&br->hash_lock); |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 7985deaff52f..04d6348fd530 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -147,8 +147,8 @@ static int br_handle_local_finish(struct sk_buff *skb) | |||
| 147 | struct net_bridge_port *p = br_port_get_rcu(skb->dev); | 147 | struct net_bridge_port *p = br_port_get_rcu(skb->dev); |
| 148 | u16 vid = 0; | 148 | u16 vid = 0; |
| 149 | 149 | ||
| 150 | br_vlan_get_tag(skb, &vid); | 150 | /* check if vlan is allowed, to avoid spoofing */ |
| 151 | if (p->flags & BR_LEARNING) | 151 | if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid)) |
| 152 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); | 152 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); |
| 153 | return 0; /* process further */ | 153 | return 0; /* process further */ |
| 154 | } | 154 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 06811d79f89f..59d3a85c5873 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -581,6 +581,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 581 | struct sk_buff *skb, u16 *vid); | 581 | struct sk_buff *skb, u16 *vid); |
| 582 | bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v, | 582 | bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v, |
| 583 | const struct sk_buff *skb); | 583 | const struct sk_buff *skb); |
| 584 | bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid); | ||
| 584 | struct sk_buff *br_handle_vlan(struct net_bridge *br, | 585 | struct sk_buff *br_handle_vlan(struct net_bridge *br, |
| 585 | const struct net_port_vlans *v, | 586 | const struct net_port_vlans *v, |
| 586 | struct sk_buff *skb); | 587 | struct sk_buff *skb); |
| @@ -648,6 +649,12 @@ static inline bool br_allowed_egress(struct net_bridge *br, | |||
| 648 | return true; | 649 | return true; |
| 649 | } | 650 | } |
| 650 | 651 | ||
| 652 | static inline bool br_should_learn(struct net_bridge_port *p, | ||
| 653 | struct sk_buff *skb, u16 *vid) | ||
| 654 | { | ||
| 655 | return true; | ||
| 656 | } | ||
| 657 | |||
| 651 | static inline struct sk_buff *br_handle_vlan(struct net_bridge *br, | 658 | static inline struct sk_buff *br_handle_vlan(struct net_bridge *br, |
| 652 | const struct net_port_vlans *v, | 659 | const struct net_port_vlans *v, |
| 653 | struct sk_buff *skb) | 660 | struct sk_buff *skb) |
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 4a3716102789..5fee2feaf292 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
| @@ -241,6 +241,34 @@ bool br_allowed_egress(struct net_bridge *br, | |||
| 241 | return false; | 241 | return false; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | /* Called under RCU */ | ||
| 245 | bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) | ||
| 246 | { | ||
| 247 | struct net_bridge *br = p->br; | ||
| 248 | struct net_port_vlans *v; | ||
| 249 | |||
| 250 | if (!br->vlan_enabled) | ||
| 251 | return true; | ||
| 252 | |||
| 253 | v = rcu_dereference(p->vlan_info); | ||
| 254 | if (!v) | ||
| 255 | return false; | ||
| 256 | |||
| 257 | br_vlan_get_tag(skb, vid); | ||
| 258 | if (!*vid) { | ||
| 259 | *vid = br_get_pvid(v); | ||
| 260 | if (*vid == VLAN_N_VID) | ||
| 261 | return false; | ||
| 262 | |||
| 263 | return true; | ||
| 264 | } | ||
| 265 | |||
| 266 | if (test_bit(*vid, v->vlan_bitmap)) | ||
| 267 | return true; | ||
| 268 | |||
| 269 | return false; | ||
| 270 | } | ||
| 271 | |||
| 244 | /* Must be protected by RTNL. | 272 | /* Must be protected by RTNL. |
| 245 | * Must be called with vid in range from 1 to 4094 inclusive. | 273 | * Must be called with vid in range from 1 to 4094 inclusive. |
| 246 | */ | 274 | */ |
diff --git a/net/core/dev.c b/net/core/dev.c index 9abc503b19b7..fb8b0546485b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2283,8 +2283,8 @@ EXPORT_SYMBOL(skb_checksum_help); | |||
| 2283 | 2283 | ||
| 2284 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | 2284 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
| 2285 | { | 2285 | { |
| 2286 | unsigned int vlan_depth = skb->mac_len; | ||
| 2286 | __be16 type = skb->protocol; | 2287 | __be16 type = skb->protocol; |
| 2287 | int vlan_depth = skb->mac_len; | ||
| 2288 | 2288 | ||
| 2289 | /* Tunnel gso handlers can set protocol to ethernet. */ | 2289 | /* Tunnel gso handlers can set protocol to ethernet. */ |
| 2290 | if (type == htons(ETH_P_TEB)) { | 2290 | if (type == htons(ETH_P_TEB)) { |
| @@ -2297,15 +2297,30 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | |||
| 2297 | type = eth->h_proto; | 2297 | type = eth->h_proto; |
| 2298 | } | 2298 | } |
| 2299 | 2299 | ||
| 2300 | while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { | 2300 | /* if skb->protocol is 802.1Q/AD then the header should already be |
| 2301 | struct vlan_hdr *vh; | 2301 | * present at mac_len - VLAN_HLEN (if mac_len > 0), or at |
| 2302 | 2302 | * ETH_HLEN otherwise | |
| 2303 | if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) | 2303 | */ |
| 2304 | return 0; | 2304 | if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { |
| 2305 | 2305 | if (vlan_depth) { | |
| 2306 | vh = (struct vlan_hdr *)(skb->data + vlan_depth); | 2306 | if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN))) |
| 2307 | type = vh->h_vlan_encapsulated_proto; | 2307 | return 0; |
| 2308 | vlan_depth += VLAN_HLEN; | 2308 | vlan_depth -= VLAN_HLEN; |
| 2309 | } else { | ||
| 2310 | vlan_depth = ETH_HLEN; | ||
| 2311 | } | ||
| 2312 | do { | ||
| 2313 | struct vlan_hdr *vh; | ||
| 2314 | |||
| 2315 | if (unlikely(!pskb_may_pull(skb, | ||
| 2316 | vlan_depth + VLAN_HLEN))) | ||
| 2317 | return 0; | ||
| 2318 | |||
| 2319 | vh = (struct vlan_hdr *)(skb->data + vlan_depth); | ||
| 2320 | type = vh->h_vlan_encapsulated_proto; | ||
| 2321 | vlan_depth += VLAN_HLEN; | ||
| 2322 | } while (type == htons(ETH_P_8021Q) || | ||
| 2323 | type == htons(ETH_P_8021AD)); | ||
| 2309 | } | 2324 | } |
| 2310 | 2325 | ||
| 2311 | *depth = vlan_depth; | 2326 | *depth = vlan_depth; |
diff --git a/net/core/filter.c b/net/core/filter.c index 9d79ca0a6e8e..4aec7b93f1a9 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -1559,8 +1559,13 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp, | |||
| 1559 | fp->jited = 0; | 1559 | fp->jited = 0; |
| 1560 | 1560 | ||
| 1561 | err = sk_chk_filter(fp->insns, fp->len); | 1561 | err = sk_chk_filter(fp->insns, fp->len); |
| 1562 | if (err) | 1562 | if (err) { |
| 1563 | if (sk != NULL) | ||
| 1564 | sk_filter_uncharge(sk, fp); | ||
| 1565 | else | ||
| 1566 | kfree(fp); | ||
| 1563 | return ERR_PTR(err); | 1567 | return ERR_PTR(err); |
| 1568 | } | ||
| 1564 | 1569 | ||
| 1565 | /* Probe if we can JIT compile the filter and if so, do | 1570 | /* Probe if we can JIT compile the filter and if so, do |
| 1566 | * the compilation of the filter. | 1571 | * the compilation of the filter. |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d6b46eb2f94c..3a26b3b23f16 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -2684,13 +2684,12 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
| 2684 | bool recovered = !before(tp->snd_una, tp->high_seq); | 2684 | bool recovered = !before(tp->snd_una, tp->high_seq); |
| 2685 | 2685 | ||
| 2686 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ | 2686 | if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ |
| 2687 | if (flag & FLAG_ORIG_SACK_ACKED) { | 2687 | /* Step 3.b. A timeout is spurious if not all data are |
| 2688 | /* Step 3.b. A timeout is spurious if not all data are | 2688 | * lost, i.e., never-retransmitted data are (s)acked. |
| 2689 | * lost, i.e., never-retransmitted data are (s)acked. | 2689 | */ |
| 2690 | */ | 2690 | if (tcp_try_undo_loss(sk, flag & FLAG_ORIG_SACK_ACKED)) |
| 2691 | tcp_try_undo_loss(sk, true); | ||
| 2692 | return; | 2691 | return; |
| 2693 | } | 2692 | |
| 2694 | if (after(tp->snd_nxt, tp->high_seq) && | 2693 | if (after(tp->snd_nxt, tp->high_seq) && |
| 2695 | (flag & FLAG_DATA_SACKED || is_dupack)) { | 2694 | (flag & FLAG_DATA_SACKED || is_dupack)) { |
| 2696 | tp->frto = 0; /* Loss was real: 2nd part of step 3.a */ | 2695 | tp->frto = 0; /* Loss was real: 2nd part of step 3.a */ |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 6313abd53c9d..56596ce390a1 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
| @@ -12,7 +12,7 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | |||
| 12 | { | 12 | { |
| 13 | static atomic_t ipv6_fragmentation_id; | 13 | static atomic_t ipv6_fragmentation_id; |
| 14 | struct in6_addr addr; | 14 | struct in6_addr addr; |
| 15 | int old, new; | 15 | int ident; |
| 16 | 16 | ||
| 17 | #if IS_ENABLED(CONFIG_IPV6) | 17 | #if IS_ENABLED(CONFIG_IPV6) |
| 18 | struct inet_peer *peer; | 18 | struct inet_peer *peer; |
| @@ -26,15 +26,10 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | |||
| 26 | return; | 26 | return; |
| 27 | } | 27 | } |
| 28 | #endif | 28 | #endif |
| 29 | do { | 29 | ident = atomic_inc_return(&ipv6_fragmentation_id); |
| 30 | old = atomic_read(&ipv6_fragmentation_id); | ||
| 31 | new = old + 1; | ||
| 32 | if (!new) | ||
| 33 | new = 1; | ||
| 34 | } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old); | ||
| 35 | 30 | ||
| 36 | addr = rt->rt6i_dst.addr; | 31 | addr = rt->rt6i_dst.addr; |
| 37 | addr.s6_addr32[0] ^= (__force __be32)new; | 32 | addr.s6_addr32[0] ^= (__force __be32)ident; |
| 38 | fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32)); | 33 | fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32)); |
| 39 | } | 34 | } |
| 40 | EXPORT_SYMBOL(ipv6_select_ident); | 35 | EXPORT_SYMBOL(ipv6_select_ident); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 4f26ee46b51f..3d2d2c8108ca 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -1392,15 +1392,19 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1392 | 1392 | ||
| 1393 | if (ipip) { | 1393 | if (ipip) { |
| 1394 | __be32 info = ic->un.gateway; | 1394 | __be32 info = ic->un.gateway; |
| 1395 | __u8 type = ic->type; | ||
| 1396 | __u8 code = ic->code; | ||
| 1395 | 1397 | ||
| 1396 | /* Update the MTU */ | 1398 | /* Update the MTU */ |
| 1397 | if (ic->type == ICMP_DEST_UNREACH && | 1399 | if (ic->type == ICMP_DEST_UNREACH && |
| 1398 | ic->code == ICMP_FRAG_NEEDED) { | 1400 | ic->code == ICMP_FRAG_NEEDED) { |
| 1399 | struct ip_vs_dest *dest = cp->dest; | 1401 | struct ip_vs_dest *dest = cp->dest; |
| 1400 | u32 mtu = ntohs(ic->un.frag.mtu); | 1402 | u32 mtu = ntohs(ic->un.frag.mtu); |
| 1403 | __be16 frag_off = cih->frag_off; | ||
| 1401 | 1404 | ||
| 1402 | /* Strip outer IP and ICMP, go to IPIP header */ | 1405 | /* Strip outer IP and ICMP, go to IPIP header */ |
| 1403 | __skb_pull(skb, ihl + sizeof(_icmph)); | 1406 | if (pskb_pull(skb, ihl + sizeof(_icmph)) == NULL) |
| 1407 | goto ignore_ipip; | ||
| 1404 | offset2 -= ihl + sizeof(_icmph); | 1408 | offset2 -= ihl + sizeof(_icmph); |
| 1405 | skb_reset_network_header(skb); | 1409 | skb_reset_network_header(skb); |
| 1406 | IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n", | 1410 | IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n", |
| @@ -1408,7 +1412,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1408 | ipv4_update_pmtu(skb, dev_net(skb->dev), | 1412 | ipv4_update_pmtu(skb, dev_net(skb->dev), |
| 1409 | mtu, 0, 0, 0, 0); | 1413 | mtu, 0, 0, 0, 0); |
| 1410 | /* Client uses PMTUD? */ | 1414 | /* Client uses PMTUD? */ |
| 1411 | if (!(cih->frag_off & htons(IP_DF))) | 1415 | if (!(frag_off & htons(IP_DF))) |
| 1412 | goto ignore_ipip; | 1416 | goto ignore_ipip; |
| 1413 | /* Prefer the resulting PMTU */ | 1417 | /* Prefer the resulting PMTU */ |
| 1414 | if (dest) { | 1418 | if (dest) { |
| @@ -1427,12 +1431,13 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1427 | /* Strip outer IP, ICMP and IPIP, go to IP header of | 1431 | /* Strip outer IP, ICMP and IPIP, go to IP header of |
| 1428 | * original request. | 1432 | * original request. |
| 1429 | */ | 1433 | */ |
| 1430 | __skb_pull(skb, offset2); | 1434 | if (pskb_pull(skb, offset2) == NULL) |
| 1435 | goto ignore_ipip; | ||
| 1431 | skb_reset_network_header(skb); | 1436 | skb_reset_network_header(skb); |
| 1432 | IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n", | 1437 | IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n", |
| 1433 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, | 1438 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, |
| 1434 | ic->type, ic->code, ntohl(info)); | 1439 | type, code, ntohl(info)); |
| 1435 | icmp_send(skb, ic->type, ic->code, info); | 1440 | icmp_send(skb, type, code, info); |
| 1436 | /* ICMP can be shorter but anyways, account it */ | 1441 | /* ICMP can be shorter but anyways, account it */ |
| 1437 | ip_vs_out_stats(cp, skb); | 1442 | ip_vs_out_stats(cp, skb); |
| 1438 | 1443 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 81dca96d2be6..f22757a29cd0 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1373,7 +1373,9 @@ retry: | |||
| 1373 | bool __netlink_ns_capable(const struct netlink_skb_parms *nsp, | 1373 | bool __netlink_ns_capable(const struct netlink_skb_parms *nsp, |
| 1374 | struct user_namespace *user_ns, int cap) | 1374 | struct user_namespace *user_ns, int cap) |
| 1375 | { | 1375 | { |
| 1376 | return sk_ns_capable(nsp->sk, user_ns, cap); | 1376 | return ((nsp->flags & NETLINK_SKB_DST) || |
| 1377 | file_ns_capable(nsp->sk->sk_socket->file, user_ns, cap)) && | ||
| 1378 | ns_capable(user_ns, cap); | ||
| 1377 | } | 1379 | } |
| 1378 | EXPORT_SYMBOL(__netlink_ns_capable); | 1380 | EXPORT_SYMBOL(__netlink_ns_capable); |
| 1379 | 1381 | ||
| @@ -2293,6 +2295,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 2293 | struct sk_buff *skb; | 2295 | struct sk_buff *skb; |
| 2294 | int err; | 2296 | int err; |
| 2295 | struct scm_cookie scm; | 2297 | struct scm_cookie scm; |
| 2298 | u32 netlink_skb_flags = 0; | ||
| 2296 | 2299 | ||
| 2297 | if (msg->msg_flags&MSG_OOB) | 2300 | if (msg->msg_flags&MSG_OOB) |
| 2298 | return -EOPNOTSUPP; | 2301 | return -EOPNOTSUPP; |
| @@ -2314,6 +2317,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 2314 | if ((dst_group || dst_portid) && | 2317 | if ((dst_group || dst_portid) && |
| 2315 | !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) | 2318 | !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) |
| 2316 | goto out; | 2319 | goto out; |
| 2320 | netlink_skb_flags |= NETLINK_SKB_DST; | ||
| 2317 | } else { | 2321 | } else { |
| 2318 | dst_portid = nlk->dst_portid; | 2322 | dst_portid = nlk->dst_portid; |
| 2319 | dst_group = nlk->dst_group; | 2323 | dst_group = nlk->dst_group; |
| @@ -2343,6 +2347,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 2343 | NETLINK_CB(skb).portid = nlk->portid; | 2347 | NETLINK_CB(skb).portid = nlk->portid; |
| 2344 | NETLINK_CB(skb).dst_group = dst_group; | 2348 | NETLINK_CB(skb).dst_group = dst_group; |
| 2345 | NETLINK_CB(skb).creds = siocb->scm->creds; | 2349 | NETLINK_CB(skb).creds = siocb->scm->creds; |
| 2350 | NETLINK_CB(skb).flags = netlink_skb_flags; | ||
| 2346 | 2351 | ||
| 2347 | err = -EFAULT; | 2352 | err = -EFAULT; |
| 2348 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 2353 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |
