[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: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
85ccc365e9
Коммит
79dc4386ae
|
@ -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);
|
||||||
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)
|
||||||
{
|
{
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Загрузка…
Ссылка в новой задаче