From: Ido Schimmel <idosch@nvidia.com>
To: liamsmith827 <liamsmith827@grapheneos.org>
Cc: netdev@vger.kernel.org, dsahern@kernel.org, davem@davemloft.net,
edumazet@kernel.org, kuba@kernel.org, pabeni@redhat.com,
horms@kernel.org, shuah@kernel.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
liamsmith827 <liamsmith827@proton.me>
Subject: Re: [RFC net-next 1/2] ipv4: Honor prohibit when oif specified
Date: Sun, 25 Oct 2026 19:13:48 +0200 [thread overview]
Message-ID: <20261025171348.GA233026@shredder> (raw)
In-Reply-To: <20261019032406.88874-2-liamsmith827@grapheneos.org>
On Mon, Oct 19, 2026 at 03:24:05AM +0000, liamsmith827 wrote:
> From: liamsmith827 <liamsmith827@proton.me>
>
> When flowi4_oif is set (SO_BINDTODEVICE, IP_PKTINFO, IP_UNICAST_IF,
> etc), prohibit rules and routes cause fib_lookup() to return -EACCES,
> but still allow the packet (and any necessary ARP) to be transmitted.
> This is documented as the expected behavior in the tests, but is
> confusing for route and rule maintainers. Specifically, Android uses
> prohibit rules as the basis for its VPN "kill switch", with the
> expectation that any packet encountering such a rule will not be allowed
> out. Due to this interface binding exemption, apps can trivially bypass
> the kill switch. This is most serious on cellular networks, where a
> connection to an arbitrary IPv4 address can be established without
> requiring ARP resolution.
>
> Preserve -EACCES from fib_lookup() instead of constructing an on-link
> route when an output interface is specified. This honors prohibit rules
> and routes while retaining the existing fallback for other lookup
> errors.
My understanding is that the original intent was to only ignore the "no
route" error (-ENETUNREACH). The comment in the code says so: "we are
allowed to send to iface even if it has NO routes".
Ignoring unreachable, blackhole and prohibit routes / rules is merely a
side-effect of not checking for a specific error code. I find it very
hard to believe that anyone is relying on this behavior:
1. It's confusing. The ip-route man page says that unreachable,
blackhole and prohibit routes all discard packets.
2. These rules and routes are honored in the VRF case.
3. IPv6 behaves differently. These rules are honored, but IPv6 will
backtrack to a shorter prefix route if it hits an unreachable, blackhole
or prohibit route with a strict oif. Will look into it, looks like a
bug.
Given the above, I think that the patch is too specific to your use
case. It doesn't make sense to only honor prohibit rules / routes. How
about checking for 'err == -ENETUNREACH' [1]?
It doesn't allow us to distinguish between "no route" and "unreachable
rule", but we can probably ignore it given that it has always been the
case and nobody complained. It needs to be explained in the commit
message.
Note that multicast needs to be exempted because of VRF. The lookup
fails on the unreachable default route in the VRF table (-EHOSTUNREACH)
and we construct the route anyway. It is also consistent with IPv6 where
these routes / rules do not affect multicast traffic since the
per-interface ff00::/8 routes in the local table are matched first.
This change will allow you to uncomment all the test cases in
ipv4_ping_novrf(), so that it matches ipv6_ping_novrf().
>
> Signed-off-by: liamsmith827 <liamsmith827@proton.me>
> ---
> net/ipv4/route.c | 11 ++++++-----
> 1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 595a3b7f1783..616c20299334 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -2853,7 +2853,7 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
> if (err) {
> res->fi = NULL;
> res->table = NULL;
> - if (fl4->flowi4_oif &&
> + if (fl4->flowi4_oif && err != -EACCES &&
> (ipv4_is_multicast(fl4->daddr) || !fl4->flowi4_l3mdev)) {
> /* Apparently, routing tables are wrong. Assume,
> * that the destination is on link.
> @@ -2864,13 +2864,14 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
> * addresses. When oif is specified, routing
> * tables are looked up with only one purpose:
> * to catch if destination is gatewayed, rather than
> - * direct. Moreover, if MSG_DONTROUTE is set,
> - * we send packet, ignoring both routing tables
> - * and ifaddr state. --ANK
> - *
> + * direct.
Why modify this hunk? Looks like an unrelated change.
> *
> * We could make it even if oif is unknown,
> * likely IPv6, but we do not.
> + *
> + * Additionally, when oif is specified, routing lookup
> + * allows us to check if destination is prohibited
> + * (-EACCES). LS.
Please remove the signature. It's unnecessary in the git era.
> */
[1]
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 595a3b7f1783..b10ea8bec090 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2854,7 +2854,8 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
res->fi = NULL;
res->table = NULL;
if (fl4->flowi4_oif &&
- (ipv4_is_multicast(fl4->daddr) || !fl4->flowi4_l3mdev)) {
+ (ipv4_is_multicast(fl4->daddr) ||
+ (!fl4->flowi4_l3mdev && err == -ENETUNREACH))) {
/* Apparently, routing tables are wrong. Assume,
* that the destination is on link.
*
next prev parent reply other threads:[~2026-10-25 17:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 3:24 [RFC net-next 0/2] " liamsmith827
2026-10-19 3:24 ` [RFC net-next 1/2] " liamsmith827
2026-10-25 17:13 ` Ido Schimmel [this message]
2026-10-19 3:24 ` [RFC net-next 2/2] selftests: net: Test " liamsmith827
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261025171348.GA233026@shredder \
--to=idosch@nvidia.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=liamsmith827@grapheneos.org \
--cc=liamsmith827@proton.me \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®