aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/fib_rules.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/fib_rules.c')
-rw-r--r--net/core/fib_rules.c55
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)