aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-06-04 02:32:12 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-04 02:32:12 -0400
commitc99f7abf0e69987e4add567e155e042cb1f2a20b (patch)
treed23898dc30ed25c1dae9bb6325041027d412397a /net
parent92ff71b8fe9cd9c673615fc6f3870af7376d7c84 (diff)
parentd8b0426af5b67973585712c9af36b86f6ea97815 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: include/net/inetpeer.h net/ipv6/output_core.c Changes in net were fixing bugs in code removed in net-next. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/multicast.c6
-rw-r--r--net/bridge/br_fdb.c8
-rw-r--r--net/bridge/br_input.c4
-rw-r--r--net/bridge/br_private.h7
-rw-r--r--net/bridge/br_vlan.c28
-rw-r--r--net/core/dev.c35
-rw-r--r--net/core/filter.c7
-rw-r--r--net/core/rtnetlink.c10
-rw-r--r--net/ipv4/tcp_input.c11
-rw-r--r--net/ipv6/output_core.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c15
-rw-r--r--net/netlink/af_netlink.c7
-rw-r--r--net/xfrm/xfrm_user.c36
13 files changed, 131 insertions, 44 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/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 2c45c069ea1a..b524c36c1273 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -538,6 +538,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
538{ 538{
539 struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; 539 struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
540 struct net_bridge_fdb_entry *fdb; 540 struct net_bridge_fdb_entry *fdb;
541 bool fdb_modified = false;
541 542
542 /* some users want to always flood. */ 543 /* some users want to always flood. */
543 if (hold_time(br) == 0) 544 if (hold_time(br) == 0)
@@ -558,10 +559,15 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
558 source->dev->name); 559 source->dev->name);
559 } else { 560 } else {
560 /* fastpath: update of existing entry */ 561 /* fastpath: update of existing entry */
561 fdb->dst = source; 562 if (unlikely(source != fdb->dst)) {
563 fdb->dst = source;
564 fdb_modified = true;
565 }
562 fdb->updated = jiffies; 566 fdb->updated = jiffies;
563 if (unlikely(added_by_user)) 567 if (unlikely(added_by_user))
564 fdb->added_by_user = 1; 568 fdb->added_by_user = 1;
569 if (unlikely(fdb_modified))
570 fdb_notify(br, fdb, RTM_NEWNEIGH);
565 } 571 }
566 } else { 572 } else {
567 spin_lock(&br->hash_lock); 573 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 53d6e32965fc..bc17210d4c52 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -589,6 +589,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
589 struct sk_buff *skb, u16 *vid); 589 struct sk_buff *skb, u16 *vid);
590bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v, 590bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v,
591 const struct sk_buff *skb); 591 const struct sk_buff *skb);
592bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid);
592struct sk_buff *br_handle_vlan(struct net_bridge *br, 593struct sk_buff *br_handle_vlan(struct net_bridge *br,
593 const struct net_port_vlans *v, 594 const struct net_port_vlans *v,
594 struct sk_buff *skb); 595 struct sk_buff *skb);
@@ -660,6 +661,12 @@ static inline bool br_allowed_egress(struct net_bridge *br,
660 return true; 661 return true;
661} 662}
662 663
664static inline bool br_should_learn(struct net_bridge_port *p,
665 struct sk_buff *skb, u16 *vid)
666{
667 return true;
668}
669
663static inline struct sk_buff *br_handle_vlan(struct net_bridge *br, 670static inline struct sk_buff *br_handle_vlan(struct net_bridge *br,
664 const struct net_port_vlans *v, 671 const struct net_port_vlans *v,
665 struct sk_buff *skb) 672 struct sk_buff *skb)
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 24c5cc55589f..fcc95390f862 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 */
245bool 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 1ba2cfe3f8e8..5367bfba0947 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2289,8 +2289,8 @@ EXPORT_SYMBOL(skb_checksum_help);
2289 2289
2290__be16 skb_network_protocol(struct sk_buff *skb, int *depth) 2290__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
2291{ 2291{
2292 unsigned int vlan_depth = skb->mac_len;
2292 __be16 type = skb->protocol; 2293 __be16 type = skb->protocol;
2293 int vlan_depth = skb->mac_len;
2294 2294
2295 /* Tunnel gso handlers can set protocol to ethernet. */ 2295 /* Tunnel gso handlers can set protocol to ethernet. */
2296 if (type == htons(ETH_P_TEB)) { 2296 if (type == htons(ETH_P_TEB)) {
@@ -2303,15 +2303,30 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
2303 type = eth->h_proto; 2303 type = eth->h_proto;
2304 } 2304 }
2305 2305
2306 while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { 2306 /* if skb->protocol is 802.1Q/AD then the header should already be
2307 struct vlan_hdr *vh; 2307 * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
2308 2308 * ETH_HLEN otherwise
2309 if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) 2309 */
2310 return 0; 2310 if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
2311 2311 if (vlan_depth) {
2312 vh = (struct vlan_hdr *)(skb->data + vlan_depth); 2312 if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN)))
2313 type = vh->h_vlan_encapsulated_proto; 2313 return 0;
2314 vlan_depth += VLAN_HLEN; 2314 vlan_depth -= VLAN_HLEN;
2315 } else {
2316 vlan_depth = ETH_HLEN;
2317 }
2318 do {
2319 struct vlan_hdr *vh;
2320
2321 if (unlikely(!pskb_may_pull(skb,
2322 vlan_depth + VLAN_HLEN)))
2323 return 0;
2324
2325 vh = (struct vlan_hdr *)(skb->data + vlan_depth);
2326 type = vh->h_vlan_encapsulated_proto;
2327 vlan_depth += VLAN_HLEN;
2328 } while (type == htons(ETH_P_8021Q) ||
2329 type == htons(ETH_P_8021AD));
2315 } 2330 }
2316 2331
2317 *depth = vlan_depth; 2332 *depth = vlan_depth;
diff --git a/net/core/filter.c b/net/core/filter.c
index 842f8393121d..9de0c25323b4 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1492,8 +1492,13 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp,
1492 fp->jited = 0; 1492 fp->jited = 0;
1493 1493
1494 err = sk_chk_filter(fp->insns, fp->len); 1494 err = sk_chk_filter(fp->insns, fp->len);
1495 if (err) 1495 if (err) {
1496 if (sk != NULL)
1497 sk_filter_uncharge(sk, fp);
1498 else
1499 kfree(fp);
1496 return ERR_PTR(err); 1500 return ERR_PTR(err);
1501 }
1497 1502
1498 /* Probe if we can JIT compile the filter and if so, do 1503 /* Probe if we can JIT compile the filter and if so, do
1499 * the compilation of the filter. 1504 * the compilation of the filter.
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index f31268dbc0d1..741b22c62acf 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2045,11 +2045,15 @@ replay:
2045 if (ops->newlink) { 2045 if (ops->newlink) {
2046 err = ops->newlink(net, dev, tb, data); 2046 err = ops->newlink(net, dev, tb, data);
2047 /* Drivers should call free_netdev() in ->destructor 2047 /* Drivers should call free_netdev() in ->destructor
2048 * and unregister it on failure so that device could be 2048 * and unregister it on failure after registration
2049 * finally freed in rtnl_unlock. 2049 * so that device could be finally freed in rtnl_unlock.
2050 */ 2050 */
2051 if (err < 0) 2051 if (err < 0) {
2052 /* If device is not registered at all, free it now */
2053 if (dev->reg_state == NETREG_UNINITIALIZED)
2054 free_netdev(dev);
2052 goto out; 2055 goto out;
2056 }
2053 } else { 2057 } else {
2054 err = register_netdevice(dev); 2058 err = register_netdevice(dev);
2055 if (err < 0) { 2059 if (err < 0) {
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 350b2072f0ab..931529d5daa2 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 6179ac186ab9..ffa029305a09 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -8,7 +8,6 @@
8#include <net/addrconf.h> 8#include <net/addrconf.h>
9#include <net/secure_seq.h> 9#include <net/secure_seq.h>
10 10
11
12int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) 11int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
13{ 12{
14 u16 offset = sizeof(struct ipv6hdr); 13 u16 offset = sizeof(struct ipv6hdr);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index d9da8c448c76..e6836755c45d 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 e0ccd84d4d67..15c731f03fa6 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1377,7 +1377,9 @@ retry:
1377bool __netlink_ns_capable(const struct netlink_skb_parms *nsp, 1377bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
1378 struct user_namespace *user_ns, int cap) 1378 struct user_namespace *user_ns, int cap)
1379{ 1379{
1380 return sk_ns_capable(nsp->sk, user_ns, cap); 1380 return ((nsp->flags & NETLINK_SKB_DST) ||
1381 file_ns_capable(nsp->sk->sk_socket->file, user_ns, cap)) &&
1382 ns_capable(user_ns, cap);
1381} 1383}
1382EXPORT_SYMBOL(__netlink_ns_capable); 1384EXPORT_SYMBOL(__netlink_ns_capable);
1383 1385
@@ -2323,6 +2325,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
2323 struct sk_buff *skb; 2325 struct sk_buff *skb;
2324 int err; 2326 int err;
2325 struct scm_cookie scm; 2327 struct scm_cookie scm;
2328 u32 netlink_skb_flags = 0;
2326 2329
2327 if (msg->msg_flags&MSG_OOB) 2330 if (msg->msg_flags&MSG_OOB)
2328 return -EOPNOTSUPP; 2331 return -EOPNOTSUPP;
@@ -2344,6 +2347,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
2344 if ((dst_group || dst_portid) && 2347 if ((dst_group || dst_portid) &&
2345 !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) 2348 !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
2346 goto out; 2349 goto out;
2350 netlink_skb_flags |= NETLINK_SKB_DST;
2347 } else { 2351 } else {
2348 dst_portid = nlk->dst_portid; 2352 dst_portid = nlk->dst_portid;
2349 dst_group = nlk->dst_group; 2353 dst_group = nlk->dst_group;
@@ -2373,6 +2377,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
2373 NETLINK_CB(skb).portid = nlk->portid; 2377 NETLINK_CB(skb).portid = nlk->portid;
2374 NETLINK_CB(skb).dst_group = dst_group; 2378 NETLINK_CB(skb).dst_group = dst_group;
2375 NETLINK_CB(skb).creds = siocb->scm->creds; 2379 NETLINK_CB(skb).creds = siocb->scm->creds;
2380 NETLINK_CB(skb).flags = netlink_skb_flags;
2376 2381
2377 err = -EFAULT; 2382 err = -EFAULT;
2378 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { 2383 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index fd9a16a6d1de..412d9dc3a873 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -947,6 +947,20 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
947 return skb; 947 return skb;
948} 948}
949 949
950/* A wrapper for nlmsg_multicast() checking that nlsk is still available.
951 * Must be called with RCU read lock.
952 */
953static inline int xfrm_nlmsg_multicast(struct net *net, struct sk_buff *skb,
954 u32 pid, unsigned int group)
955{
956 struct sock *nlsk = rcu_dereference(net->xfrm.nlsk);
957
958 if (nlsk)
959 return nlmsg_multicast(nlsk, skb, pid, group, GFP_ATOMIC);
960 else
961 return -1;
962}
963
950static inline size_t xfrm_spdinfo_msgsize(void) 964static inline size_t xfrm_spdinfo_msgsize(void)
951{ 965{
952 return NLMSG_ALIGN(4) 966 return NLMSG_ALIGN(4)
@@ -2228,7 +2242,7 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
2228 if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) 2242 if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0)
2229 BUG(); 2243 BUG();
2230 2244
2231 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); 2245 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE);
2232} 2246}
2233#else 2247#else
2234static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, 2248static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
@@ -2419,7 +2433,7 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c)
2419 return -EMSGSIZE; 2433 return -EMSGSIZE;
2420 } 2434 }
2421 2435
2422 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); 2436 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_EXPIRE);
2423} 2437}
2424 2438
2425static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c) 2439static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c)
@@ -2434,7 +2448,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event
2434 if (build_aevent(skb, x, c) < 0) 2448 if (build_aevent(skb, x, c) < 0)
2435 BUG(); 2449 BUG();
2436 2450
2437 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); 2451 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_AEVENTS);
2438} 2452}
2439 2453
2440static int xfrm_notify_sa_flush(const struct km_event *c) 2454static int xfrm_notify_sa_flush(const struct km_event *c)
@@ -2460,7 +2474,7 @@ static int xfrm_notify_sa_flush(const struct km_event *c)
2460 2474
2461 nlmsg_end(skb, nlh); 2475 nlmsg_end(skb, nlh);
2462 2476
2463 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); 2477 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_SA);
2464} 2478}
2465 2479
2466static inline size_t xfrm_sa_len(struct xfrm_state *x) 2480static inline size_t xfrm_sa_len(struct xfrm_state *x)
@@ -2547,7 +2561,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c)
2547 2561
2548 nlmsg_end(skb, nlh); 2562 nlmsg_end(skb, nlh);
2549 2563
2550 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); 2564 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_SA);
2551 2565
2552out_free_skb: 2566out_free_skb:
2553 kfree_skb(skb); 2567 kfree_skb(skb);
@@ -2638,7 +2652,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
2638 if (build_acquire(skb, x, xt, xp) < 0) 2652 if (build_acquire(skb, x, xt, xp) < 0)
2639 BUG(); 2653 BUG();
2640 2654
2641 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); 2655 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_ACQUIRE);
2642} 2656}
2643 2657
2644/* User gives us xfrm_user_policy_info followed by an array of 0 2658/* User gives us xfrm_user_policy_info followed by an array of 0
@@ -2752,7 +2766,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct
2752 if (build_polexpire(skb, xp, dir, c) < 0) 2766 if (build_polexpire(skb, xp, dir, c) < 0)
2753 BUG(); 2767 BUG();
2754 2768
2755 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); 2769 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_EXPIRE);
2756} 2770}
2757 2771
2758static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c) 2772static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c)
@@ -2814,7 +2828,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_e
2814 2828
2815 nlmsg_end(skb, nlh); 2829 nlmsg_end(skb, nlh);
2816 2830
2817 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); 2831 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_POLICY);
2818 2832
2819out_free_skb: 2833out_free_skb:
2820 kfree_skb(skb); 2834 kfree_skb(skb);
@@ -2842,7 +2856,7 @@ static int xfrm_notify_policy_flush(const struct km_event *c)
2842 2856
2843 nlmsg_end(skb, nlh); 2857 nlmsg_end(skb, nlh);
2844 2858
2845 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); 2859 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_POLICY);
2846 2860
2847out_free_skb: 2861out_free_skb:
2848 kfree_skb(skb); 2862 kfree_skb(skb);
@@ -2911,7 +2925,7 @@ static int xfrm_send_report(struct net *net, u8 proto,
2911 if (build_report(skb, proto, sel, addr) < 0) 2925 if (build_report(skb, proto, sel, addr) < 0)
2912 BUG(); 2926 BUG();
2913 2927
2914 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); 2928 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_REPORT);
2915} 2929}
2916 2930
2917static inline size_t xfrm_mapping_msgsize(void) 2931static inline size_t xfrm_mapping_msgsize(void)
@@ -2963,7 +2977,7 @@ static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
2963 if (build_mapping(skb, x, ipaddr, sport) < 0) 2977 if (build_mapping(skb, x, ipaddr, sport) < 0)
2964 BUG(); 2978 BUG();
2965 2979
2966 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); 2980 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MAPPING);
2967} 2981}
2968 2982
2969static bool xfrm_is_alive(const struct km_event *c) 2983static bool xfrm_is_alive(const struct km_event *c)