Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a94fe48 authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller
Browse files

genetlink: make multicast groups const, prevent abuse



Register generic netlink multicast groups as an array with
the family and give them contiguous group IDs. Then instead
of passing the global group ID to the various functions that
send messages, pass the ID relative to the family - for most
families that's just 0 because the only have one group.

This avoids the list_head and ID in each group, adding a new
field for the mcast group ID offset to the family.

At the same time, this allows us to prevent abusing groups
again like the quota and dropmon code did, since we can now
check that a family only uses a group it owns.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 68eb5503
Loading
Loading
Loading
Loading
+8 −18
Original line number Diff line number Diff line
@@ -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,
@@ -146,8 +148,7 @@ int acpi_bus_generate_netlink_event(const char *device_class,
		return result;
	}

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

@@ -155,18 +156,7 @@ 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
+5 −20
Original line number Diff line number Diff line
@@ -2670,16 +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(&team_nl_family, dev_net(team->dev),
				       skb, 0, team_change_event_mcgrp.id,
				       GFP_KERNEL);
				       skb, 0, 0, GFP_KERNEL);
}

static int team_nl_send_event_options_get(struct team *team,
@@ -2698,22 +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);
	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)
+8 −16
Original line number Diff line number Diff line
@@ -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,
@@ -1676,7 +1678,7 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
	}

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

@@ -1686,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)
+7 −8
Original line number Diff line number Diff line
@@ -9,6 +9,10 @@
#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 = {
	/*
@@ -22,10 +26,8 @@ static struct genl_family quota_genl_family = {
	.name = "VFS_DQUOT",
	.version = 1,
	.maxattr = QUOTA_NL_A_MAX,
};

static struct genl_multicast_group quota_mcgrp = {
	.name = "events",
	.mcgrps = quota_mcgrps,
	.n_mcgrps = ARRAY_SIZE(quota_mcgrps),
};

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

	genlmsg_multicast(&quota_genl_family, skb, 0, quota_mcgrp.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");
@@ -102,9 +104,6 @@ static int __init quota_init(void)
	if (genl_register_family(&quota_genl_family) != 0)
		printk(KERN_ERR
		       "VFS: Failed to create quota netlink interface.\n");
	if (genl_register_mc_group(&quota_genl_family, &quota_mcgrp))
		printk(KERN_ERR
		       "VFS: Failed to register quota mcast group.\n");
	return 0;
};

+20 −29
Original line number Diff line number Diff line
@@ -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;						\
		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);
	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)
Loading