aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-11-19 09:19:39 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-19 16:39:06 -0500
commit2a94fe48f32ccf7321450a2cc07f2b724a444e5b (patch)
treee5a066d8f83d8822d448421019a4503f361295f9 /net/openvswitch
parent68eb55031da7c967d954e5f9415cd05f4abdb692 (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')
-rw-r--r--net/openvswitch/datapath.c43
-rw-r--r--net/openvswitch/dp_notify.c6
2 files changed, 17 insertions, 32 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 @@
62int ovs_net_id __read_mostly; 62int ovs_net_id __read_mostly;
63 63
64static void ovs_notify(struct genl_family *family, 64static 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
888err_flow_free: 886err_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;
998unlock: 995unlock:
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
1247err_destroy_local_port: 1243err_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;
1313unlock: 1308unlock:
@@ -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;
1345unlock: 1339unlock:
@@ -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
1607exit_unlock: 1600exit_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
1656exit_free: 1648exit_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
1693exit_unlock: 1684exit_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
1796static const struct genl_family_and_ops dp_genl_families[] = { 1787static 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;
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c
index f4b66c84ea0b..2c631fe76be1 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -35,15 +35,13 @@ static void dp_detach_port_notify(struct vport *vport)
35 ovs_dp_detach_port(vport); 35 ovs_dp_detach_port(vport);
36 if (IS_ERR(notify)) { 36 if (IS_ERR(notify)) {
37 genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0, 37 genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
38 ovs_dp_vport_multicast_group.id, 38 0, PTR_ERR(notify));
39 PTR_ERR(notify));
40 return; 39 return;
41 } 40 }
42 41
43 genlmsg_multicast_netns(&dp_vport_genl_family, 42 genlmsg_multicast_netns(&dp_vport_genl_family,
44 ovs_dp_get_net(dp), notify, 0, 43 ovs_dp_get_net(dp), notify, 0,
45 ovs_dp_vport_multicast_group.id, 44 0, GFP_KERNEL);
46 GFP_KERNEL);
47} 45}
48 46
49void ovs_dp_notify_wq(struct work_struct *work) 47void ovs_dp_notify_wq(struct work_struct *work)