Skip to content

Commit

Permalink
Merge branch 'genetlink_mcast'
Browse files Browse the repository at this point in the history
Johannes Berg says:

====================
genetlink: clean up multicast group APIs

The generic netlink multicast group registration doesn't have to
be dynamic, and can thus be simplified just like I did with the
ops. This removes some complexity in registration code.

Additionally, two users of generic netlink already use multicast
groups in a wrong way, add workarounds for those two to keep the
userspace API working, but at the same time make them not clash
with other users of multicast groups as might happen now.

While making it all a bit easier, also prevent such abuse by adding
checks to the APIs so each family can only use the groups it owns.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 19, 2013
2 parents dbde497 + 2a94fe4 commit 091e066
Show file tree
Hide file tree
Showing 33 changed files with 518 additions and 513 deletions.
25 changes: 8 additions & 17 deletions drivers/acpi/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,17 @@ enum {
#define ACPI_GENL_VERSION 0x01
#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group"

static const struct genl_multicast_group acpi_event_mcgrps[] = {
{ .name = ACPI_GENL_MCAST_GROUP_NAME, },
};

static struct genl_family acpi_event_genl_family = {
.id = GENL_ID_GENERATE,
.name = ACPI_GENL_FAMILY_NAME,
.version = ACPI_GENL_VERSION,
.maxattr = ACPI_GENL_ATTR_MAX,
};

static struct genl_multicast_group acpi_event_mcgrp = {
.name = ACPI_GENL_MCAST_GROUP_NAME,
.mcgrps = acpi_event_mcgrps,
.n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps),
};

int acpi_bus_generate_netlink_event(const char *device_class,
Expand Down Expand Up @@ -146,26 +148,15 @@ int acpi_bus_generate_netlink_event(const char *device_class,
return result;
}

genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);
return 0;
}

EXPORT_SYMBOL(acpi_bus_generate_netlink_event);

static int acpi_event_genetlink_init(void)
{
int result;

result = genl_register_family(&acpi_event_genl_family);
if (result)
return result;

result = genl_register_mc_group(&acpi_event_genl_family,
&acpi_event_mcgrp);
if (result)
genl_unregister_family(&acpi_event_genl_family);

return result;
return genl_register_family(&acpi_event_genl_family);
}

#else
Expand Down
27 changes: 6 additions & 21 deletions drivers/net/team/team.c
Original file line number Diff line number Diff line change
Expand Up @@ -2670,15 +2670,15 @@ static const struct genl_ops team_nl_ops[] = {
},
};

static struct genl_multicast_group team_change_event_mcgrp = {
.name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
static const struct genl_multicast_group team_nl_mcgrps[] = {
{ .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, },
};

static int team_nl_send_multicast(struct sk_buff *skb,
struct team *team, u32 portid)
{
return genlmsg_multicast_netns(dev_net(team->dev), skb, 0,
team_change_event_mcgrp.id, GFP_KERNEL);
return genlmsg_multicast_netns(&team_nl_family, dev_net(team->dev),
skb, 0, 0, GFP_KERNEL);
}

static int team_nl_send_event_options_get(struct team *team,
Expand All @@ -2697,23 +2697,8 @@ static int team_nl_send_event_port_get(struct team *team,

static int team_nl_init(void)
{
int err;

err = genl_register_family_with_ops(&team_nl_family, team_nl_ops,
ARRAY_SIZE(team_nl_ops));
if (err)
return err;

err = genl_register_mc_group(&team_nl_family, &team_change_event_mcgrp);
if (err)
goto err_change_event_grp_reg;

return 0;

err_change_event_grp_reg:
genl_unregister_family(&team_nl_family);

return err;
return genl_register_family_with_ops_groups(&team_nl_family, team_nl_ops,
team_nl_mcgrps);
}

static void team_nl_fini(void)
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/mac80211_hwsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -2148,8 +2148,7 @@ static int hwsim_init_netlink(void)

printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");

rc = genl_register_family_with_ops(&hwsim_genl_family,
hwsim_ops, ARRAY_SIZE(hwsim_ops));
rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops);
if (rc)
goto failure;

Expand Down
3 changes: 2 additions & 1 deletion drivers/scsi/pmcraid.c
Original file line number Diff line number Diff line change
Expand Up @@ -1512,7 +1512,8 @@ static int pmcraid_notify_aen(
}

result =
genlmsg_multicast(skb, 0, pmcraid_event_family.id, GFP_ATOMIC);
genlmsg_multicast(&pmcraid_event_family, skb, 0,
pmcraid_event_family.id, GFP_ATOMIC);

/* If there are no listeners, genlmsg_multicast may return non-zero
* value.
Expand Down
25 changes: 9 additions & 16 deletions drivers/thermal/thermal_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1606,15 +1606,17 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);

#ifdef CONFIG_NET
static const struct genl_multicast_group thermal_event_mcgrps[] = {
{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
};

static struct genl_family thermal_event_genl_family = {
.id = GENL_ID_GENERATE,
.name = THERMAL_GENL_FAMILY_NAME,
.version = THERMAL_GENL_VERSION,
.maxattr = THERMAL_GENL_ATTR_MAX,
};

static struct genl_multicast_group thermal_event_mcgrp = {
.name = THERMAL_GENL_MCAST_GROUP_NAME,
.mcgrps = thermal_event_mcgrps,
.n_mcgrps = ARRAY_SIZE(thermal_event_mcgrps),
};

int thermal_generate_netlink_event(struct thermal_zone_device *tz,
Expand Down Expand Up @@ -1675,7 +1677,8 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
return result;
}

result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC);
result = genlmsg_multicast(&thermal_event_genl_family, skb, 0,
0, GFP_ATOMIC);
if (result)
dev_err(&tz->device, "Failed to send netlink event:%d", result);

Expand All @@ -1685,17 +1688,7 @@ EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);

static int genetlink_init(void)
{
int result;

result = genl_register_family(&thermal_event_genl_family);
if (result)
return result;

result = genl_register_mc_group(&thermal_event_genl_family,
&thermal_event_mcgrp);
if (result)
genl_unregister_family(&thermal_event_genl_family);
return result;
return genl_register_family(&thermal_event_genl_family);
}

static void genetlink_exit(void)
Expand Down
10 changes: 6 additions & 4 deletions fs/dlm/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,16 @@ static int user_cmd(struct sk_buff *skb, struct genl_info *info)
return 0;
}

static struct genl_ops dlm_nl_ops = {
.cmd = DLM_CMD_HELLO,
.doit = user_cmd,
static struct genl_ops dlm_nl_ops[] = {
{
.cmd = DLM_CMD_HELLO,
.doit = user_cmd,
},
};

int __init dlm_netlink_init(void)
{
return genl_register_family_with_ops(&family, &dlm_nl_ops, 1);
return genl_register_family_with_ops(&family, dlm_nl_ops);
}

void dlm_netlink_exit(void)
Expand Down
16 changes: 14 additions & 2 deletions fs/quota/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,25 @@
#include <net/netlink.h>
#include <net/genetlink.h>

static const struct genl_multicast_group quota_mcgrps[] = {
{ .name = "events", },
};

/* Netlink family structure for quota */
static struct genl_family quota_genl_family = {
.id = GENL_ID_GENERATE,
/*
* Needed due to multicast group ID abuse - old code assumed
* the family ID was also a valid multicast group ID (which
* isn't true) and userspace might thus rely on it. Assign a
* static ID for this group to make dealing with that easier.
*/
.id = GENL_ID_VFS_DQUOT,
.hdrsize = 0,
.name = "VFS_DQUOT",
.version = 1,
.maxattr = QUOTA_NL_A_MAX,
.mcgrps = quota_mcgrps,
.n_mcgrps = ARRAY_SIZE(quota_mcgrps),
};

/**
Expand Down Expand Up @@ -78,7 +90,7 @@ void quota_send_warning(struct kqid qid, dev_t dev,
goto attr_err_out;
genlmsg_end(skb, msg_head);

genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
genlmsg_multicast(&quota_genl_family, skb, 0, 0, GFP_NOFS);
return;
attr_err_out:
printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
Expand Down
53 changes: 22 additions & 31 deletions include/linux/genl_magic_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,49 +273,40 @@ static struct genl_family ZZZ_genl_family __read_mostly = {
* Magic: define multicast groups
* Magic: define multicast group registration helper
*/
#define ZZZ_genl_mcgrps CONCAT_(GENL_MAGIC_FAMILY, _genl_mcgrps)
static const struct genl_multicast_group ZZZ_genl_mcgrps[] = {
#undef GENL_mc_group
#define GENL_mc_group(group) { .name = #group, },
#include GENL_MAGIC_INCLUDE_FILE
};

enum CONCAT_(GENL_MAGIC_FAMILY, group_ids) {
#undef GENL_mc_group
#define GENL_mc_group(group) CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group),
#include GENL_MAGIC_INCLUDE_FILE
};

#undef GENL_mc_group
#define GENL_mc_group(group) \
static struct genl_multicast_group \
CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \
.name = #group, \
}; \
static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
struct sk_buff *skb, gfp_t flags) \
{ \
unsigned int group_id = \
CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \
if (!group_id) \
return -EINVAL; \
return genlmsg_multicast(skb, 0, group_id, flags); \
CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group); \
return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \
group_id, flags); \
}

#include GENL_MAGIC_INCLUDE_FILE

int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
{
int err = genl_register_family_with_ops(&ZZZ_genl_family,
ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops));
if (err)
return err;
#undef GENL_mc_group
#define GENL_mc_group(group) \
err = genl_register_mc_group(&ZZZ_genl_family, \
&CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \
if (err) \
goto fail; \
else \
pr_info("%s: mcg %s: %u\n", #group, \
__stringify(GENL_MAGIC_FAMILY), \
CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id);

#include GENL_MAGIC_INCLUDE_FILE

#undef GENL_mc_group
#define GENL_mc_group(group)
return 0;
fail:
genl_unregister_family(&ZZZ_genl_family);
return err;

int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
{
return genl_register_family_with_ops_groups(&ZZZ_genl_family, \
ZZZ_genl_ops, \
ZZZ_genl_mcgrps);
}

void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void)
Expand Down
Loading

0 comments on commit 091e066

Please sign in to comment.