aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/fib_rules.h3
-rw-r--r--net/core/fib_rules.c55
-rw-r--r--net/decnet/dn_rules.c7
-rw-r--r--net/ipv4/fib_rules.c7
-rw-r--r--net/ipv4/ipmr.c3
-rw-r--r--net/ipv6/fib6_rules.c7
-rw-r--r--net/ipv6/ip6mr.c3
7 files changed, 63 insertions, 22 deletions
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index e5cfcfc7dd93..b473df5b9512 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -75,7 +75,8 @@ struct fib_rules_ops {
75 int (*configure)(struct fib_rule *, 75 int (*configure)(struct fib_rule *,
76 struct sk_buff *, 76 struct sk_buff *,
77 struct fib_rule_hdr *, 77 struct fib_rule_hdr *,
78 struct nlattr **); 78 struct nlattr **,
79 struct netlink_ext_ack *);
79 int (*delete)(struct fib_rule *); 80 int (*delete)(struct fib_rule *);
80 int (*compare)(struct fib_rule *, 81 int (*compare)(struct fib_rule *,
81 struct fib_rule_hdr *, 82 struct fib_rule_hdr *,
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)
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index c795c3f509c9..72236695db3d 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -121,13 +121,16 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
121 121
122static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 122static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
123 struct fib_rule_hdr *frh, 123 struct fib_rule_hdr *frh,
124 struct nlattr **tb) 124 struct nlattr **tb,
125 struct netlink_ext_ack *extack)
125{ 126{
126 int err = -EINVAL; 127 int err = -EINVAL;
127 struct dn_fib_rule *r = (struct dn_fib_rule *)rule; 128 struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
128 129
129 if (frh->tos) 130 if (frh->tos) {
131 NL_SET_ERR_MSG(extack, "Invalid tos value");
130 goto errout; 132 goto errout;
133 }
131 134
132 if (rule->table == RT_TABLE_UNSPEC) { 135 if (rule->table == RT_TABLE_UNSPEC) {
133 if (rule->action == FR_ACT_TO_TBL) { 136 if (rule->action == FR_ACT_TO_TBL) {
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 737d11bc8838..f8eb78d042a4 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -213,14 +213,17 @@ static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
213 213
214static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 214static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
215 struct fib_rule_hdr *frh, 215 struct fib_rule_hdr *frh,
216 struct nlattr **tb) 216 struct nlattr **tb,
217 struct netlink_ext_ack *extack)
217{ 218{
218 struct net *net = sock_net(skb->sk); 219 struct net *net = sock_net(skb->sk);
219 int err = -EINVAL; 220 int err = -EINVAL;
220 struct fib4_rule *rule4 = (struct fib4_rule *) rule; 221 struct fib4_rule *rule4 = (struct fib4_rule *) rule;
221 222
222 if (frh->tos & ~IPTOS_TOS_MASK) 223 if (frh->tos & ~IPTOS_TOS_MASK) {
224 NL_SET_ERR_MSG(extack, "Invalid tos");
223 goto errout; 225 goto errout;
226 }
224 227
225 /* split local/main if they are not already split */ 228 /* split local/main if they are not already split */
226 err = fib_unmerge(net); 229 err = fib_unmerge(net);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 2fb4de3f7f66..38e092eafc97 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -201,7 +201,8 @@ static const struct nla_policy ipmr_rule_policy[FRA_MAX + 1] = {
201}; 201};
202 202
203static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 203static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
204 struct fib_rule_hdr *frh, struct nlattr **tb) 204 struct fib_rule_hdr *frh, struct nlattr **tb,
205 struct netlink_ext_ack *extack)
205{ 206{
206 return 0; 207 return 0;
207} 208}
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index df113c7b5fc8..6547fc6491a6 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -245,15 +245,18 @@ static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = {
245 245
246static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 246static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
247 struct fib_rule_hdr *frh, 247 struct fib_rule_hdr *frh,
248 struct nlattr **tb) 248 struct nlattr **tb,
249 struct netlink_ext_ack *extack)
249{ 250{
250 int err = -EINVAL; 251 int err = -EINVAL;
251 struct net *net = sock_net(skb->sk); 252 struct net *net = sock_net(skb->sk);
252 struct fib6_rule *rule6 = (struct fib6_rule *) rule; 253 struct fib6_rule *rule6 = (struct fib6_rule *) rule;
253 254
254 if (rule->action == FR_ACT_TO_TBL && !rule->l3mdev) { 255 if (rule->action == FR_ACT_TO_TBL && !rule->l3mdev) {
255 if (rule->table == RT6_TABLE_UNSPEC) 256 if (rule->table == RT6_TABLE_UNSPEC) {
257 NL_SET_ERR_MSG(extack, "Invalid table");
256 goto errout; 258 goto errout;
259 }
257 260
258 if (fib6_new_table(net, rule->table) == NULL) { 261 if (fib6_new_table(net, rule->table) == NULL) {
259 err = -ENOBUFS; 262 err = -ENOBUFS;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 298fd8b6ed17..20a419ee8000 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -180,7 +180,8 @@ static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
180}; 180};
181 181
182static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 182static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
183 struct fib_rule_hdr *frh, struct nlattr **tb) 183 struct fib_rule_hdr *frh, struct nlattr **tb,
184 struct netlink_ext_ack *extack)
184{ 185{
185 return 0; 186 return 0;
186} 187}