diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index aa187672cf99..077c56cbed4e 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1788,7 +1788,7 @@ static int tcmu_netlink_event_send(struct tcmu_dev *udev, } ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0, - TCMU_MCGRP_CONFIG); + TCMU_MCGRP_CONFIG, GFP_KERNEL); /* Wait during an add as the listener may not be up yet */ if (ret == 0 || diff --git a/include/net/genetlink.h b/include/net/genetlink.h index d5b2e09a81d8..2d9e67a69cbe 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -296,12 +296,13 @@ static inline int genlmsg_multicast(const struct genl_family *family, * @skb: netlink message as socket buffer * @portid: own netlink portid to avoid sending to yourself * @group: offset of multicast group in groups array + * @flags: allocation flags * * This function must hold the RTNL or rcu_read_lock(). */ int genlmsg_multicast_allns(const struct genl_family *family, struct sk_buff *skb, u32 portid, - unsigned int group); + unsigned int group, gfp_t flags); /** * genlmsg_unicast - unicast a netlink message diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 733f59822f8f..ebb381c3f1b9 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -117,7 +117,7 @@ static int l2tp_tunnel_notify(struct genl_family *family, NLM_F_ACK, tunnel, cmd); if (ret >= 0) { - ret = genlmsg_multicast_allns(family, msg, 0, 0); + ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC); /* We don't care if no one is listening */ if (ret == -ESRCH) ret = 0; @@ -145,7 +145,7 @@ static int l2tp_session_notify(struct genl_family *family, NLM_F_ACK, session, cmd); if (ret >= 0) { - ret = genlmsg_multicast_allns(family, msg, 0, 0); + ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC); /* We don't care if no one is listening */ if (ret == -ESRCH) ret = 0; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 374c06353376..102b8d6b5612 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -949,11 +949,15 @@ static int genl_ctrl_event(int event, const struct genl_family *family, if (IS_ERR(msg)) return PTR_ERR(msg); - if (!family->netnsok) + if (!family->netnsok) { genlmsg_multicast_netns(&genl_ctrl, &init_net, msg, 0, 0, GFP_KERNEL); - else - genlmsg_multicast_allns(&genl_ctrl, msg, 0, 0); + } else { + rcu_read_lock(); + genlmsg_multicast_allns(&genl_ctrl, msg, 0, + 0, GFP_ATOMIC); + rcu_read_unlock(); + } return 0; } @@ -1054,23 +1058,23 @@ struct nlattr **genl_family_attrbuf(const struct genl_family *family) } EXPORT_SYMBOL(genl_family_attrbuf); -static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group) +static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, + gfp_t flags) { struct sk_buff *tmp; struct net *net, *prev = NULL; bool delivered = false; int err; - rcu_read_lock(); for_each_net_rcu(net) { if (prev) { - tmp = skb_clone(skb, GFP_ATOMIC); + tmp = skb_clone(skb, flags); if (!tmp) { err = -ENOMEM; goto error; } err = nlmsg_multicast(prev->genl_sock, tmp, - portid, group, GFP_ATOMIC); + portid, group, flags); if (!err) delivered = true; else if (err != -ESRCH) @@ -1079,30 +1083,26 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group) prev = net; } - err = nlmsg_multicast(prev->genl_sock, skb, portid, group, GFP_ATOMIC); - - rcu_read_unlock(); + err = nlmsg_multicast(prev->genl_sock, skb, portid, group, flags); if (!err) delivered = true; else if (err != -ESRCH) return err; return delivered ? 0 : -ESRCH; error: - rcu_read_unlock(); - kfree_skb(skb); return err; } int genlmsg_multicast_allns(const struct genl_family *family, struct sk_buff *skb, u32 portid, - unsigned int group) + unsigned int group, gfp_t flags) { if (WARN_ON_ONCE(group >= family->n_mcgrps)) return -EINVAL; group = family->mcgrp_offset + group; - return genlmsg_mcast(skb, portid, group); + return genlmsg_mcast(skb, portid, group, flags); } EXPORT_SYMBOL(genlmsg_multicast_allns); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f32958dd9555..988d8f9a1b14 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -15407,8 +15407,10 @@ void nl80211_common_reg_change_event(enum nl80211_commands cmd_id, genlmsg_end(msg, hdr); + rcu_read_lock(); genlmsg_multicast_allns(&nl80211_fam, msg, 0, - NL80211_MCGRP_REGULATORY); + NL80211_MCGRP_REGULATORY, GFP_ATOMIC); + rcu_read_unlock(); return; @@ -15907,8 +15909,10 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, genlmsg_end(msg, hdr); + rcu_read_lock(); genlmsg_multicast_allns(&nl80211_fam, msg, 0, - NL80211_MCGRP_REGULATORY); + NL80211_MCGRP_REGULATORY, GFP_ATOMIC); + rcu_read_unlock(); return;