Branch data Line data Source code
1 : : /*
2 : : * NETLINK Generic Netlink Family
3 : : *
4 : : * Authors: Jamal Hadi Salim
5 : : * Thomas Graf <tgraf@suug.ch>
6 : : * Johannes Berg <johannes@sipsolutions.net>
7 : : */
8 : :
9 : : #include <linux/module.h>
10 : : #include <linux/kernel.h>
11 : : #include <linux/slab.h>
12 : : #include <linux/errno.h>
13 : : #include <linux/types.h>
14 : : #include <linux/socket.h>
15 : : #include <linux/string.h>
16 : : #include <linux/skbuff.h>
17 : : #include <linux/mutex.h>
18 : : #include <linux/bitmap.h>
19 : : #include <linux/rwsem.h>
20 : : #include <net/sock.h>
21 : : #include <net/genetlink.h>
22 : :
23 : : static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
24 : : static DECLARE_RWSEM(cb_lock);
25 : :
26 : 0 : void genl_lock(void)
27 : : {
28 : 2 : mutex_lock(&genl_mutex);
29 : 0 : }
30 : : EXPORT_SYMBOL(genl_lock);
31 : :
32 : 0 : void genl_unlock(void)
33 : : {
34 : 2 : mutex_unlock(&genl_mutex);
35 : 0 : }
36 : : EXPORT_SYMBOL(genl_unlock);
37 : :
38 : : #ifdef CONFIG_LOCKDEP
39 : : int lockdep_genl_is_held(void)
40 : : {
41 : : return lockdep_is_held(&genl_mutex);
42 : : }
43 : : EXPORT_SYMBOL(lockdep_genl_is_held);
44 : : #endif
45 : :
46 : : static void genl_lock_all(void)
47 : : {
48 : 0 : down_write(&cb_lock);
49 : : genl_lock();
50 : : }
51 : :
52 : : static void genl_unlock_all(void)
53 : : {
54 : : genl_unlock();
55 : 0 : up_write(&cb_lock);
56 : : }
57 : :
58 : : #define GENL_FAM_TAB_SIZE 16
59 : : #define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1)
60 : :
61 : : static struct list_head family_ht[GENL_FAM_TAB_SIZE];
62 : : /*
63 : : * Bitmap of multicast groups that are currently in use.
64 : : *
65 : : * To avoid an allocation at boot of just one unsigned long,
66 : : * declare it global instead.
67 : : * Bit 0 is marked as already used since group 0 is invalid.
68 : : * Bit 1 is marked as already used since the drop-monitor code
69 : : * abuses the API and thinks it can statically use group 1.
70 : : * That group will typically conflict with other groups that
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.
74 : : * Bit 17 is marked as already used since the VFS quota code
75 : : * also abused this API and relied on family == group ID, we
76 : : * cater to that by giving it a static family and group ID.
77 : : * Bit 18 is marked as already used since the PMCRAID driver
78 : : * did the same thing as the VFS quota code (maybe copied?)
79 : : */
80 : : static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
81 : : BIT(GENL_ID_VFS_DQUOT) |
82 : : BIT(GENL_ID_PMCRAID);
83 : : static unsigned long *mc_groups = &mc_group_start;
84 : : static unsigned long mc_groups_longs = 1;
85 : :
86 : : static int genl_ctrl_event(int event, struct genl_family *family,
87 : : const struct genl_multicast_group *grp,
88 : : int grp_id);
89 : :
90 : : static inline unsigned int genl_family_hash(unsigned int id)
91 : : {
92 : 33 : return id & GENL_FAM_TAB_MASK;
93 : : }
94 : :
95 : : static inline struct list_head *genl_family_chain(unsigned int id)
96 : : {
97 : : return &family_ht[genl_family_hash(id)];
98 : : }
99 : :
100 : : static struct genl_family *genl_family_find_byid(unsigned int id)
101 : : {
102 : : struct genl_family *f;
103 : :
104 [ # # ][ + - ]: 1 : list_for_each_entry(f, genl_family_chain(id), family_list)
[ # # ][ # # ]
105 [ # # ][ - + ]: 1 : if (f->id == id)
[ # # ][ # # ]
106 : : return f;
107 : :
108 : : return NULL;
109 : : }
110 : :
111 : 0 : static struct genl_family *genl_family_find_byname(char *name)
112 : : {
113 : : struct genl_family *f;
114 : : int i;
115 : :
116 [ + + ]: 34 : for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
117 [ + + ]: 44 : list_for_each_entry(f, genl_family_chain(i), family_list)
118 [ + ]: 10 : if (strcmp(f->name, name) == 0)
119 : : return f;
120 : :
121 : : return NULL;
122 : : }
123 : :
124 : : static const struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
125 : : {
126 : : int i;
127 : :
128 [ + - ]: 1 : for (i = 0; i < family->n_ops; i++)
129 [ - + ]: 1 : if (family->ops[i].cmd == cmd)
130 : : return &family->ops[i];
131 : :
132 : : return NULL;
133 : : }
134 : :
135 : : /* Of course we are going to have problems once we hit
136 : : * 2^16 alive types, but that can only happen by year 2K
137 : : */
138 : 0 : static u16 genl_generate_id(void)
139 : : {
140 : : static u16 id_gen_idx = GENL_MIN_ID;
141 : : int i;
142 : :
143 [ # # ]: 0 : for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
144 [ # # ]: 0 : if (id_gen_idx != GENL_ID_VFS_DQUOT &&
145 [ # # ]: 0 : id_gen_idx != GENL_ID_PMCRAID &&
146 : 0 : !genl_family_find_byid(id_gen_idx))
147 : : return id_gen_idx;
148 [ # # ]: 0 : if (++id_gen_idx > GENL_MAX_ID)
149 : 0 : id_gen_idx = GENL_MIN_ID;
150 : : }
151 : :
152 : : return 0;
153 : : }
154 : :
155 : 0 : static int genl_allocate_reserve_groups(int n_groups, int *first_id)
156 : : {
157 : : unsigned long *new_groups;
158 : : int start = 0;
159 : : int i;
160 : : int id;
161 : : bool fits;
162 : :
163 : : do {
164 [ # # ]: 0 : if (start == 0)
165 : 0 : id = find_first_zero_bit(mc_groups,
166 : : mc_groups_longs *
167 : : BITS_PER_LONG);
168 : : else
169 : 0 : id = find_next_zero_bit(mc_groups,
170 : : mc_groups_longs * BITS_PER_LONG,
171 : : start);
172 : :
173 : : fits = true;
174 [ # # ]: 0 : for (i = id;
175 : 0 : i < min_t(int, id + n_groups,
176 : : mc_groups_longs * BITS_PER_LONG);
177 : 0 : i++) {
178 [ # # ]: 0 : if (test_bit(i, mc_groups)) {
179 : : start = i;
180 : : fits = false;
181 : : break;
182 : : }
183 : : }
184 : :
185 [ # # ]: 0 : if (id >= mc_groups_longs * BITS_PER_LONG) {
186 : 0 : unsigned long new_longs = mc_groups_longs +
187 : 0 : BITS_TO_LONGS(n_groups);
188 : 0 : size_t nlen = new_longs * sizeof(unsigned long);
189 : :
190 [ # # ]: 0 : if (mc_groups == &mc_group_start) {
191 : : new_groups = kzalloc(nlen, GFP_KERNEL);
192 [ # # ]: 0 : if (!new_groups)
193 : : return -ENOMEM;
194 : 0 : mc_groups = new_groups;
195 : 0 : *mc_groups = mc_group_start;
196 : : } else {
197 : 0 : new_groups = krealloc(mc_groups, nlen,
198 : : GFP_KERNEL);
199 [ # # ]: 0 : if (!new_groups)
200 : : return -ENOMEM;
201 : 0 : mc_groups = new_groups;
202 [ # # ]: 0 : for (i = 0; i < BITS_TO_LONGS(n_groups); i++)
203 : 0 : mc_groups[mc_groups_longs + i] = 0;
204 : : }
205 : 0 : mc_groups_longs = new_longs;
206 : : }
207 [ # # ]: 0 : } while (!fits);
208 : :
209 [ # # ]: 0 : for (i = id; i < id + n_groups; i++)
210 : 0 : set_bit(i, mc_groups);
211 : 0 : *first_id = id;
212 : 0 : return 0;
213 : : }
214 : :
215 : : static struct genl_family genl_ctrl;
216 : :
217 : 0 : static int genl_validate_assign_mc_groups(struct genl_family *family)
218 : : {
219 : : int first_id;
220 : 0 : int n_groups = family->n_mcgrps;
221 : : int err = 0, i;
222 : : bool groups_allocated = false;
223 : :
224 [ # # ]: 0 : if (!n_groups)
225 : : return 0;
226 : :
227 [ # # ]: 0 : for (i = 0; i < n_groups; i++) {
228 : 0 : const struct genl_multicast_group *grp = &family->mcgrps[i];
229 : :
230 [ # # ][ # # ]: 0 : if (WARN_ON(grp->name[0] == '\0'))
231 : : return -EINVAL;
232 [ # # ][ # # ]: 0 : if (WARN_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL))
233 : : return -EINVAL;
234 : : }
235 : :
236 : : /* special-case our own group and hacks */
237 [ # # ]: 0 : if (family == &genl_ctrl) {
238 : 0 : first_id = GENL_ID_CTRL;
239 [ # # ]: 0 : BUG_ON(n_groups != 1);
240 [ # # ]: 0 : } else if (strcmp(family->name, "NET_DM") == 0) {
241 : 0 : first_id = 1;
242 [ # # ]: 0 : BUG_ON(n_groups != 1);
243 [ # # ]: 0 : } else if (family->id == GENL_ID_VFS_DQUOT) {
244 : 0 : first_id = GENL_ID_VFS_DQUOT;
245 [ # # ]: 0 : BUG_ON(n_groups != 1);
246 [ # # ]: 0 : } else if (family->id == GENL_ID_PMCRAID) {
247 : 0 : first_id = GENL_ID_PMCRAID;
248 [ # # ]: 0 : BUG_ON(n_groups != 1);
249 : : } else {
250 : : groups_allocated = true;
251 : 0 : err = genl_allocate_reserve_groups(n_groups, &first_id);
252 [ # # ]: 0 : if (err)
253 : : return err;
254 : : }
255 : :
256 : 0 : family->mcgrp_offset = first_id;
257 : :
258 : : /* if still initializing, can't and don't need to to realloc bitmaps */
259 [ # # ]: 0 : if (!init_net.genl_sock)
260 : : return 0;
261 : :
262 [ # # ]: 0 : if (family->netnsok) {
263 : : struct net *net;
264 : :
265 : 0 : netlink_table_grab();
266 : : rcu_read_lock();
267 [ # # ]: 0 : for_each_net_rcu(net) {
268 : 0 : err = __netlink_change_ngroups(net->genl_sock,
269 : 0 : mc_groups_longs * BITS_PER_LONG);
270 [ # # ]: 0 : if (err) {
271 : : /*
272 : : * No need to roll back, can only fail if
273 : : * memory allocation fails and then the
274 : : * number of _possible_ groups has been
275 : : * increased on some sockets which is ok.
276 : : */
277 : : break;
278 : : }
279 : : }
280 : : rcu_read_unlock();
281 : 0 : netlink_table_ungrab();
282 : : } else {
283 : 0 : err = netlink_change_ngroups(init_net.genl_sock,
284 : 0 : mc_groups_longs * BITS_PER_LONG);
285 : : }
286 : :
287 [ # # ]: 0 : if (groups_allocated && err) {
288 [ # # ]: 0 : for (i = 0; i < family->n_mcgrps; i++)
289 : 0 : clear_bit(family->mcgrp_offset + i, mc_groups);
290 : : }
291 : :
292 : 0 : return err;
293 : : }
294 : :
295 : 0 : static void genl_unregister_mc_groups(struct genl_family *family)
296 : : {
297 : : struct net *net;
298 : : int i;
299 : :
300 : 0 : netlink_table_grab();
301 : : rcu_read_lock();
302 [ # # ]: 0 : for_each_net_rcu(net) {
303 [ # # ]: 0 : for (i = 0; i < family->n_mcgrps; i++)
304 : 0 : __netlink_clear_multicast_users(
305 : 0 : net->genl_sock, family->mcgrp_offset + i);
306 : : }
307 : : rcu_read_unlock();
308 : 0 : netlink_table_ungrab();
309 : :
310 [ # # ]: 0 : for (i = 0; i < family->n_mcgrps; i++) {
311 : 0 : int grp_id = family->mcgrp_offset + i;
312 : :
313 [ # # ]: 0 : if (grp_id != 1)
314 : 0 : clear_bit(grp_id, mc_groups);
315 : 0 : genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, family,
316 : 0 : &family->mcgrps[i], grp_id);
317 : : }
318 : 0 : }
319 : :
320 : 0 : static int genl_validate_ops(struct genl_family *family)
321 : : {
322 : 0 : const struct genl_ops *ops = family->ops;
323 : 0 : unsigned int n_ops = family->n_ops;
324 : : int i, j;
325 : :
326 [ # # ][ # # ]: 0 : if (WARN_ON(n_ops && !ops))
327 : : return -EINVAL;
328 : :
329 [ # # ]: 0 : if (!n_ops)
330 : : return 0;
331 : :
332 [ # # ]: 0 : for (i = 0; i < n_ops; i++) {
333 [ # # ][ # # ]: 0 : if (ops[i].dumpit == NULL && ops[i].doit == NULL)
334 : : return -EINVAL;
335 [ # # ]: 0 : for (j = i + 1; j < n_ops; j++)
336 [ # # ]: 0 : if (ops[i].cmd == ops[j].cmd)
337 : : return -EINVAL;
338 : : }
339 : :
340 : : /* family is not registered yet, so no locking needed */
341 : 0 : family->ops = ops;
342 : 0 : family->n_ops = n_ops;
343 : :
344 : : return 0;
345 : : }
346 : :
347 : : /**
348 : : * __genl_register_family - register a generic netlink family
349 : : * @family: generic netlink family
350 : : *
351 : : * Registers the specified family after validating it first. Only one
352 : : * family may be registered with the same family name or identifier.
353 : : * The family id may equal GENL_ID_GENERATE causing an unique id to
354 : : * be automatically generated and assigned.
355 : : *
356 : : * The family's ops array must already be assigned, you can use the
357 : : * genl_register_family_with_ops() helper function.
358 : : *
359 : : * Return 0 on success or a negative error code.
360 : : */
361 : 0 : int __genl_register_family(struct genl_family *family)
362 : : {
363 : : int err = -EINVAL, i;
364 : :
365 [ # # ]: 0 : if (family->id && family->id < GENL_MIN_ID)
366 : : goto errout;
367 : :
368 [ # # ]: 0 : if (family->id > GENL_MAX_ID)
369 : : goto errout;
370 : :
371 : 0 : err = genl_validate_ops(family);
372 [ # # ]: 0 : if (err)
373 : : return err;
374 : :
375 : : genl_lock_all();
376 : :
377 [ # # ]: 0 : if (genl_family_find_byname(family->name)) {
378 : : err = -EEXIST;
379 : : goto errout_locked;
380 : : }
381 : :
382 [ # # ]: 0 : if (family->id == GENL_ID_GENERATE) {
383 : 0 : u16 newid = genl_generate_id();
384 : :
385 [ # # ]: 0 : if (!newid) {
386 : : err = -ENOMEM;
387 : : goto errout_locked;
388 : : }
389 : :
390 : 0 : family->id = newid;
391 [ # # ]: 0 : } else if (genl_family_find_byid(family->id)) {
392 : : err = -EEXIST;
393 : : goto errout_locked;
394 : : }
395 : :
396 [ # # ][ # # ]: 0 : if (family->maxattr && !family->parallel_ops) {
397 : 0 : family->attrbuf = kmalloc((family->maxattr+1) *
398 : : sizeof(struct nlattr *), GFP_KERNEL);
399 [ # # ]: 0 : if (family->attrbuf == NULL) {
400 : : err = -ENOMEM;
401 : : goto errout_locked;
402 : : }
403 : : } else
404 : 0 : family->attrbuf = NULL;
405 : :
406 : 0 : err = genl_validate_assign_mc_groups(family);
407 [ # # ]: 0 : if (err)
408 : : goto errout_locked;
409 : :
410 : 0 : list_add_tail(&family->family_list, genl_family_chain(family->id));
411 : : genl_unlock_all();
412 : :
413 : : /* send all events */
414 : 0 : genl_ctrl_event(CTRL_CMD_NEWFAMILY, family, NULL, 0);
415 [ # # ]: 0 : for (i = 0; i < family->n_mcgrps; i++)
416 : 0 : genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, family,
417 : 0 : &family->mcgrps[i], family->mcgrp_offset + i);
418 : :
419 : : return 0;
420 : :
421 : : errout_locked:
422 : : genl_unlock_all();
423 : : errout:
424 : 0 : return err;
425 : : }
426 : : EXPORT_SYMBOL(__genl_register_family);
427 : :
428 : : /**
429 : : * genl_unregister_family - unregister generic netlink family
430 : : * @family: generic netlink family
431 : : *
432 : : * Unregisters the specified family.
433 : : *
434 : : * Returns 0 on success or a negative error code.
435 : : */
436 : 0 : int genl_unregister_family(struct genl_family *family)
437 : : {
438 : : struct genl_family *rc;
439 : :
440 : : genl_lock_all();
441 : :
442 : 0 : genl_unregister_mc_groups(family);
443 : :
444 [ # # ]: 0 : list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
445 [ # # ][ # # ]: 0 : if (family->id != rc->id || strcmp(rc->name, family->name))
446 : 0 : continue;
447 : :
448 : : list_del(&rc->family_list);
449 : 0 : family->n_ops = 0;
450 : : genl_unlock_all();
451 : :
452 : 0 : kfree(family->attrbuf);
453 : 0 : genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
454 : 0 : return 0;
455 : : }
456 : :
457 : : genl_unlock_all();
458 : :
459 : 0 : return -ENOENT;
460 : : }
461 : : EXPORT_SYMBOL(genl_unregister_family);
462 : :
463 : : /**
464 : : * genlmsg_put - Add generic netlink header to netlink message
465 : : * @skb: socket buffer holding the message
466 : : * @portid: netlink portid the message is addressed to
467 : : * @seq: sequence number (usually the one of the sender)
468 : : * @family: generic netlink family
469 : : * @flags: netlink message flags
470 : : * @cmd: generic netlink command
471 : : *
472 : : * Returns pointer to user specific header
473 : : */
474 : 0 : void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
475 : : struct genl_family *family, int flags, u8 cmd)
476 : : {
477 : : struct nlmsghdr *nlh;
478 : : struct genlmsghdr *hdr;
479 : :
480 : 0 : nlh = nlmsg_put(skb, portid, seq, family->id, GENL_HDRLEN +
481 : 0 : family->hdrsize, flags);
482 [ # # ]: 0 : if (nlh == NULL)
483 : : return NULL;
484 : :
485 : : hdr = nlmsg_data(nlh);
486 : 0 : hdr->cmd = cmd;
487 : 0 : hdr->version = family->version;
488 : 0 : hdr->reserved = 0;
489 : :
490 : 0 : return (char *) hdr + GENL_HDRLEN;
491 : : }
492 : : EXPORT_SYMBOL(genlmsg_put);
493 : :
494 : 0 : static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
495 : : {
496 : : /* our ops are always const - netlink API doesn't propagate that */
497 : 0 : const struct genl_ops *ops = cb->data;
498 : : int rc;
499 : :
500 : : genl_lock();
501 : 0 : rc = ops->dumpit(skb, cb);
502 : : genl_unlock();
503 : 0 : return rc;
504 : : }
505 : :
506 : 0 : static int genl_lock_done(struct netlink_callback *cb)
507 : : {
508 : : /* our ops are always const - netlink API doesn't propagate that */
509 : 0 : const struct genl_ops *ops = cb->data;
510 : : int rc = 0;
511 : :
512 [ # # ]: 0 : if (ops->done) {
513 : : genl_lock();
514 : 0 : rc = ops->done(cb);
515 : : genl_unlock();
516 : : }
517 : 0 : return rc;
518 : : }
519 : :
520 : 1 : static int genl_family_rcv_msg(struct genl_family *family,
521 : : struct sk_buff *skb,
522 : : struct nlmsghdr *nlh)
523 : : {
524 : : const struct genl_ops *ops;
525 : : struct net *net = sock_net(skb->sk);
526 : : struct genl_info info;
527 : : struct genlmsghdr *hdr = nlmsg_data(nlh);
528 : : struct nlattr **attrbuf;
529 : : int hdrlen, err;
530 : :
531 : : /* this family doesn't exist in this netns */
532 : : if (!family->netnsok && !net_eq(net, &init_net))
533 : : return -ENOENT;
534 : :
535 : 1 : hdrlen = GENL_HDRLEN + family->hdrsize;
536 [ + - ]: 1 : if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
537 : : return -EINVAL;
538 : :
539 : 1 : ops = genl_get_cmd(hdr->cmd, family);
540 [ + - ]: 1 : if (ops == NULL)
541 : : return -EOPNOTSUPP;
542 : :
543 [ - + # # ]: 1 : if ((ops->flags & GENL_ADMIN_PERM) &&
544 : 0 : !capable(CAP_NET_ADMIN))
545 : : return -EPERM;
546 : :
547 [ - + ]: 1 : if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) {
548 : : int rc;
549 : :
550 [ # # ]: 0 : if (ops->dumpit == NULL)
551 : : return -EOPNOTSUPP;
552 : :
553 [ # # ]: 0 : if (!family->parallel_ops) {
554 : 0 : struct netlink_dump_control c = {
555 : 0 : .module = family->module,
556 : : /* we have const, but the netlink API doesn't */
557 : : .data = (void *)ops,
558 : : .dump = genl_lock_dumpit,
559 : : .done = genl_lock_done,
560 : : };
561 : :
562 : : genl_unlock();
563 : 0 : rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
564 : : genl_lock();
565 : :
566 : : } else {
567 : 0 : struct netlink_dump_control c = {
568 : 0 : .module = family->module,
569 : 0 : .dump = ops->dumpit,
570 : 0 : .done = ops->done,
571 : : };
572 : :
573 : 0 : rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
574 : : }
575 : :
576 : 0 : return rc;
577 : : }
578 : :
579 [ + ]: 1 : if (ops->doit == NULL)
580 : : return -EOPNOTSUPP;
581 : :
582 [ + - ][ - + ]: 2 : if (family->maxattr && family->parallel_ops) {
583 : 0 : attrbuf = kmalloc((family->maxattr+1) *
584 : : sizeof(struct nlattr *), GFP_KERNEL);
585 [ # # ]: 0 : if (attrbuf == NULL)
586 : : return -ENOMEM;
587 : : } else
588 : 1 : attrbuf = family->attrbuf;
589 : :
590 [ + - ]: 1 : if (attrbuf) {
591 : 1 : err = nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
592 : : ops->policy);
593 [ + - ]: 1 : if (err < 0)
594 : : goto out;
595 : : }
596 : :
597 : 1 : info.snd_seq = nlh->nlmsg_seq;
598 : 1 : info.snd_portid = NETLINK_CB(skb).portid;
599 : 1 : info.nlhdr = nlh;
600 : 1 : info.genlhdr = nlmsg_data(nlh);
601 : 1 : info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
602 : 1 : info.attrs = attrbuf;
603 : : genl_info_net_set(&info, net);
604 : 1 : memset(&info.user_ptr, 0, sizeof(info.user_ptr));
605 : :
606 [ - + ]: 1 : if (family->pre_doit) {
607 : 0 : err = family->pre_doit(ops, skb, &info);
608 [ # # ]: 0 : if (err)
609 : : goto out;
610 : : }
611 : :
612 : 1 : err = ops->doit(skb, &info);
613 : :
614 [ - + ]: 1 : if (family->post_doit)
615 : 0 : family->post_doit(ops, skb, &info);
616 : :
617 : : out:
618 [ - + ]: 1 : if (family->parallel_ops)
619 : 0 : kfree(attrbuf);
620 : :
621 : 1 : return err;
622 : : }
623 : :
624 : 0 : static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
625 : : {
626 : : struct genl_family *family;
627 : : int err;
628 : :
629 : 1 : family = genl_family_find_byid(nlh->nlmsg_type);
630 [ + - ]: 1 : if (family == NULL)
631 : : return -ENOENT;
632 : :
633 [ + - ]: 1 : if (!family->parallel_ops)
634 : : genl_lock();
635 : :
636 : 1 : err = genl_family_rcv_msg(family, skb, nlh);
637 : :
638 [ + - ]: 1 : if (!family->parallel_ops)
639 : : genl_unlock();
640 : :
641 : 1 : return err;
642 : : }
643 : :
644 : 0 : static void genl_rcv(struct sk_buff *skb)
645 : : {
646 : 1 : down_read(&cb_lock);
647 : 1 : netlink_rcv_skb(skb, &genl_rcv_msg);
648 : 1 : up_read(&cb_lock);
649 : 1 : }
650 : :
651 : : /**************************************************************************
652 : : * Controller
653 : : **************************************************************************/
654 : :
655 : : static struct genl_family genl_ctrl = {
656 : : .id = GENL_ID_CTRL,
657 : : .name = "nlctrl",
658 : : .version = 0x2,
659 : : .maxattr = CTRL_ATTR_MAX,
660 : : .netnsok = true,
661 : : };
662 : :
663 : 0 : static int ctrl_fill_info(struct genl_family *family, u32 portid, u32 seq,
664 : : u32 flags, struct sk_buff *skb, u8 cmd)
665 : : {
666 : : void *hdr;
667 : :
668 : 0 : hdr = genlmsg_put(skb, portid, seq, &genl_ctrl, flags, cmd);
669 [ # # ]: 0 : if (hdr == NULL)
670 : : return -1;
671 : :
672 [ # # # # ]: 0 : if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, family->name) ||
673 [ # # ]: 0 : nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, family->id) ||
674 [ # # ]: 0 : nla_put_u32(skb, CTRL_ATTR_VERSION, family->version) ||
675 [ # # ]: 0 : nla_put_u32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize) ||
676 : 0 : nla_put_u32(skb, CTRL_ATTR_MAXATTR, family->maxattr))
677 : : goto nla_put_failure;
678 : :
679 [ # # ]: 0 : if (family->n_ops) {
680 : : struct nlattr *nla_ops;
681 : : int i;
682 : :
683 : : nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
684 [ # # ]: 0 : if (nla_ops == NULL)
685 : : goto nla_put_failure;
686 : :
687 [ # # ]: 0 : for (i = 0; i < family->n_ops; i++) {
688 : : struct nlattr *nest;
689 : 0 : const struct genl_ops *ops = &family->ops[i];
690 : 0 : u32 op_flags = ops->flags;
691 : :
692 [ # # ]: 0 : if (ops->dumpit)
693 : 0 : op_flags |= GENL_CMD_CAP_DUMP;
694 [ # # ]: 0 : if (ops->doit)
695 : 0 : op_flags |= GENL_CMD_CAP_DO;
696 [ # # ]: 0 : if (ops->policy)
697 : 0 : op_flags |= GENL_CMD_CAP_HASPOL;
698 : :
699 : 0 : nest = nla_nest_start(skb, i + 1);
700 [ # # ]: 0 : if (nest == NULL)
701 : : goto nla_put_failure;
702 : :
703 [ # # # # ]: 0 : if (nla_put_u32(skb, CTRL_ATTR_OP_ID, ops->cmd) ||
704 : : nla_put_u32(skb, CTRL_ATTR_OP_FLAGS, op_flags))
705 : : goto nla_put_failure;
706 : :
707 : : nla_nest_end(skb, nest);
708 : : }
709 : :
710 : : nla_nest_end(skb, nla_ops);
711 : : }
712 : :
713 [ # # ]: 0 : if (family->n_mcgrps) {
714 : : struct nlattr *nla_grps;
715 : : int i;
716 : :
717 : : nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);
718 [ # # ]: 0 : if (nla_grps == NULL)
719 : : goto nla_put_failure;
720 : :
721 [ # # ]: 0 : for (i = 0; i < family->n_mcgrps; i++) {
722 : : struct nlattr *nest;
723 : : const struct genl_multicast_group *grp;
724 : :
725 : 0 : grp = &family->mcgrps[i];
726 : :
727 : 0 : nest = nla_nest_start(skb, i + 1);
728 [ # # ]: 0 : if (nest == NULL)
729 : : goto nla_put_failure;
730 : :
731 [ # # ]: 0 : if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID,
732 [ # # ]: 0 : family->mcgrp_offset + i) ||
733 : : nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
734 : 0 : grp->name))
735 : : goto nla_put_failure;
736 : :
737 : : nla_nest_end(skb, nest);
738 : : }
739 : : nla_nest_end(skb, nla_grps);
740 : : }
741 : :
742 : 0 : return genlmsg_end(skb, hdr);
743 : :
744 : : nla_put_failure:
745 : : genlmsg_cancel(skb, hdr);
746 : : return -EMSGSIZE;
747 : : }
748 : :
749 : 0 : static int ctrl_fill_mcgrp_info(struct genl_family *family,
750 : : const struct genl_multicast_group *grp,
751 : : int grp_id, u32 portid, u32 seq, u32 flags,
752 : : struct sk_buff *skb, u8 cmd)
753 : : {
754 : : void *hdr;
755 : : struct nlattr *nla_grps;
756 : : struct nlattr *nest;
757 : :
758 : 0 : hdr = genlmsg_put(skb, portid, seq, &genl_ctrl, flags, cmd);
759 [ # # ]: 0 : if (hdr == NULL)
760 : : return -1;
761 : :
762 [ # # # # ]: 0 : if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, family->name) ||
763 : 0 : nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, family->id))
764 : : goto nla_put_failure;
765 : :
766 : : nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);
767 [ # # ]: 0 : if (nla_grps == NULL)
768 : : goto nla_put_failure;
769 : :
770 : : nest = nla_nest_start(skb, 1);
771 [ # # ]: 0 : if (nest == NULL)
772 : : goto nla_put_failure;
773 : :
774 [ # # # # ]: 0 : if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp_id) ||
775 : : nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
776 : 0 : grp->name))
777 : : goto nla_put_failure;
778 : :
779 : : nla_nest_end(skb, nest);
780 : : nla_nest_end(skb, nla_grps);
781 : :
782 : 0 : return genlmsg_end(skb, hdr);
783 : :
784 : : nla_put_failure:
785 : : genlmsg_cancel(skb, hdr);
786 : : return -EMSGSIZE;
787 : : }
788 : :
789 : 0 : static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
790 : : {
791 : :
792 : : int i, n = 0;
793 : : struct genl_family *rt;
794 : : struct net *net = sock_net(skb->sk);
795 : 0 : int chains_to_skip = cb->args[0];
796 : 0 : int fams_to_skip = cb->args[1];
797 : :
798 [ # # ]: 0 : for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) {
799 : : n = 0;
800 [ # # ]: 0 : list_for_each_entry(rt, genl_family_chain(i), family_list) {
801 : : if (!rt->netnsok && !net_eq(net, &init_net))
802 : : continue;
803 [ # # ]: 0 : if (++n < fams_to_skip)
804 : 0 : continue;
805 [ # # ]: 0 : if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
806 : 0 : cb->nlh->nlmsg_seq, NLM_F_MULTI,
807 : : skb, CTRL_CMD_NEWFAMILY) < 0)
808 : : goto errout;
809 : : }
810 : :
811 : : fams_to_skip = 0;
812 : : }
813 : :
814 : : errout:
815 : 0 : cb->args[0] = i;
816 : 0 : cb->args[1] = n;
817 : :
818 : 0 : return skb->len;
819 : : }
820 : :
821 : 0 : static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
822 : : u32 portid, int seq, u8 cmd)
823 : : {
824 : : struct sk_buff *skb;
825 : : int err;
826 : :
827 : : skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
828 [ # # ]: 0 : if (skb == NULL)
829 : : return ERR_PTR(-ENOBUFS);
830 : :
831 : 0 : err = ctrl_fill_info(family, portid, seq, 0, skb, cmd);
832 [ # # ]: 0 : if (err < 0) {
833 : : nlmsg_free(skb);
834 : 0 : return ERR_PTR(err);
835 : : }
836 : :
837 : : return skb;
838 : : }
839 : :
840 : : static struct sk_buff *
841 : 0 : ctrl_build_mcgrp_msg(struct genl_family *family,
842 : : const struct genl_multicast_group *grp,
843 : : int grp_id, u32 portid, int seq, u8 cmd)
844 : : {
845 : : struct sk_buff *skb;
846 : : int err;
847 : :
848 : : skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
849 [ # # ]: 0 : if (skb == NULL)
850 : : return ERR_PTR(-ENOBUFS);
851 : :
852 : 0 : err = ctrl_fill_mcgrp_info(family, grp, grp_id, portid,
853 : : seq, 0, skb, cmd);
854 [ # # ]: 0 : if (err < 0) {
855 : : nlmsg_free(skb);
856 : 0 : return ERR_PTR(err);
857 : : }
858 : :
859 : : return skb;
860 : : }
861 : :
862 : : static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
863 : : [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
864 : : [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
865 : : .len = GENL_NAMSIZ - 1 },
866 : : };
867 : :
868 : 0 : static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
869 : : {
870 : : struct sk_buff *msg;
871 : : struct genl_family *res = NULL;
872 : : int err = -EINVAL;
873 : :
874 [ - + ]: 1 : if (info->attrs[CTRL_ATTR_FAMILY_ID]) {
875 : : u16 id = nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]);
876 : 0 : res = genl_family_find_byid(id);
877 : : err = -ENOENT;
878 : : }
879 : :
880 [ # # ]: 1 : if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {
881 : : char *name;
882 : :
883 : 1 : name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);
884 : 1 : res = genl_family_find_byname(name);
885 : : #ifdef CONFIG_MODULES
886 [ + - ]: 1 : if (res == NULL) {
887 : : genl_unlock();
888 : 1 : up_read(&cb_lock);
889 : 1 : request_module("net-pf-%d-proto-%d-family-%s",
890 : : PF_NETLINK, NETLINK_GENERIC, name);
891 : 1 : down_read(&cb_lock);
892 : : genl_lock();
893 : 1 : res = genl_family_find_byname(name);
894 : : }
895 : : #endif
896 : : err = -ENOENT;
897 : : }
898 : :
899 [ - + ]: 1 : if (res == NULL)
900 : : return err;
901 : :
902 : : if (!res->netnsok && !net_eq(genl_info_net(info), &init_net)) {
903 : : /* family doesn't exist here */
904 : : return -ENOENT;
905 : : }
906 : :
907 : 0 : msg = ctrl_build_family_msg(res, info->snd_portid, info->snd_seq,
908 : : CTRL_CMD_NEWFAMILY);
909 [ # # ]: 0 : if (IS_ERR(msg))
910 : 0 : return PTR_ERR(msg);
911 : :
912 : 0 : return genlmsg_reply(msg, info);
913 : : }
914 : :
915 : 0 : static int genl_ctrl_event(int event, struct genl_family *family,
916 : : const struct genl_multicast_group *grp,
917 : : int grp_id)
918 : : {
919 : : struct sk_buff *msg;
920 : :
921 : : /* genl is still initialising */
922 [ # # ]: 0 : if (!init_net.genl_sock)
923 : : return 0;
924 : :
925 [ # # # ]: 0 : switch (event) {
926 : : case CTRL_CMD_NEWFAMILY:
927 : : case CTRL_CMD_DELFAMILY:
928 [ # # ]: 0 : WARN_ON(grp);
929 : 0 : msg = ctrl_build_family_msg(family, 0, 0, event);
930 : 0 : break;
931 : : case CTRL_CMD_NEWMCAST_GRP:
932 : : case CTRL_CMD_DELMCAST_GRP:
933 [ # # ]: 0 : BUG_ON(!grp);
934 : 0 : msg = ctrl_build_mcgrp_msg(family, grp, grp_id, 0, 0, event);
935 : 0 : break;
936 : : default:
937 : : return -EINVAL;
938 : : }
939 : :
940 [ # # ]: 0 : if (IS_ERR(msg))
941 : 0 : return PTR_ERR(msg);
942 : :
943 [ # # ]: 0 : if (!family->netnsok) {
944 : 0 : genlmsg_multicast_netns(&genl_ctrl, &init_net, msg, 0,
945 : : 0, GFP_KERNEL);
946 : : } else {
947 : : rcu_read_lock();
948 : 0 : genlmsg_multicast_allns(&genl_ctrl, msg, 0,
949 : : 0, GFP_ATOMIC);
950 : : rcu_read_unlock();
951 : : }
952 : :
953 : : return 0;
954 : : }
955 : :
956 : : static struct genl_ops genl_ctrl_ops[] = {
957 : : {
958 : : .cmd = CTRL_CMD_GETFAMILY,
959 : : .doit = ctrl_getfamily,
960 : : .dumpit = ctrl_dumpfamily,
961 : : .policy = ctrl_policy,
962 : : },
963 : : };
964 : :
965 : : static struct genl_multicast_group genl_ctrl_groups[] = {
966 : : { .name = "notify", },
967 : : };
968 : :
969 : 0 : static int __net_init genl_pernet_init(struct net *net)
970 : : {
971 : 0 : struct netlink_kernel_cfg cfg = {
972 : : .input = genl_rcv,
973 : : .flags = NL_CFG_F_NONROOT_RECV,
974 : : };
975 : :
976 : : /* we'll bump the group number right afterwards */
977 : 0 : net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, &cfg);
978 : :
979 [ # # ]: 0 : if (!net->genl_sock && net_eq(net, &init_net))
980 : 0 : panic("GENL: Cannot initialize generic netlink\n");
981 : :
982 [ # # ]: 0 : if (!net->genl_sock)
983 : : return -ENOMEM;
984 : :
985 : 0 : return 0;
986 : : }
987 : :
988 : 0 : static void __net_exit genl_pernet_exit(struct net *net)
989 : : {
990 : 0 : netlink_kernel_release(net->genl_sock);
991 : 0 : net->genl_sock = NULL;
992 : 0 : }
993 : :
994 : : static struct pernet_operations genl_pernet_ops = {
995 : : .init = genl_pernet_init,
996 : : .exit = genl_pernet_exit,
997 : : };
998 : :
999 : 0 : static int __init genl_init(void)
1000 : : {
1001 : : int i, err;
1002 : :
1003 [ # # ]: 0 : for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
1004 : 0 : INIT_LIST_HEAD(&family_ht[i]);
1005 : :
1006 : : err = genl_register_family_with_ops_groups(&genl_ctrl, genl_ctrl_ops,
1007 : : genl_ctrl_groups);
1008 [ # # ]: 0 : if (err < 0)
1009 : : goto problem;
1010 : :
1011 : 0 : err = register_pernet_subsys(&genl_pernet_ops);
1012 [ # # ]: 0 : if (err)
1013 : : goto problem;
1014 : :
1015 : 0 : return 0;
1016 : :
1017 : : problem:
1018 : 0 : panic("GENL: Cannot register controller: %d\n", err);
1019 : : }
1020 : :
1021 : : subsys_initcall(genl_init);
1022 : :
1023 : 0 : static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
1024 : : gfp_t flags)
1025 : : {
1026 : : struct sk_buff *tmp;
1027 : : struct net *net, *prev = NULL;
1028 : : int err;
1029 : :
1030 [ # # ]: 0 : for_each_net_rcu(net) {
1031 [ # # ]: 0 : if (prev) {
1032 : 0 : tmp = skb_clone(skb, flags);
1033 [ # # ]: 0 : if (!tmp) {
1034 : : err = -ENOMEM;
1035 : : goto error;
1036 : : }
1037 : 0 : err = nlmsg_multicast(prev->genl_sock, tmp,
1038 : : portid, group, flags);
1039 [ # # ]: 0 : if (err)
1040 : : goto error;
1041 : : }
1042 : :
1043 : : prev = net;
1044 : : }
1045 : :
1046 : 0 : return nlmsg_multicast(prev->genl_sock, skb, portid, group, flags);
1047 : : error:
1048 : 0 : kfree_skb(skb);
1049 : 0 : return err;
1050 : : }
1051 : :
1052 : 0 : int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
1053 : : u32 portid, unsigned int group, gfp_t flags)
1054 : : {
1055 [ # # ][ # # ]: 0 : if (WARN_ON_ONCE(group >= family->n_mcgrps))
[ # # ][ # # ]
1056 : : return -EINVAL;
1057 : 0 : group = family->mcgrp_offset + group;
1058 : 0 : return genlmsg_mcast(skb, portid, group, flags);
1059 : : }
1060 : : EXPORT_SYMBOL(genlmsg_multicast_allns);
1061 : :
1062 : 0 : void genl_notify(struct genl_family *family,
1063 : : struct sk_buff *skb, struct net *net, u32 portid, u32 group,
1064 : 0 : struct nlmsghdr *nlh, gfp_t flags)
1065 : : {
1066 : 0 : struct sock *sk = net->genl_sock;
1067 : : int report = 0;
1068 : :
1069 [ # # ]: 0 : if (nlh)
1070 : : report = nlmsg_report(nlh);
1071 : :
1072 [ # # ][ # # ]: 0 : if (WARN_ON_ONCE(group >= family->n_mcgrps))
[ # # ][ # # ]
1073 : 0 : return;
1074 : 0 : group = family->mcgrp_offset + group;
1075 : 0 : nlmsg_notify(sk, skb, portid, group, report, flags);
1076 : : }
1077 : : EXPORT_SYMBOL(genl_notify);
|