Skip to content

Commit 35e8c7b

Browse files
roopa-prabhudavem330
authored andcommitted
net: fib_rules: bring back rule_exists to match rule during add
After commit f9d4b0c ("fib_rules: move common handling of newrule delrule msgs into fib_nl2rule"), rule_exists got replaced by rule_find for existing rule lookup in both the add and del paths. While this is good for the delete path, it solves a few problems but opens up a few invalid key matches in the add path. $ip -4 rule add table main tos 10 fwmark 1 $ip -4 rule add table main tos 10 RTNETLINK answers: File exists The problem here is rule_find does not check if the key masks in the new and old rule are the same and hence ends up matching a more secific rule. Rule key masks cannot be easily compared today without an elaborate if-else block. Its best to introduce key masks for easier and accurate rule comparison in the future. Until then, due to fear of regressions this patch re-introduces older loose rule_exists during add. Also fixes both rule_exists and rule_find to cover missing attributes. Fixes: f9d4b0c ("fib_rules: move common handling of newrule delrule msgs into fib_nl2rule") Signed-off-by: Roopa Prabhu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3ffe64f commit 35e8c7b

File tree

1 file changed

+71
-1
lines changed

1 file changed

+71
-1
lines changed

net/core/fib_rules.c

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,9 @@ static struct fib_rule *rule_find(struct fib_rules_ops *ops,
444444
if (rule->ip_proto && r->ip_proto != rule->ip_proto)
445445
continue;
446446

447+
if (rule->proto && r->proto != rule->proto)
448+
continue;
449+
447450
if (fib_rule_port_range_set(&rule->sport_range) &&
448451
!fib_rule_port_range_compare(&r->sport_range,
449452
&rule->sport_range))
@@ -653,6 +656,73 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
653656
return err;
654657
}
655658

659+
static int rule_exists(struct fib_rules_ops *ops, struct fib_rule_hdr *frh,
660+
struct nlattr **tb, struct fib_rule *rule)
661+
{
662+
struct fib_rule *r;
663+
664+
list_for_each_entry(r, &ops->rules_list, list) {
665+
if (r->action != rule->action)
666+
continue;
667+
668+
if (r->table != rule->table)
669+
continue;
670+
671+
if (r->pref != rule->pref)
672+
continue;
673+
674+
if (memcmp(r->iifname, rule->iifname, IFNAMSIZ))
675+
continue;
676+
677+
if (memcmp(r->oifname, rule->oifname, IFNAMSIZ))
678+
continue;
679+
680+
if (r->mark != rule->mark)
681+
continue;
682+
683+
if (r->suppress_ifgroup != rule->suppress_ifgroup)
684+
continue;
685+
686+
if (r->suppress_prefixlen != rule->suppress_prefixlen)
687+
continue;
688+
689+
if (r->mark_mask != rule->mark_mask)
690+
continue;
691+
692+
if (r->tun_id != rule->tun_id)
693+
continue;
694+
695+
if (r->fr_net != rule->fr_net)
696+
continue;
697+
698+
if (r->l3mdev != rule->l3mdev)
699+
continue;
700+
701+
if (!uid_eq(r->uid_range.start, rule->uid_range.start) ||
702+
!uid_eq(r->uid_range.end, rule->uid_range.end))
703+
continue;
704+
705+
if (r->ip_proto != rule->ip_proto)
706+
continue;
707+
708+
if (r->proto != rule->proto)
709+
continue;
710+
711+
if (!fib_rule_port_range_compare(&r->sport_range,
712+
&rule->sport_range))
713+
continue;
714+
715+
if (!fib_rule_port_range_compare(&r->dport_range,
716+
&rule->dport_range))
717+
continue;
718+
719+
if (!ops->compare(r, frh, tb))
720+
continue;
721+
return 1;
722+
}
723+
return 0;
724+
}
725+
656726
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
657727
struct netlink_ext_ack *extack)
658728
{
@@ -687,7 +757,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
687757
goto errout;
688758

689759
if ((nlh->nlmsg_flags & NLM_F_EXCL) &&
690-
rule_find(ops, frh, tb, rule, user_priority)) {
760+
rule_exists(ops, frh, tb, rule)) {
691761
err = -EEXIST;
692762
goto errout_free;
693763
}

0 commit comments

Comments
 (0)