aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-11-19 09:19:32 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-19 16:39:05 -0500
commite5dcecba015f9774a402ba559b80b16999747e3b (patch)
tree866103a98e1987c6b52a05a41cc0f5cbc1c14add
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>
-rw-r--r--net/core/drop_monitor.c13
-rw-r--r--net/netlink/genetlink.c13
2 files changed, 22 insertions, 4 deletions
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 0efc5028ba9d..46ee488c0015 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -106,6 +106,10 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data)
106 return skb; 106 return skb;
107} 107}
108 108
109static struct genl_multicast_group dm_mcgrp = {
110 .name = "events",
111};
112
109static void send_dm_alert(struct work_struct *work) 113static void send_dm_alert(struct work_struct *work)
110{ 114{
111 struct sk_buff *skb; 115 struct sk_buff *skb;
@@ -116,7 +120,7 @@ static void send_dm_alert(struct work_struct *work)
116 skb = reset_per_cpu_data(data); 120 skb = reset_per_cpu_data(data);
117 121
118 if (skb) 122 if (skb)
119 genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL); 123 genlmsg_multicast(skb, 0, dm_mcgrp.id, GFP_KERNEL);
120} 124}
121 125
122/* 126/*
@@ -371,6 +375,13 @@ static int __init init_net_drop_monitor(void)
371 return rc; 375 return rc;
372 } 376 }
373 377
378 rc = genl_register_mc_group(&net_drop_monitor_family, &dm_mcgrp);
379 if (rc) {
380 pr_err("Failed to register drop monitor mcast group\n");
381 goto out_unreg;
382 }
383 WARN_ON(dm_mcgrp.id != NET_DM_GRP_ALERT);
384
374 rc = register_netdevice_notifier(&dropmon_net_notifier); 385 rc = register_netdevice_notifier(&dropmon_net_notifier);
375 if (rc < 0) { 386 if (rc < 0) {
376 pr_crit("Failed to register netdevice notifier\n"); 387 pr_crit("Failed to register netdevice notifier\n");
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index c68ce73619b5..353909d46dda 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];
65 * To avoid an allocation at boot of just one unsigned long, 65 * To avoid an allocation at boot of just one unsigned long,
66 * declare it global instead. 66 * declare it global instead.
67 * Bit 0 is marked as already used since group 0 is invalid. 67 * Bit 0 is marked as already used since group 0 is invalid.
68 * Bit 1 is marked as already used since the drop-monitor code
69 * abuses the API and thinks it can statically use group 1.
70 * That group will typically conflict with other groups that
71 * any proper users use.
68 */ 72 */
69static unsigned long mc_group_start = 0x1; 73static unsigned long mc_group_start = 0x3;
70static unsigned long *mc_groups = &mc_group_start; 74static unsigned long *mc_groups = &mc_group_start;
71static unsigned long mc_groups_longs = 1; 75static unsigned long mc_groups_longs = 1;
72 76
@@ -160,9 +164,11 @@ int genl_register_mc_group(struct genl_family *family,
160 164
161 genl_lock_all(); 165 genl_lock_all();
162 166
163 /* special-case our own group */ 167 /* special-case our own group and hacks */
164 if (grp == &notify_grp) 168 if (grp == &notify_grp)
165 id = GENL_ID_CTRL; 169 id = GENL_ID_CTRL;
170 else if (strcmp(family->name, "NET_DM") == 0)
171 id = 1;
166 else 172 else
167 id = find_first_zero_bit(mc_groups, 173 id = find_first_zero_bit(mc_groups,
168 mc_groups_longs * BITS_PER_LONG); 174 mc_groups_longs * BITS_PER_LONG);
@@ -245,7 +251,8 @@ static void __genl_unregister_mc_group(struct genl_family *family,
245 rcu_read_unlock(); 251 rcu_read_unlock();
246 netlink_table_ungrab(); 252 netlink_table_ungrab();
247 253
248 clear_bit(grp->id, mc_groups); 254 if (grp->id != 1)
255 clear_bit(grp->id, mc_groups);
249 list_del(&grp->list); 256 list_del(&grp->list);
250 genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp); 257 genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
251 grp->id = 0; 258 grp->id = 0;