diff mbox series

ipv6: ensure ip6_dst_mtu_forward() returns at least IPV6_MIN_MTU

Message ID 20210607234307.3375806-1-zenczykowski@gmail.com
State New
Headers show
Series ipv6: ensure ip6_dst_mtu_forward() returns at least IPV6_MIN_MTU | expand

Commit Message

Maciej Żenczykowski June 7, 2021, 11:43 p.m. UTC
From: Maciej Żenczykowski <maze@google.com>

ip6_dst_mtu_forward() has just two call sites, one of which already
enforces the minimum mtu (which we can now remove), but it does
materially affect the other (presumably buggy) call site in:
  net/netfilter/nf_flow_table_core.c
  flow_offload_fill_route()

Cc: David S. Miller <davem@davemloft.net>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: David Ahern <dsahern@kernel.org>
Cc: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
---
 include/net/ip6_route.h | 4 ++--
 net/ipv6/ip6_output.c   | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

Comments

David Ahern June 8, 2021, 1:16 a.m. UTC | #1
On 6/7/21 5:43 PM, Maciej Żenczykowski wrote:
> From: Maciej Żenczykowski <maze@google.com>
> 
> ip6_dst_mtu_forward() has just two call sites, one of which already
> enforces the minimum mtu (which we can now remove), but it does
> materially affect the other (presumably buggy) call site in:
>   net/netfilter/nf_flow_table_core.c
>   flow_offload_fill_route()
> 
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
> Cc: David Ahern <dsahern@kernel.org>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Maciej Żenczykowski <maze@google.com>
> ---
>  include/net/ip6_route.h | 4 ++--
>  net/ipv6/ip6_output.c   | 2 --
>  2 files changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
> index 9dd3c75a4d62..e01364c0821d 100644
> --- a/include/net/ip6_route.h
> +++ b/include/net/ip6_route.h
> @@ -315,14 +315,14 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
>  	unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);

we can prevent a route getting an mtu as a metric that is < IPV6_MIN_MTU.

>  
>  	if (mtu)
> -		return mtu;
> +		return max_t(unsigned int, mtu, IPV6_MIN_MTU);
>  
>  	rcu_read_lock();
>  	idev = __in6_dev_get(dst->dev);
>  	mtu = idev ? idev->cnf.mtu6 : IPV6_MIN_MTU;

and we can prevent cnf.mtu6 getting set < IPV6_MIN_MTU:

addrconf_notify(), NETDEV_CHANGEMTU case.
ipv6_add_dev() already requires dev->mtu to be > IPV6_MIN_MTU
ndisc_router_discovery requires it.

so it seems implausible for the idev to get a value below the minimum.

the metric is less clear that it is checked, so it would be the one to
make sure is meeting expectations.
diff mbox series

Patch

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 9dd3c75a4d62..e01364c0821d 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -315,14 +315,14 @@  static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
 	unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
 
 	if (mtu)
-		return mtu;
+		return max_t(unsigned int, mtu, IPV6_MIN_MTU);
 
 	rcu_read_lock();
 	idev = __in6_dev_get(dst->dev);
 	mtu = idev ? idev->cnf.mtu6 : IPV6_MIN_MTU;
 	rcu_read_unlock();
 
-	return mtu;
+	return max_t(unsigned int, mtu, IPV6_MIN_MTU);
 }
 
 u32 ip6_mtu_from_fib6(const struct fib6_result *res,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index ff4f9ebcf7f6..8e56378713cd 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -578,8 +578,6 @@  int ip6_forward(struct sk_buff *skb)
 	}
 
 	mtu = ip6_dst_mtu_forward(dst);
-	if (mtu < IPV6_MIN_MTU)
-		mtu = IPV6_MIN_MTU;
 
 	if (ip6_pkt_too_big(skb, mtu)) {
 		/* Again, force OUTPUT device used as source address */