On Fri, Sep 27, 2013 at 01:53:14PM -0400, Nicolas HICHER wrote: [...] > On debian wheezy, jessie, sid, if you try to delete an inexistant > table with ip rule, the local table will be deleted. The table number must > be greater than 256:
There are two different code-paths for table id < 256 and above or equal. For the "above or equal to 256" path, the table id is attached as a netlink attribute instead of using the (8bit) table field. When the netlink attribute is used, the table field is set to RT_TABLE_UNSPEC which is defined as 0. There's a helper function to handle getting the correct table id in include/net/fib_rules.h called "frh_get_table", see: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/net/fib_rules.h#n111 It looks like for the delete rule case, this is called from the "list_for_each" loop in "fib_nl_delrule" in file net/core/fib_rules.c, see: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/net/core/fib_rules.c#n464 If I understand the code correctly, the loop is trying to locate the correct rule based on the matching criterias (skipping any criteria which is not set). The precondition to check if specified table id and rule table id matches seems to be buggy though: " if (frh->table && (frh_get_table(frh, tb) != rule->table))" When iproute2 is using the netlink attribute I think frh->table will be RT_TABLE_UNSPEC, which means 0. So the matching is not performed and (given that all other criterias match) the first rule (local) will be deleted. Would be very welcome if you could rebuild the kernel with the attached patch and report back if it solves the problem for you or not. -- Andreas Henriksson
>From b65e3e7512cffb75da9ec1d78898eab80ad3d493 Mon Sep 17 00:00:00 2001 From: Andreas Henriksson <andr...@fatal.se> Date: Thu, 7 Nov 2013 13:50:43 +0100 Subject: [PATCH] Fix "ip rule delete table 256" When trying to delete a table >= 256 using iproute2 the local table will be deleted. The table id is specified as a netlink attribute when it needs more then 8 bits and iproute2 then sets the table field to RT_TABLE_UNSPEC (0). Preconditions to matching the table id in the rule delete code doesn't seem to take the "table id in netlink attribute" into condition so the frh_get_table helper function never gets to do its job when matching against current rule. Originally reported at: http://bugs.debian.org/724783 Reported-by: Nicolas HICHER <nhic...@avencall.com> Signed-off-by: Andreas Henriksson <andr...@fatal.se> --- net/core/fib_rules.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 2e65413..2efb6bf 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -460,7 +460,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh) if (frh->action && (frh->action != rule->action)) continue; - if (frh->table && (frh_get_table(frh, tb) != rule->table)) + if (frh_get_table(frh, tb) && (frh_get_table(frh, tb) != rule->table)) continue; if (tb[FRA_PRIORITY] && -- 1.8.4.2