xfrm: fix "disable_policy" flag use when arriving from different devices
authorEyal Birger <eyal.birger@gmail.com>
Fri, 13 May 2022 20:34:02 +0000 (23:34 +0300)
committerSteffen Klassert <steffen.klassert@secunet.com>
Mon, 16 May 2022 07:31:26 +0000 (09:31 +0200)
commite6175a2ed1f18bf2f649625bf725e07adcfa6a28
tree6b1e9cc11f5c66e9f71fcb9db966352317eff62c
parent79396934e289dbc501316c1d1f975bb4c88ae460
xfrm: fix "disable_policy" flag use when arriving from different devices

In IPv4 setting the "disable_policy" flag on a device means no policy
should be enforced for traffic originating from the device. This was
implemented by seting the DST_NOPOLICY flag in the dst based on the
originating device.

However, dsts are cached in nexthops regardless of the originating
devices, in which case, the DST_NOPOLICY flag value may be incorrect.

Consider the following setup:

                     +------------------------------+
                     | ROUTER                       |
  +-------------+    | +-----------------+          |
  | ipsec src   |----|-|ipsec0           |          |
  +-------------+    | |disable_policy=0 |   +----+ |
                     | +-----------------+   |eth1|-|-----
  +-------------+    | +-----------------+   +----+ |
  | noipsec src |----|-|eth0             |          |
  +-------------+    | |disable_policy=1 |          |
                     | +-----------------+          |
                     +------------------------------+

Where ROUTER has a default route towards eth1.

dst entries for traffic arriving from eth0 would have DST_NOPOLICY
and would be cached and therefore can be reused by traffic originating
from ipsec0, skipping policy check.

Fix by setting a IPSKB_NOPOLICY flag in IPCB and observing it instead
of the DST in IN/FWD IPv4 policy checks.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
include/net/ip.h
include/net/xfrm.h
net/ipv4/route.c