aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink
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/netlink
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/netlink')
-rw-r--r--net/netlink/genetlink.c278
1 files changed, 166 insertions, 112 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 36e3a86cacf6..7dbc4f732c75 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -69,16 +69,20 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
69 * abuses the API and thinks it can statically use group 1. 69 * abuses the API and thinks it can statically use group 1.
70 * That group will typically conflict with other groups that 70 * That group will typically conflict with other groups that
71 * any proper users use. 71 * any proper users use.
72 * Bit 16 is marked as used since it's used for generic netlink
73 * and the code no longer marks pre-reserved IDs as used.
72 * Bit 17 is marked as already used since the VFS quota code 74 * Bit 17 is marked as already used since the VFS quota code
73 * also abused this API and relied on family == group ID, we 75 * also abused this API and relied on family == group ID, we
74 * cater to that by giving it a static family and group ID. 76 * cater to that by giving it a static family and group ID.
75 */ 77 */
76static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_VFS_DQUOT); 78static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
79 BIT(GENL_ID_VFS_DQUOT);
77static unsigned long *mc_groups = &mc_group_start; 80static unsigned long *mc_groups = &mc_group_start;
78static unsigned long mc_groups_longs = 1; 81static unsigned long mc_groups_longs = 1;
79 82
80static int genl_ctrl_event(int event, struct genl_family *family, 83static int genl_ctrl_event(int event, struct genl_family *family,
81 struct genl_multicast_group *grp); 84 const struct genl_multicast_group *grp,
85 int grp_id);
82 86
83static inline unsigned int genl_family_hash(unsigned int id) 87static inline unsigned int genl_family_hash(unsigned int id)
84{ 88{
@@ -144,66 +148,110 @@ static u16 genl_generate_id(void)
144 return 0; 148 return 0;
145} 149}
146 150
147static struct genl_multicast_group notify_grp; 151static int genl_allocate_reserve_groups(int n_groups, int *first_id)
148
149/**
150 * genl_register_mc_group - register a multicast group
151 *
152 * Registers the specified multicast group and notifies userspace
153 * about the new group.
154 *
155 * Returns 0 on success or a negative error code.
156 *
157 * @family: The generic netlink family the group shall be registered for.
158 * @grp: The group to register, must have a name.
159 */
160int genl_register_mc_group(struct genl_family *family,
161 struct genl_multicast_group *grp)
162{ 152{
163 int id;
164 unsigned long *new_groups; 153 unsigned long *new_groups;
165 int err = 0; 154 int start = 0;
155 int i;
156 int id;
157 bool fits;
158
159 do {
160 if (start == 0)
161 id = find_first_zero_bit(mc_groups,
162 mc_groups_longs *
163 BITS_PER_LONG);
164 else
165 id = find_next_zero_bit(mc_groups,
166 mc_groups_longs * BITS_PER_LONG,
167 start);
168
169 fits = true;
170 for (i = id;
171 i < min_t(int, id + n_groups,
172 mc_groups_longs * BITS_PER_LONG);
173 i++) {
174 if (test_bit(i, mc_groups)) {
175 start = i;
176 fits = false;
177 break;
178 }
179 }
166 180
167 BUG_ON(grp->name[0] == '\0'); 181 if (id >= mc_groups_longs * BITS_PER_LONG) {
168 BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL); 182 unsigned long new_longs = mc_groups_longs +
183 BITS_TO_LONGS(n_groups);
184 size_t nlen = new_longs * sizeof(unsigned long);
185
186 if (mc_groups == &mc_group_start) {
187 new_groups = kzalloc(nlen, GFP_KERNEL);
188 if (!new_groups)
189 return -ENOMEM;
190 mc_groups = new_groups;
191 *mc_groups = mc_group_start;
192 } else {
193 new_groups = krealloc(mc_groups, nlen,
194 GFP_KERNEL);
195 if (!new_groups)
196 return -ENOMEM;
197 mc_groups = new_groups;
198 for (i = 0; i < BITS_TO_LONGS(n_groups); i++)
199 mc_groups[mc_groups_longs + i] = 0;
200 }
201 mc_groups_longs = new_longs;
202 }
203 } while (!fits);
169 204
170 genl_lock_all(); 205 for (i = id; i < id + n_groups; i++)
206 set_bit(i, mc_groups);
207 *first_id = id;
208 return 0;
209}
210
211static struct genl_family genl_ctrl;
212
213static int genl_validate_assign_mc_groups(struct genl_family *family)
214{
215 int first_id;
216 int n_groups = family->n_mcgrps;
217 int err, i;
218 bool groups_allocated = false;
219
220 if (!n_groups)
221 return 0;
222
223 for (i = 0; i < n_groups; i++) {
224 const struct genl_multicast_group *grp = &family->mcgrps[i];
225
226 if (WARN_ON(grp->name[0] == '\0'))
227 return -EINVAL;
228 if (WARN_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL))
229 return -EINVAL;
230 }
171 231
172 /* special-case our own group and hacks */ 232 /* special-case our own group and hacks */
173 if (grp == &notify_grp) 233 if (family == &genl_ctrl) {
174 id = GENL_ID_CTRL; 234 first_id = GENL_ID_CTRL;
175 else if (strcmp(family->name, "NET_DM") == 0) 235 BUG_ON(n_groups != 1);
176 id = 1; 236 } else if (strcmp(family->name, "NET_DM") == 0) {
177 else if (strcmp(family->name, "VFS_DQUOT") == 0) 237 first_id = 1;
178 id = GENL_ID_VFS_DQUOT; 238 BUG_ON(n_groups != 1);
179 else 239 } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
180 id = find_first_zero_bit(mc_groups, 240 first_id = GENL_ID_VFS_DQUOT;
181 mc_groups_longs * BITS_PER_LONG); 241 BUG_ON(n_groups != 1);
182 242 } else {
183 243 groups_allocated = true;
184 if (id >= mc_groups_longs * BITS_PER_LONG) { 244 err = genl_allocate_reserve_groups(n_groups, &first_id);
185 size_t nlen = (mc_groups_longs + 1) * sizeof(unsigned long); 245 if (err)
186 246 return err;
187 if (mc_groups == &mc_group_start) {
188 new_groups = kzalloc(nlen, GFP_KERNEL);
189 if (!new_groups) {
190 err = -ENOMEM;
191 goto out;
192 }
193 mc_groups = new_groups;
194 *mc_groups = mc_group_start;
195 } else {
196 new_groups = krealloc(mc_groups, nlen, GFP_KERNEL);
197 if (!new_groups) {
198 err = -ENOMEM;
199 goto out;
200 }
201 mc_groups = new_groups;
202 mc_groups[mc_groups_longs] = 0;
203 }
204 mc_groups_longs++;
205 } 247 }
206 248
249 family->mcgrp_offset = first_id;
250
251 /* if still initializing, can't and don't need to to realloc bitmaps */
252 if (!init_net.genl_sock)
253 return 0;
254
207 if (family->netnsok) { 255 if (family->netnsok) {
208 struct net *net; 256 struct net *net;
209 257
@@ -219,9 +267,7 @@ int genl_register_mc_group(struct genl_family *family,
219 * number of _possible_ groups has been 267 * number of _possible_ groups has been
220 * increased on some sockets which is ok. 268 * increased on some sockets which is ok.
221 */ 269 */
222 rcu_read_unlock(); 270 break;
223 netlink_table_ungrab();
224 goto out;
225 } 271 }
226 } 272 }
227 rcu_read_unlock(); 273 rcu_read_unlock();
@@ -229,46 +275,39 @@ int genl_register_mc_group(struct genl_family *family,
229 } else { 275 } else {
230 err = netlink_change_ngroups(init_net.genl_sock, 276 err = netlink_change_ngroups(init_net.genl_sock,
231 mc_groups_longs * BITS_PER_LONG); 277 mc_groups_longs * BITS_PER_LONG);
232 if (err)
233 goto out;
234 } 278 }
235 279
236 grp->id = id; 280 if (groups_allocated && err) {
237 set_bit(id, mc_groups); 281 for (i = 0; i < family->n_mcgrps; i++)
238 list_add_tail(&grp->list, &family->mcast_groups); 282 clear_bit(family->mcgrp_offset + i, mc_groups);
283 }
239 284
240 genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, family, grp);
241 out:
242 genl_unlock_all();
243 return err; 285 return err;
244} 286}
245EXPORT_SYMBOL(genl_register_mc_group);
246 287
247static void __genl_unregister_mc_group(struct genl_family *family, 288static void genl_unregister_mc_groups(struct genl_family *family)
248 struct genl_multicast_group *grp)
249{ 289{
250 struct net *net; 290 struct net *net;
291 int i;
251 292
252 netlink_table_grab(); 293 netlink_table_grab();
253 rcu_read_lock(); 294 rcu_read_lock();
254 for_each_net_rcu(net) 295 for_each_net_rcu(net) {
255 __netlink_clear_multicast_users(net->genl_sock, grp->id); 296 for (i = 0; i < family->n_mcgrps; i++)
297 __netlink_clear_multicast_users(
298 net->genl_sock, family->mcgrp_offset + i);
299 }
256 rcu_read_unlock(); 300 rcu_read_unlock();
257 netlink_table_ungrab(); 301 netlink_table_ungrab();
258 302
259 if (grp->id != 1) 303 for (i = 0; i < family->n_mcgrps; i++) {
260 clear_bit(grp->id, mc_groups); 304 int grp_id = family->mcgrp_offset + i;
261 list_del(&grp->list);
262 genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, family, grp);
263 grp->id = 0;
264}
265
266static void genl_unregister_mc_groups(struct genl_family *family)
267{
268 struct genl_multicast_group *grp, *tmp;
269 305
270 list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list) 306 if (grp_id != 1)
271 __genl_unregister_mc_group(family, grp); 307 clear_bit(grp_id, mc_groups);
308 genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, family,
309 &family->mcgrps[i], grp_id);
310 }
272} 311}
273 312
274static int genl_validate_ops(struct genl_family *family) 313static int genl_validate_ops(struct genl_family *family)
@@ -314,7 +353,7 @@ static int genl_validate_ops(struct genl_family *family)
314 */ 353 */
315int __genl_register_family(struct genl_family *family) 354int __genl_register_family(struct genl_family *family)
316{ 355{
317 int err = -EINVAL; 356 int err = -EINVAL, i;
318 357
319 if (family->id && family->id < GENL_MIN_ID) 358 if (family->id && family->id < GENL_MIN_ID)
320 goto errout; 359 goto errout;
@@ -326,8 +365,6 @@ int __genl_register_family(struct genl_family *family)
326 if (err) 365 if (err)
327 return err; 366 return err;
328 367
329 INIT_LIST_HEAD(&family->mcast_groups);
330
331 genl_lock_all(); 368 genl_lock_all();
332 369
333 if (genl_family_find_byname(family->name)) { 370 if (genl_family_find_byname(family->name)) {
@@ -359,10 +396,18 @@ int __genl_register_family(struct genl_family *family)
359 } else 396 } else
360 family->attrbuf = NULL; 397 family->attrbuf = NULL;
361 398
399 err = genl_validate_assign_mc_groups(family);
400 if (err)
401 goto errout_locked;
402
362 list_add_tail(&family->family_list, genl_family_chain(family->id)); 403 list_add_tail(&family->family_list, genl_family_chain(family->id));
363 genl_unlock_all(); 404 genl_unlock_all();
364 405
365 genl_ctrl_event(CTRL_CMD_NEWFAMILY, family, NULL); 406 /* send all events */
407 genl_ctrl_event(CTRL_CMD_NEWFAMILY, family, NULL, 0);
408 for (i = 0; i < family->n_mcgrps; i++)
409 genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, family,
410 &family->mcgrps[i], family->mcgrp_offset + i);
366 411
367 return 0; 412 return 0;
368 413
@@ -398,7 +443,7 @@ int genl_unregister_family(struct genl_family *family)
398 genl_unlock_all(); 443 genl_unlock_all();
399 444
400 kfree(family->attrbuf); 445 kfree(family->attrbuf);
401 genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL); 446 genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
402 return 0; 447 return 0;
403 } 448 }
404 449
@@ -658,23 +703,26 @@ static int ctrl_fill_info(struct genl_family *family, u32 portid, u32 seq,
658 nla_nest_end(skb, nla_ops); 703 nla_nest_end(skb, nla_ops);
659 } 704 }
660 705
661 if (!list_empty(&family->mcast_groups)) { 706 if (family->n_mcgrps) {
662 struct genl_multicast_group *grp;
663 struct nlattr *nla_grps; 707 struct nlattr *nla_grps;
664 int idx = 1; 708 int i;
665 709
666 nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS); 710 nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);
667 if (nla_grps == NULL) 711 if (nla_grps == NULL)
668 goto nla_put_failure; 712 goto nla_put_failure;
669 713
670 list_for_each_entry(grp, &family->mcast_groups, list) { 714 for (i = 0; i < family->n_mcgrps; i++) {
671 struct nlattr *nest; 715 struct nlattr *nest;
716 const struct genl_multicast_group *grp;
672 717
673 nest = nla_nest_start(skb, idx++); 718 grp = &family->mcgrps[i];
719
720 nest = nla_nest_start(skb, i + 1);
674 if (nest == NULL) 721 if (nest == NULL)
675 goto nla_put_failure; 722 goto nla_put_failure;
676 723
677 if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id) || 724 if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID,
725 family->mcgrp_offset + i) ||
678 nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME, 726 nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
679 grp->name)) 727 grp->name))
680 goto nla_put_failure; 728 goto nla_put_failure;
@@ -692,9 +740,9 @@ nla_put_failure:
692} 740}
693 741
694static int ctrl_fill_mcgrp_info(struct genl_family *family, 742static int ctrl_fill_mcgrp_info(struct genl_family *family,
695 struct genl_multicast_group *grp, u32 portid, 743 const struct genl_multicast_group *grp,
696 u32 seq, u32 flags, struct sk_buff *skb, 744 int grp_id, u32 portid, u32 seq, u32 flags,
697 u8 cmd) 745 struct sk_buff *skb, u8 cmd)
698{ 746{
699 void *hdr; 747 void *hdr;
700 struct nlattr *nla_grps; 748 struct nlattr *nla_grps;
@@ -716,7 +764,7 @@ static int ctrl_fill_mcgrp_info(struct genl_family *family,
716 if (nest == NULL) 764 if (nest == NULL)
717 goto nla_put_failure; 765 goto nla_put_failure;
718 766
719 if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id) || 767 if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp_id) ||
720 nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME, 768 nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
721 grp->name)) 769 grp->name))
722 goto nla_put_failure; 770 goto nla_put_failure;
@@ -782,9 +830,10 @@ static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
782 return skb; 830 return skb;
783} 831}
784 832
785static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_family *family, 833static struct sk_buff *
786 struct genl_multicast_group *grp, 834ctrl_build_mcgrp_msg(struct genl_family *family,
787 u32 portid, int seq, u8 cmd) 835 const struct genl_multicast_group *grp,
836 int grp_id, u32 portid, int seq, u8 cmd)
788{ 837{
789 struct sk_buff *skb; 838 struct sk_buff *skb;
790 int err; 839 int err;
@@ -793,7 +842,8 @@ static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_family *family,
793 if (skb == NULL) 842 if (skb == NULL)
794 return ERR_PTR(-ENOBUFS); 843 return ERR_PTR(-ENOBUFS);
795 844
796 err = ctrl_fill_mcgrp_info(family, grp, portid, seq, 0, skb, cmd); 845 err = ctrl_fill_mcgrp_info(family, grp, grp_id, portid,
846 seq, 0, skb, cmd);
797 if (err < 0) { 847 if (err < 0) {
798 nlmsg_free(skb); 848 nlmsg_free(skb);
799 return ERR_PTR(err); 849 return ERR_PTR(err);
@@ -856,7 +906,8 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
856} 906}
857 907
858static int genl_ctrl_event(int event, struct genl_family *family, 908static int genl_ctrl_event(int event, struct genl_family *family,
859 struct genl_multicast_group *grp) 909 const struct genl_multicast_group *grp,
910 int grp_id)
860{ 911{
861 struct sk_buff *msg; 912 struct sk_buff *msg;
862 913
@@ -873,7 +924,7 @@ static int genl_ctrl_event(int event, struct genl_family *family,
873 case CTRL_CMD_NEWMCAST_GRP: 924 case CTRL_CMD_NEWMCAST_GRP:
874 case CTRL_CMD_DELMCAST_GRP: 925 case CTRL_CMD_DELMCAST_GRP:
875 BUG_ON(!grp); 926 BUG_ON(!grp);
876 msg = ctrl_build_mcgrp_msg(family, grp, 0, 0, event); 927 msg = ctrl_build_mcgrp_msg(family, grp, grp_id, 0, 0, event);
877 break; 928 break;
878 default: 929 default:
879 return -EINVAL; 930 return -EINVAL;
@@ -884,11 +935,11 @@ static int genl_ctrl_event(int event, struct genl_family *family,
884 935
885 if (!family->netnsok) { 936 if (!family->netnsok) {
886 genlmsg_multicast_netns(&genl_ctrl, &init_net, msg, 0, 937 genlmsg_multicast_netns(&genl_ctrl, &init_net, msg, 0,
887 GENL_ID_CTRL, GFP_KERNEL); 938 0, GFP_KERNEL);
888 } else { 939 } else {
889 rcu_read_lock(); 940 rcu_read_lock();
890 genlmsg_multicast_allns(&genl_ctrl, msg, 0, 941 genlmsg_multicast_allns(&genl_ctrl, msg, 0,
891 GENL_ID_CTRL, GFP_ATOMIC); 942 0, GFP_ATOMIC);
892 rcu_read_unlock(); 943 rcu_read_unlock();
893 } 944 }
894 945
@@ -904,8 +955,8 @@ static struct genl_ops genl_ctrl_ops[] = {
904 }, 955 },
905}; 956};
906 957
907static struct genl_multicast_group notify_grp = { 958static struct genl_multicast_group genl_ctrl_groups[] = {
908 .name = "notify", 959 { .name = "notify", },
909}; 960};
910 961
911static int __net_init genl_pernet_init(struct net *net) 962static int __net_init genl_pernet_init(struct net *net)
@@ -945,7 +996,8 @@ static int __init genl_init(void)
945 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) 996 for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
946 INIT_LIST_HEAD(&family_ht[i]); 997 INIT_LIST_HEAD(&family_ht[i]);
947 998
948 err = genl_register_family_with_ops(&genl_ctrl, genl_ctrl_ops); 999 err = genl_register_family_with_ops_groups(&genl_ctrl, genl_ctrl_ops,
1000 genl_ctrl_groups);
949 if (err < 0) 1001 if (err < 0)
950 goto problem; 1002 goto problem;
951 1003
@@ -953,10 +1005,6 @@ static int __init genl_init(void)
953 if (err) 1005 if (err)
954 goto problem; 1006 goto problem;
955 1007
956 err = genl_register_mc_group(&genl_ctrl, &notify_grp);
957 if (err < 0)
958 goto problem;
959
960 return 0; 1008 return 0;
961 1009
962problem: 1010problem:
@@ -997,6 +1045,9 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
997int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb, 1045int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
998 u32 portid, unsigned int group, gfp_t flags) 1046 u32 portid, unsigned int group, gfp_t flags)
999{ 1047{
1048 if (group >= family->n_mcgrps)
1049 return -EINVAL;
1050 group = family->mcgrp_offset + group;
1000 return genlmsg_mcast(skb, portid, group, flags); 1051 return genlmsg_mcast(skb, portid, group, flags);
1001} 1052}
1002EXPORT_SYMBOL(genlmsg_multicast_allns); 1053EXPORT_SYMBOL(genlmsg_multicast_allns);
@@ -1011,6 +1062,9 @@ void genl_notify(struct genl_family *family,
1011 if (nlh) 1062 if (nlh)
1012 report = nlmsg_report(nlh); 1063 report = nlmsg_report(nlh);
1013 1064
1065 if (group >= family->n_mcgrps)
1066 return;
1067 group = family->mcgrp_offset + group;
1014 nlmsg_notify(sk, skb, portid, group, report, flags); 1068 nlmsg_notify(sk, skb, portid, group, report, flags);
1015} 1069}
1016EXPORT_SYMBOL(genl_notify); 1070EXPORT_SYMBOL(genl_notify);