diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 0efc5028ba9d7072feb5846592396e8dd301237a..46ee488c00150326656c7300a84cc971087743d1 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) return skb; } +static struct genl_multicast_group dm_mcgrp = { + .name = "events", +}; + static void send_dm_alert(struct work_struct *work) { struct sk_buff *skb; @@ -116,7 +120,7 @@ static void send_dm_alert(struct work_struct *work) skb = reset_per_cpu_data(data); if (skb) - genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL); + genlmsg_multicast(skb, 0, dm_mcgrp.id, GFP_KERNEL); } /* @@ -371,6 +375,13 @@ static int __init init_net_drop_monitor(void) return rc; } + rc = genl_register_mc_group(&net_drop_monitor_family, &dm_mcgrp); + if (rc) { + pr_err("Failed to register drop monitor mcast group\n"); + goto out_unreg; + } + WARN_ON(dm_mcgrp.id != NET_DM_GRP_ALERT); + rc = register_netdevice_notifier(&dropmon_net_notifier); if (rc < 0) { pr_crit("Failed to register netdevice notifier\n"); diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index c68ce73619b551a92de19fcb2a53f343c85e2d9f..353909d46dda86d810bb00248de49bdd1ab0acbd 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 == ¬ify_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;