genetlink: fix genlmsg_multicast() bug
authorJohannes Berg <johannes.berg@intel.com>
Thu, 21 Nov 2013 17:17:04 +0000 (18:17 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 21 Nov 2013 18:09:43 +0000 (13:09 -0500)
Unfortunately, I introduced a tremendously stupid bug into
genlmsg_multicast() when doing all those multicast group
changes: it adjusts the group number, but then passes it
to genlmsg_multicast_netns() which does that again.

Somehow, my tests failed to catch this, so add a warning
into genlmsg_multicast_netns() and remove the offending
group ID adjustment.

Also add a warning to the similar code in other functions
so people who misuse them are more loudly warned.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/genetlink.h
net/netlink/genetlink.c

index ace4abf..771af09 100644 (file)
@@ -265,7 +265,7 @@ static inline int genlmsg_multicast_netns(struct genl_family *family,
                                          struct net *net, struct sk_buff *skb,
                                          u32 portid, unsigned int group, gfp_t flags)
 {
-       if (group >= family->n_mcgrps)
+       if (WARN_ON_ONCE(group >= family->n_mcgrps))
                return -EINVAL;
        group = family->mcgrp_offset + group;
        return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
@@ -283,9 +283,6 @@ static inline int genlmsg_multicast(struct genl_family *family,
                                    struct sk_buff *skb, u32 portid,
                                    unsigned int group, gfp_t flags)
 {
-       if (group >= family->n_mcgrps)
-               return -EINVAL;
-       group = family->mcgrp_offset + group;
        return genlmsg_multicast_netns(family, &init_net, skb,
                                       portid, group, flags);
 }
index 7dbc4f7..4518a57 100644 (file)
@@ -1045,7 +1045,7 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
 int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
                            u32 portid, unsigned int group, gfp_t flags)
 {
-       if (group >= family->n_mcgrps)
+       if (WARN_ON_ONCE(group >= family->n_mcgrps))
                return -EINVAL;
        group = family->mcgrp_offset + group;
        return genlmsg_mcast(skb, portid, group, flags);
@@ -1062,7 +1062,7 @@ void genl_notify(struct genl_family *family,
        if (nlh)
                report = nlmsg_report(nlh);
 
-       if (group >= family->n_mcgrps)
+       if (WARN_ON_ONCE(group >= family->n_mcgrps))
                return;
        group = family->mcgrp_offset + group;
        nlmsg_notify(sk, skb, portid, group, report, flags);