aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f329b72578f5..49bc2db7982b 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -5,7 +5,6 @@
5 * Thomas Graf <tgraf@suug.ch> 5 * Thomas Graf <tgraf@suug.ch>
6 */ 6 */
7 7
8#include <linux/config.h>
9#include <linux/module.h> 8#include <linux/module.h>
10#include <linux/kernel.h> 9#include <linux/kernel.h>
11#include <linux/errno.h> 10#include <linux/errno.h>
@@ -320,7 +319,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
320 goto errout; 319 goto errout;
321 } 320 }
322 321
323 if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb)) { 322 if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb, CAP_NET_ADMIN)) {
324 err = -EPERM; 323 err = -EPERM;
325 goto errout; 324 goto errout;
326 } 325 }
@@ -388,7 +387,10 @@ static void genl_rcv(struct sock *sk, int len)
388static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, 387static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
389 u32 flags, struct sk_buff *skb, u8 cmd) 388 u32 flags, struct sk_buff *skb, u8 cmd)
390{ 389{
390 struct nlattr *nla_ops;
391 struct genl_ops *ops;
391 void *hdr; 392 void *hdr;
393 int idx = 1;
392 394
393 hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd, 395 hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd,
394 family->version); 396 family->version);
@@ -397,6 +399,37 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
397 399
398 NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); 400 NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name);
399 NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); 401 NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id);
402 NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version);
403 NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize);
404 NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr);
405
406 nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
407 if (nla_ops == NULL)
408 goto nla_put_failure;
409
410 list_for_each_entry(ops, &family->ops_list, ops_list) {
411 struct nlattr *nest;
412
413 nest = nla_nest_start(skb, idx++);
414 if (nest == NULL)
415 goto nla_put_failure;
416
417 NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
418 NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
419
420 if (ops->policy)
421 NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
422
423 if (ops->doit)
424 NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
425
426 if (ops->dumpit)
427 NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
428
429 nla_nest_end(skb, nest);
430 }
431
432 nla_nest_end(skb, nla_ops);
400 433
401 return genlmsg_end(skb, hdr); 434 return genlmsg_end(skb, hdr);
402 435
@@ -412,6 +445,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
412 int chains_to_skip = cb->args[0]; 445 int chains_to_skip = cb->args[0];
413 int fams_to_skip = cb->args[1]; 446 int fams_to_skip = cb->args[1];
414 447
448 if (chains_to_skip != 0)
449 genl_lock();
450
415 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { 451 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
416 if (i < chains_to_skip) 452 if (i < chains_to_skip)
417 continue; 453 continue;
@@ -429,6 +465,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
429 } 465 }
430 466
431errout: 467errout:
468 if (chains_to_skip != 0)
469 genl_unlock();
470
432 cb->args[0] = i; 471 cb->args[0] = i;
433 cb->args[1] = n; 472 cb->args[1] = n;
434 473
@@ -441,7 +480,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
441 struct sk_buff *skb; 480 struct sk_buff *skb;
442 int err; 481 int err;
443 482
444 skb = nlmsg_new(NLMSG_GOODSIZE); 483 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
445 if (skb == NULL) 484 if (skb == NULL)
446 return ERR_PTR(-ENOBUFS); 485 return ERR_PTR(-ENOBUFS);
447 486
@@ -456,7 +495,8 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
456 495
457static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = { 496static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = {
458 [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, 497 [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
459 [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING }, 498 [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
499 .len = GENL_NAMSIZ - 1 },
460}; 500};
461 501
462static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) 502static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
@@ -471,12 +511,9 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
471 } 511 }
472 512
473 if (info->attrs[CTRL_ATTR_FAMILY_NAME]) { 513 if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {
474 char name[GENL_NAMSIZ]; 514 char *name;
475
476 if (nla_strlcpy(name, info->attrs[CTRL_ATTR_FAMILY_NAME],
477 GENL_NAMSIZ) >= GENL_NAMSIZ)
478 goto errout;
479 515
516 name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);
480 res = genl_family_find_byname(name); 517 res = genl_family_find_byname(name);
481 } 518 }
482 519
@@ -511,7 +548,7 @@ static int genl_ctrl_event(int event, void *data)
511 if (IS_ERR(msg)) 548 if (IS_ERR(msg))
512 return PTR_ERR(msg); 549 return PTR_ERR(msg);
513 550
514 genlmsg_multicast(msg, 0, GENL_ID_CTRL); 551 genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
515 break; 552 break;
516 } 553 }
517 554