diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrlabel.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 1d6ced37ad71..0d1ee82ee55b 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -458,20 +458,52 @@ static int ip6addrlbl_fill(struct sk_buff *skb, | |||
458 | return 0; | 458 | return 0; |
459 | } | 459 | } |
460 | 460 | ||
461 | static int ip6addrlbl_valid_dump_req(const struct nlmsghdr *nlh, | ||
462 | struct netlink_ext_ack *extack) | ||
463 | { | ||
464 | struct ifaddrlblmsg *ifal; | ||
465 | |||
466 | if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifal))) { | ||
467 | NL_SET_ERR_MSG_MOD(extack, "Invalid header for address label dump request"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | ifal = nlmsg_data(nlh); | ||
472 | if (ifal->__ifal_reserved || ifal->ifal_prefixlen || | ||
473 | ifal->ifal_flags || ifal->ifal_index || ifal->ifal_seq) { | ||
474 | NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address label dump request"); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | if (nlmsg_attrlen(nlh, sizeof(*ifal))) { | ||
479 | NL_SET_ERR_MSG_MOD(extack, "Invalid data after header for address label dump requewst"); | ||
480 | return -EINVAL; | ||
481 | } | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
461 | static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) | 486 | static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) |
462 | { | 487 | { |
488 | const struct nlmsghdr *nlh = cb->nlh; | ||
463 | struct net *net = sock_net(skb->sk); | 489 | struct net *net = sock_net(skb->sk); |
464 | struct ip6addrlbl_entry *p; | 490 | struct ip6addrlbl_entry *p; |
465 | int idx = 0, s_idx = cb->args[0]; | 491 | int idx = 0, s_idx = cb->args[0]; |
466 | int err; | 492 | int err; |
467 | 493 | ||
494 | if (cb->strict_check) { | ||
495 | err = ip6addrlbl_valid_dump_req(nlh, cb->extack); | ||
496 | if (err < 0) | ||
497 | return err; | ||
498 | } | ||
499 | |||
468 | rcu_read_lock(); | 500 | rcu_read_lock(); |
469 | hlist_for_each_entry_rcu(p, &net->ipv6.ip6addrlbl_table.head, list) { | 501 | hlist_for_each_entry_rcu(p, &net->ipv6.ip6addrlbl_table.head, list) { |
470 | if (idx >= s_idx) { | 502 | if (idx >= s_idx) { |
471 | err = ip6addrlbl_fill(skb, p, | 503 | err = ip6addrlbl_fill(skb, p, |
472 | net->ipv6.ip6addrlbl_table.seq, | 504 | net->ipv6.ip6addrlbl_table.seq, |
473 | NETLINK_CB(cb->skb).portid, | 505 | NETLINK_CB(cb->skb).portid, |
474 | cb->nlh->nlmsg_seq, | 506 | nlh->nlmsg_seq, |
475 | RTM_NEWADDRLABEL, | 507 | RTM_NEWADDRLABEL, |
476 | NLM_F_MULTI); | 508 | NLM_F_MULTI); |
477 | if (err < 0) | 509 | if (err < 0) |