mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 01:08:13 -04:00
ipv4: fib: Don't ignore error route in local/main tables.
When CONFIG_IP_MULTIPLE_TABLES is enabled but no rule is added,
fib_lookup() performs route lookup directly on two tables.
Since the first lookup does not properly bail out, the result
of an error route in the merged local/main table could be
overwritten by another route in the default table:
# unshare -n
# ip link set lo up
# ip route add 192.168.0.0/24 dev lo table 253
# ip route add unreachable 192.168.0.0/24
# ip route get 192.168.0.1
192.168.0.1 dev lo table default uid 0
cache <local>
Once a random rule is added, the error route is respected:
# ip rule add table 0
# ip rule del table 0
# ip route get 192.168.0.1
RTNETLINK answers: No route to host
Let's fix the inconsistent behaviour.
Fixes: f4530fa574 ("ipv4: Avoid overhead when no custom FIB rules are installed.")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260619212753.3367244-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
40529e5862
commit
b72f0db642
@@ -374,7 +374,7 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp,
|
||||
struct fib_result *res, unsigned int flags)
|
||||
{
|
||||
struct fib_table *tb;
|
||||
int err = -ENETUNREACH;
|
||||
int err = -EAGAIN;
|
||||
|
||||
flags |= FIB_LOOKUP_NOREF;
|
||||
if (net->ipv4.fib_has_custom_rules)
|
||||
@@ -388,17 +388,16 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp,
|
||||
if (tb)
|
||||
err = fib_table_lookup(tb, flp, res, flags);
|
||||
|
||||
if (!err)
|
||||
if (err != -EAGAIN)
|
||||
goto out;
|
||||
|
||||
tb = rcu_dereference_rtnl(net->ipv4.fib_default);
|
||||
if (tb)
|
||||
err = fib_table_lookup(tb, flp, res, flags);
|
||||
|
||||
out:
|
||||
if (err == -EAGAIN)
|
||||
err = -ENETUNREACH;
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user