Commit 79dc4386 authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller

[GENETLINK]: Fix race in genl_unregister_mc_groups()

family->mcast_groups is protected by genl_lock so it must
be held while accessing the list in genl_unregister_mc_groups().
Requires adding a non-locking variant of genl_unregister_mc_group().
Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 85ccc365
...@@ -200,6 +200,18 @@ int genl_register_mc_group(struct genl_family *family, ...@@ -200,6 +200,18 @@ int genl_register_mc_group(struct genl_family *family,
} }
EXPORT_SYMBOL(genl_register_mc_group); EXPORT_SYMBOL(genl_register_mc_group);
static void __genl_unregister_mc_group(struct genl_family *family,
struct genl_multicast_group *grp)
{
BUG_ON(grp->family != family);
netlink_clear_multicast_users(genl_sock, grp->id);
clear_bit(grp->id, mc_groups);
list_del(&grp->list);
genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
grp->id = 0;
grp->family = NULL;
}
/** /**
* genl_unregister_mc_group - unregister a multicast group * genl_unregister_mc_group - unregister a multicast group
* *
...@@ -217,14 +229,8 @@ EXPORT_SYMBOL(genl_register_mc_group); ...@@ -217,14 +229,8 @@ EXPORT_SYMBOL(genl_register_mc_group);
void genl_unregister_mc_group(struct genl_family *family, void genl_unregister_mc_group(struct genl_family *family,
struct genl_multicast_group *grp) struct genl_multicast_group *grp)
{ {
BUG_ON(grp->family != family);
genl_lock(); genl_lock();
netlink_clear_multicast_users(genl_sock, grp->id); __genl_unregister_mc_group(family, grp);
clear_bit(grp->id, mc_groups);
list_del(&grp->list);
genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
grp->id = 0;
grp->family = NULL;
genl_unlock(); genl_unlock();
} }
...@@ -232,8 +238,10 @@ static void genl_unregister_mc_groups(struct genl_family *family) ...@@ -232,8 +238,10 @@ static void genl_unregister_mc_groups(struct genl_family *family)
{ {
struct genl_multicast_group *grp, *tmp; struct genl_multicast_group *grp, *tmp;
genl_lock();
list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list) list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list)
genl_unregister_mc_group(family, grp); __genl_unregister_mc_group(family, grp);
genl_unlock();
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment