diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 25e22c48060a..c4054a9795ff 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -13,6 +13,12 @@ static struct genl_family ethtool_genl_family; static bool ethnl_ok __read_mostly; + +/* Serializes broadcast notification sequence allocation with the multicast + * send, so that userspace observes nlmsg_seq monotonic in receive order + * regardless of which lock the caller holds (rtnl or instance lock). + */ +static DEFINE_MUTEX(ethnl_bcast_lock); static u32 ethnl_bcast_seq; #define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \ @@ -82,12 +88,6 @@ static void ethnl_sock_priv_destroy(void *priv) } } -u32 ethnl_bcast_seq_next(void) -{ - ASSERT_RTNL(); - return ++ethnl_bcast_seq; -} - int ethnl_ops_begin(struct net_device *dev) { int ret; @@ -329,8 +329,7 @@ void *ethnl_dump_put(struct sk_buff *skb, struct netlink_callback *cb, u8 cmd) void *ethnl_bcastmsg_put(struct sk_buff *skb, u8 cmd) { - return genlmsg_put(skb, 0, ++ethnl_bcast_seq, ðtool_genl_family, 0, - cmd); + return genlmsg_put(skb, 0, 0, ðtool_genl_family, 0, cmd); } void *ethnl_unicast_put(struct sk_buff *skb, u32 portid, u32 seq, u8 cmd) @@ -340,8 +339,15 @@ void *ethnl_unicast_put(struct sk_buff *skb, u32 portid, u32 seq, u8 cmd) int ethnl_multicast(struct sk_buff *skb, struct net_device *dev) { - return genlmsg_multicast_netns(ðtool_genl_family, dev_net(dev), skb, - 0, ETHNL_MCGRP_MONITOR, GFP_KERNEL); + struct nlmsghdr *nlh = nlmsg_hdr(skb); + int ret; + + mutex_lock(ðnl_bcast_lock); + nlh->nlmsg_seq = ++ethnl_bcast_seq; + ret = genlmsg_multicast_netns(ðtool_genl_family, dev_net(dev), skb, + 0, ETHNL_MCGRP_MONITOR, GFP_KERNEL); + mutex_unlock(ðnl_bcast_lock); + return ret; } /* GET request helpers */ @@ -1081,7 +1087,7 @@ void ethnl_notify(struct net_device *dev, unsigned int cmd, { if (unlikely(!ethnl_ok)) return; - ASSERT_RTNL(); + netdev_assert_locked_ops_compat(dev); if (likely(cmd < ARRAY_SIZE(ethnl_notify_handlers) && ethnl_notify_handlers[cmd])) diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 674c9c19529b..f94aaa66379c 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -10,7 +10,6 @@ struct ethnl_req_info; -u32 ethnl_bcast_seq_next(void); int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, const struct nlattr *nest, struct net *net, struct netlink_ext_ack *extack, diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c index 53792f53f922..65bad23d5c59 100644 --- a/net/ethtool/rss.c +++ b/net/ethtool/rss.c @@ -995,7 +995,6 @@ ethnl_rss_create_send_ntf(const struct sk_buff *rsp, struct net_device *dev) nlh = nlmsg_hdr(ntf); /* Convert the reply into a notification */ nlh->nlmsg_pid = 0; - nlh->nlmsg_seq = ethnl_bcast_seq_next(); genl_hdr = nlmsg_data(nlh); genl_hdr->cmd = ETHTOOL_MSG_RSS_CREATE_NTF;