summaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-11-19 15:19:32 +0100
committerDavid S. Miller <davem@davemloft.net>2013-11-19 16:39:05 -0500
commite5dcecba015f9774a402ba559b80b16999747e3b (patch)
tree866103a98e1987c6b52a05a41cc0f5cbc1c14add /net/netlink
parentc53ed7423619b4e8108914a9f31b426dd58ad591 (diff)
drop_monitor/genetlink: use proper genetlink multicast APIs
The drop monitor code is abusing the genetlink API and is statically using the generic netlink multicast group 1, even if that group belongs to somebody else (which it invariably will, since it's not reserved.) Make the drop monitor code use the proper APIs to reserve a group ID, but also reserve the group id 1 in generic netlink code to preserve the userspace API. Since drop monitor can be a module, don't clear the bit for it on unregistration. Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/genetlink.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index c68ce73619b..353909d46dd 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -65,8 +65,12 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
* To avoid an allocation at boot of just one unsigned long,
* declare it global instead.
* Bit 0 is marked as already used since group 0 is invalid.
+ * Bit 1 is marked as already used since the drop-monitor code
+ * abuses the API and thinks it can statically use group 1.
+ * That group will typically conflict with other groups that
+ * any proper users use.
*/
-static unsigned long mc_group_start = 0x1;
+static unsigned long mc_group_start = 0x3;
static unsigned long *mc_groups = &mc_group_start;
static unsigned long mc_groups_longs = 1;
@@ -160,9 +164,11 @@ int genl_register_mc_group(struct genl_family *family,
genl_lock_all();
- /* special-case our own group */
+ /* special-case our own group and hacks */
if (grp == &notify_grp)
id = GENL_ID_CTRL;
+ else if (strcmp(family->name, "NET_DM") == 0)
+ id = 1;
else
id = find_first_zero_bit(mc_groups,
mc_groups_longs * BITS_PER_LONG);
@@ -245,7 +251,8 @@ static void __genl_unregister_mc_group(struct genl_family *family,
rcu_read_unlock();
netlink_table_ungrab();
- clear_bit(grp->id, mc_groups);
+ if (grp->id != 1)
+ clear_bit(grp->id, mc_groups);
list_del(&grp->list);
genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
grp->id = 0;