diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-11-19 09:19:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-19 16:39:06 -0500 |
commit | 2a94fe48f32ccf7321450a2cc07f2b724a444e5b (patch) | |
tree | e5a066d8f83d8822d448421019a4503f361295f9 /net/openvswitch/datapath.c | |
parent | 68eb55031da7c967d954e5f9415cd05f4abdb692 (diff) |
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: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 43 |
1 files changed, 15 insertions, 28 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 5c19846b1d2a..1de4d281e3f1 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -62,11 +62,10 @@ | |||
62 | int ovs_net_id __read_mostly; | 62 | int ovs_net_id __read_mostly; |
63 | 63 | ||
64 | static void ovs_notify(struct genl_family *family, | 64 | static void ovs_notify(struct genl_family *family, |
65 | struct sk_buff *skb, struct genl_info *info, | 65 | struct sk_buff *skb, struct genl_info *info) |
66 | struct genl_multicast_group *grp) | ||
67 | { | 66 | { |
68 | genl_notify(family, skb, genl_info_net(info), info->snd_portid, | 67 | genl_notify(family, skb, genl_info_net(info), info->snd_portid, |
69 | grp->id, info->nlhdr, GFP_KERNEL); | 68 | 0, info->nlhdr, GFP_KERNEL); |
70 | } | 69 | } |
71 | 70 | ||
72 | /** | 71 | /** |
@@ -878,11 +877,10 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
878 | ovs_unlock(); | 877 | ovs_unlock(); |
879 | 878 | ||
880 | if (!IS_ERR(reply)) | 879 | if (!IS_ERR(reply)) |
881 | ovs_notify(&dp_flow_genl_family, reply, info, | 880 | ovs_notify(&dp_flow_genl_family, reply, info); |
882 | &ovs_dp_flow_multicast_group); | ||
883 | else | 881 | else |
884 | genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 0, | 882 | genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 0, |
885 | ovs_dp_flow_multicast_group.id, PTR_ERR(reply)); | 883 | 0, PTR_ERR(reply)); |
886 | return 0; | 884 | return 0; |
887 | 885 | ||
888 | err_flow_free: | 886 | err_flow_free: |
@@ -992,8 +990,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
992 | ovs_flow_free(flow, true); | 990 | ovs_flow_free(flow, true); |
993 | ovs_unlock(); | 991 | ovs_unlock(); |
994 | 992 | ||
995 | ovs_notify(&dp_flow_genl_family, reply, info, | 993 | ovs_notify(&dp_flow_genl_family, reply, info); |
996 | &ovs_dp_flow_multicast_group); | ||
997 | return 0; | 994 | return 0; |
998 | unlock: | 995 | unlock: |
999 | ovs_unlock(); | 996 | ovs_unlock(); |
@@ -1240,8 +1237,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1240 | 1237 | ||
1241 | ovs_unlock(); | 1238 | ovs_unlock(); |
1242 | 1239 | ||
1243 | ovs_notify(&dp_datapath_genl_family, reply, info, | 1240 | ovs_notify(&dp_datapath_genl_family, reply, info); |
1244 | &ovs_dp_datapath_multicast_group); | ||
1245 | return 0; | 1241 | return 0; |
1246 | 1242 | ||
1247 | err_destroy_local_port: | 1243 | err_destroy_local_port: |
@@ -1306,8 +1302,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1306 | __dp_destroy(dp); | 1302 | __dp_destroy(dp); |
1307 | ovs_unlock(); | 1303 | ovs_unlock(); |
1308 | 1304 | ||
1309 | ovs_notify(&dp_datapath_genl_family, reply, info, | 1305 | ovs_notify(&dp_datapath_genl_family, reply, info); |
1310 | &ovs_dp_datapath_multicast_group); | ||
1311 | 1306 | ||
1312 | return 0; | 1307 | return 0; |
1313 | unlock: | 1308 | unlock: |
@@ -1332,14 +1327,13 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1332 | if (IS_ERR(reply)) { | 1327 | if (IS_ERR(reply)) { |
1333 | err = PTR_ERR(reply); | 1328 | err = PTR_ERR(reply); |
1334 | genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0, | 1329 | genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0, |
1335 | ovs_dp_datapath_multicast_group.id, err); | 1330 | 0, err); |
1336 | err = 0; | 1331 | err = 0; |
1337 | goto unlock; | 1332 | goto unlock; |
1338 | } | 1333 | } |
1339 | 1334 | ||
1340 | ovs_unlock(); | 1335 | ovs_unlock(); |
1341 | ovs_notify(&dp_datapath_genl_family, reply, info, | 1336 | ovs_notify(&dp_datapath_genl_family, reply, info); |
1342 | &ovs_dp_datapath_multicast_group); | ||
1343 | 1337 | ||
1344 | return 0; | 1338 | return 0; |
1345 | unlock: | 1339 | unlock: |
@@ -1601,8 +1595,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1601 | goto exit_unlock; | 1595 | goto exit_unlock; |
1602 | } | 1596 | } |
1603 | 1597 | ||
1604 | ovs_notify(&dp_vport_genl_family, reply, info, | 1598 | ovs_notify(&dp_vport_genl_family, reply, info); |
1605 | &ovs_dp_vport_multicast_group); | ||
1606 | 1599 | ||
1607 | exit_unlock: | 1600 | exit_unlock: |
1608 | ovs_unlock(); | 1601 | ovs_unlock(); |
@@ -1649,8 +1642,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1649 | BUG_ON(err < 0); | 1642 | BUG_ON(err < 0); |
1650 | 1643 | ||
1651 | ovs_unlock(); | 1644 | ovs_unlock(); |
1652 | ovs_notify(&dp_vport_genl_family, reply, info, | 1645 | ovs_notify(&dp_vport_genl_family, reply, info); |
1653 | &ovs_dp_vport_multicast_group); | ||
1654 | return 0; | 1646 | return 0; |
1655 | 1647 | ||
1656 | exit_free: | 1648 | exit_free: |
@@ -1687,8 +1679,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1687 | err = 0; | 1679 | err = 0; |
1688 | ovs_dp_detach_port(vport); | 1680 | ovs_dp_detach_port(vport); |
1689 | 1681 | ||
1690 | ovs_notify(&dp_vport_genl_family, reply, info, | 1682 | ovs_notify(&dp_vport_genl_family, reply, info); |
1691 | &ovs_dp_vport_multicast_group); | ||
1692 | 1683 | ||
1693 | exit_unlock: | 1684 | exit_unlock: |
1694 | ovs_unlock(); | 1685 | ovs_unlock(); |
@@ -1790,7 +1781,7 @@ struct genl_family_and_ops { | |||
1790 | struct genl_family *family; | 1781 | struct genl_family *family; |
1791 | const struct genl_ops *ops; | 1782 | const struct genl_ops *ops; |
1792 | int n_ops; | 1783 | int n_ops; |
1793 | struct genl_multicast_group *group; | 1784 | const struct genl_multicast_group *group; |
1794 | }; | 1785 | }; |
1795 | 1786 | ||
1796 | static const struct genl_family_and_ops dp_genl_families[] = { | 1787 | static const struct genl_family_and_ops dp_genl_families[] = { |
@@ -1828,16 +1819,12 @@ static int dp_register_genl(void) | |||
1828 | 1819 | ||
1829 | f->family->ops = f->ops; | 1820 | f->family->ops = f->ops; |
1830 | f->family->n_ops = f->n_ops; | 1821 | f->family->n_ops = f->n_ops; |
1822 | f->family->mcgrps = f->group; | ||
1823 | f->family->n_mcgrps = f->group ? 1 : 0; | ||
1831 | err = genl_register_family(f->family); | 1824 | err = genl_register_family(f->family); |
1832 | if (err) | 1825 | if (err) |
1833 | goto error; | 1826 | goto error; |
1834 | n_registered++; | 1827 | n_registered++; |
1835 | |||
1836 | if (f->group) { | ||
1837 | err = genl_register_mc_group(f->family, f->group); | ||
1838 | if (err) | ||
1839 | goto error; | ||
1840 | } | ||
1841 | } | 1828 | } |
1842 | 1829 | ||
1843 | return 0; | 1830 | return 0; |