diff options
Diffstat (limited to 'net/core/fib_rules.c')
-rw-r--r-- | net/core/fib_rules.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 67801104e9a8..ebd9351b213a 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -469,14 +469,18 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
469 | if (frh->src_len) | 469 | if (frh->src_len) |
470 | if (!tb[FRA_SRC] || | 470 | if (!tb[FRA_SRC] || |
471 | frh->src_len > (ops->addr_size * 8) || | 471 | frh->src_len > (ops->addr_size * 8) || |
472 | nla_len(tb[FRA_SRC]) != ops->addr_size) | 472 | nla_len(tb[FRA_SRC]) != ops->addr_size) { |
473 | NL_SET_ERR_MSG(extack, "Invalid source address"); | ||
473 | goto errout; | 474 | goto errout; |
475 | } | ||
474 | 476 | ||
475 | if (frh->dst_len) | 477 | if (frh->dst_len) |
476 | if (!tb[FRA_DST] || | 478 | if (!tb[FRA_DST] || |
477 | frh->dst_len > (ops->addr_size * 8) || | 479 | frh->dst_len > (ops->addr_size * 8) || |
478 | nla_len(tb[FRA_DST]) != ops->addr_size) | 480 | nla_len(tb[FRA_DST]) != ops->addr_size) { |
481 | NL_SET_ERR_MSG(extack, "Invalid dst address"); | ||
479 | goto errout; | 482 | goto errout; |
483 | } | ||
480 | 484 | ||
481 | nlrule = kzalloc(ops->rule_size, GFP_KERNEL); | 485 | nlrule = kzalloc(ops->rule_size, GFP_KERNEL); |
482 | if (!nlrule) { | 486 | if (!nlrule) { |
@@ -537,6 +541,7 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
537 | nlrule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); | 541 | nlrule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); |
538 | if (nlrule->l3mdev != 1) | 542 | if (nlrule->l3mdev != 1) |
539 | #endif | 543 | #endif |
544 | NL_SET_ERR_MSG(extack, "Invalid l3mdev"); | ||
540 | goto errout_free; | 545 | goto errout_free; |
541 | } | 546 | } |
542 | 547 | ||
@@ -554,31 +559,41 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
554 | nlrule->suppress_ifgroup = -1; | 559 | nlrule->suppress_ifgroup = -1; |
555 | 560 | ||
556 | if (tb[FRA_GOTO]) { | 561 | if (tb[FRA_GOTO]) { |
557 | if (nlrule->action != FR_ACT_GOTO) | 562 | if (nlrule->action != FR_ACT_GOTO) { |
563 | NL_SET_ERR_MSG(extack, "Unexpected goto"); | ||
558 | goto errout_free; | 564 | goto errout_free; |
565 | } | ||
559 | 566 | ||
560 | nlrule->target = nla_get_u32(tb[FRA_GOTO]); | 567 | nlrule->target = nla_get_u32(tb[FRA_GOTO]); |
561 | /* Backward jumps are prohibited to avoid endless loops */ | 568 | /* Backward jumps are prohibited to avoid endless loops */ |
562 | if (nlrule->target <= nlrule->pref) | 569 | if (nlrule->target <= nlrule->pref) { |
570 | NL_SET_ERR_MSG(extack, "Backward goto not supported"); | ||
563 | goto errout_free; | 571 | goto errout_free; |
572 | } | ||
564 | } else if (nlrule->action == FR_ACT_GOTO) { | 573 | } else if (nlrule->action == FR_ACT_GOTO) { |
574 | NL_SET_ERR_MSG(extack, "Missing goto target for action goto"); | ||
565 | goto errout_free; | 575 | goto errout_free; |
566 | } | 576 | } |
567 | 577 | ||
568 | if (nlrule->l3mdev && nlrule->table) | 578 | if (nlrule->l3mdev && nlrule->table) { |
579 | NL_SET_ERR_MSG(extack, "l3mdev and table are mutually exclusive"); | ||
569 | goto errout_free; | 580 | goto errout_free; |
581 | } | ||
570 | 582 | ||
571 | if (tb[FRA_UID_RANGE]) { | 583 | if (tb[FRA_UID_RANGE]) { |
572 | if (current_user_ns() != net->user_ns) { | 584 | if (current_user_ns() != net->user_ns) { |
573 | err = -EPERM; | 585 | err = -EPERM; |
586 | NL_SET_ERR_MSG(extack, "No permission to set uid"); | ||
574 | goto errout_free; | 587 | goto errout_free; |
575 | } | 588 | } |
576 | 589 | ||
577 | nlrule->uid_range = nla_get_kuid_range(tb); | 590 | nlrule->uid_range = nla_get_kuid_range(tb); |
578 | 591 | ||
579 | if (!uid_range_set(&nlrule->uid_range) || | 592 | if (!uid_range_set(&nlrule->uid_range) || |
580 | !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) | 593 | !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) { |
594 | NL_SET_ERR_MSG(extack, "Invalid uid range"); | ||
581 | goto errout_free; | 595 | goto errout_free; |
596 | } | ||
582 | } else { | 597 | } else { |
583 | nlrule->uid_range = fib_kuid_range_unset; | 598 | nlrule->uid_range = fib_kuid_range_unset; |
584 | } | 599 | } |
@@ -589,15 +604,19 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
589 | if (tb[FRA_SPORT_RANGE]) { | 604 | if (tb[FRA_SPORT_RANGE]) { |
590 | err = nla_get_port_range(tb[FRA_SPORT_RANGE], | 605 | err = nla_get_port_range(tb[FRA_SPORT_RANGE], |
591 | &nlrule->sport_range); | 606 | &nlrule->sport_range); |
592 | if (err) | 607 | if (err) { |
608 | NL_SET_ERR_MSG(extack, "Invalid sport range"); | ||
593 | goto errout_free; | 609 | goto errout_free; |
610 | } | ||
594 | } | 611 | } |
595 | 612 | ||
596 | if (tb[FRA_DPORT_RANGE]) { | 613 | if (tb[FRA_DPORT_RANGE]) { |
597 | err = nla_get_port_range(tb[FRA_DPORT_RANGE], | 614 | err = nla_get_port_range(tb[FRA_DPORT_RANGE], |
598 | &nlrule->dport_range); | 615 | &nlrule->dport_range); |
599 | if (err) | 616 | if (err) { |
617 | NL_SET_ERR_MSG(extack, "Invalid dport range"); | ||
600 | goto errout_free; | 618 | goto errout_free; |
619 | } | ||
601 | } | 620 | } |
602 | 621 | ||
603 | *rule = nlrule; | 622 | *rule = nlrule; |
@@ -621,18 +640,23 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
621 | int err = -EINVAL, unresolved = 0; | 640 | int err = -EINVAL, unresolved = 0; |
622 | bool user_priority = false; | 641 | bool user_priority = false; |
623 | 642 | ||
624 | if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) | 643 | if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { |
644 | NL_SET_ERR_MSG(extack, "Invalid msg length"); | ||
625 | goto errout; | 645 | goto errout; |
646 | } | ||
626 | 647 | ||
627 | ops = lookup_rules_ops(net, frh->family); | 648 | ops = lookup_rules_ops(net, frh->family); |
628 | if (!ops) { | 649 | if (!ops) { |
629 | err = -EAFNOSUPPORT; | 650 | err = -EAFNOSUPPORT; |
651 | NL_SET_ERR_MSG(extack, "Rule family not supported"); | ||
630 | goto errout; | 652 | goto errout; |
631 | } | 653 | } |
632 | 654 | ||
633 | err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); | 655 | err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); |
634 | if (err < 0) | 656 | if (err < 0) { |
657 | NL_SET_ERR_MSG(extack, "Error parsing msg"); | ||
635 | goto errout; | 658 | goto errout; |
659 | } | ||
636 | 660 | ||
637 | err = fib_nl2rule(skb, nlh, extack, ops, tb, &rule, &user_priority); | 661 | err = fib_nl2rule(skb, nlh, extack, ops, tb, &rule, &user_priority); |
638 | if (err) | 662 | if (err) |
@@ -644,7 +668,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
644 | goto errout_free; | 668 | goto errout_free; |
645 | } | 669 | } |
646 | 670 | ||
647 | err = ops->configure(rule, skb, frh, tb); | 671 | err = ops->configure(rule, skb, frh, tb, extack); |
648 | if (err < 0) | 672 | if (err < 0) |
649 | goto errout_free; | 673 | goto errout_free; |
650 | 674 | ||
@@ -723,18 +747,23 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
723 | int err = -EINVAL; | 747 | int err = -EINVAL; |
724 | bool user_priority = false; | 748 | bool user_priority = false; |
725 | 749 | ||
726 | if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) | 750 | if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { |
751 | NL_SET_ERR_MSG(extack, "Invalid msg length"); | ||
727 | goto errout; | 752 | goto errout; |
753 | } | ||
728 | 754 | ||
729 | ops = lookup_rules_ops(net, frh->family); | 755 | ops = lookup_rules_ops(net, frh->family); |
730 | if (ops == NULL) { | 756 | if (ops == NULL) { |
731 | err = -EAFNOSUPPORT; | 757 | err = -EAFNOSUPPORT; |
758 | NL_SET_ERR_MSG(extack, "Rule family not supported"); | ||
732 | goto errout; | 759 | goto errout; |
733 | } | 760 | } |
734 | 761 | ||
735 | err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); | 762 | err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); |
736 | if (err < 0) | 763 | if (err < 0) { |
764 | NL_SET_ERR_MSG(extack, "Error parsing msg"); | ||
737 | goto errout; | 765 | goto errout; |
766 | } | ||
738 | 767 | ||
739 | err = fib_nl2rule(skb, nlh, extack, ops, tb, &nlrule, &user_priority); | 768 | err = fib_nl2rule(skb, nlh, extack, ops, tb, &nlrule, &user_priority); |
740 | if (err) | 769 | if (err) |