netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
@ 2019-09-24  7:36 Jason A. Donenfeld
  2019-09-24  9:35 ` Jason A. Donenfeld
  2019-09-24 12:52 ` David Miller
  0 siblings, 2 replies; 10+ messages in thread
From: Jason A. Donenfeld @ 2019-09-24  7:36 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: Jason A. Donenfeld, stable

Commit 7d9e5f422150 removed references from certain dsts, but accounting
for this never translated down into the fib6 suppression code. This bug
was triggered by WireGuard users who use wg-quick(8), which uses the
"suppress-prefix" directive to ip-rule(8) for routing all of their
internet traffic without routing loops. The test case in the link of
this commit reliably triggers various crashes due to the use-after-free
caused by the reference underflow.

Cc: stable@vger.kernel.org
Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
Test-case: https://git.zx2c4.com/WireGuard/commit/?id=ad66532000f7a20b149e47c5eb3a957362c8e161
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
 net/ipv6/fib6_rules.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d22b6c140f23..f9e8fe3ff0c5 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -287,7 +287,8 @@ static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg
 	return false;
 
 suppress_route:
-	ip6_rt_put(rt);
+	if (!(arg->flags & FIB_LOOKUP_NOREF))
+		ip6_rt_put(rt);
 	return true;
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24  7:36 [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule Jason A. Donenfeld
@ 2019-09-24  9:35 ` Jason A. Donenfeld
  2019-09-24 12:52 ` David Miller
  1 sibling, 0 replies; 10+ messages in thread
From: Jason A. Donenfeld @ 2019-09-24  9:35 UTC (permalink / raw)
  To: Netdev, LKML, Wei Wang

Hey Wei,

I meant to CC you but slipped up. Sorry about that. Take a look at
this thread if you have a chance.

Thanks,
Jason

On Tue, Sep 24, 2019 at 10:03 AM Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> Commit 7d9e5f422150 removed references from certain dsts, but accounting
> for this never translated down into the fib6 suppression code. This bug
> was triggered by WireGuard users who use wg-quick(8), which uses the
> "suppress-prefix" directive to ip-rule(8) for routing all of their
> internet traffic without routing loops. The test case in the link of
> this commit reliably triggers various crashes due to the use-after-free
> caused by the reference underflow.
>
> Cc: stable@vger.kernel.org
> Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
> Test-case: https://git.zx2c4.com/WireGuard/commit/?id=ad66532000f7a20b149e47c5eb3a957362c8e161
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
> ---
>  net/ipv6/fib6_rules.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
> index d22b6c140f23..f9e8fe3ff0c5 100644
> --- a/net/ipv6/fib6_rules.c
> +++ b/net/ipv6/fib6_rules.c
> @@ -287,7 +287,8 @@ static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg
>         return false;
>
>  suppress_route:
> -       ip6_rt_put(rt);
> +       if (!(arg->flags & FIB_LOOKUP_NOREF))
> +               ip6_rt_put(rt);
>         return true;
>  }
>
> --
> 2.21.0

On Tue, Sep 24, 2019 at 10:03 AM Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> Commit 7d9e5f422150 removed references from certain dsts, but accounting
> for this never translated down into the fib6 suppression code. This bug
> was triggered by WireGuard users who use wg-quick(8), which uses the
> "suppress-prefix" directive to ip-rule(8) for routing all of their
> internet traffic without routing loops. The test case in the link of
> this commit reliably triggers various crashes due to the use-after-free
> caused by the reference underflow.
>
> Cc: stable@vger.kernel.org
> Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
> Test-case: https://git.zx2c4.com/WireGuard/commit/?id=ad66532000f7a20b149e47c5eb3a957362c8e161
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
> ---
>  net/ipv6/fib6_rules.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
> index d22b6c140f23..f9e8fe3ff0c5 100644
> --- a/net/ipv6/fib6_rules.c
> +++ b/net/ipv6/fib6_rules.c
> @@ -287,7 +287,8 @@ static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg
>         return false;
>
>  suppress_route:
> -       ip6_rt_put(rt);
> +       if (!(arg->flags & FIB_LOOKUP_NOREF))
> +               ip6_rt_put(rt);
>         return true;
>  }
>
> --
> 2.21.0



-- 
Jason A. Donenfeld
Deep Space Explorer
fr: +33 6 51 90 82 66
us: +1 513 476 1200

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24  7:36 [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule Jason A. Donenfeld
  2019-09-24  9:35 ` Jason A. Donenfeld
@ 2019-09-24 12:52 ` David Miller
  2019-09-24 12:55   ` Jason A. Donenfeld
  2019-09-24 14:01   ` [PATCH v2] " Jason A. Donenfeld
  1 sibling, 2 replies; 10+ messages in thread
From: David Miller @ 2019-09-24 12:52 UTC (permalink / raw)
  To: Jason; +Cc: netdev, linux-kernel, stable

From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Tue, 24 Sep 2019 09:36:15 +0200

> Commit 7d9e5f422150 removed references from certain dsts, but accounting
> for this never translated down into the fib6 suppression code. This bug
> was triggered by WireGuard users who use wg-quick(8), which uses the
> "suppress-prefix" directive to ip-rule(8) for routing all of their
> internet traffic without routing loops. The test case in the link of
> this commit reliably triggers various crashes due to the use-after-free
> caused by the reference underflow.
> 
> Cc: stable@vger.kernel.org
> Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
> Test-case: https://git.zx2c4.com/WireGuard/commit/?id=ad66532000f7a20b149e47c5eb3a957362c8e161
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>

Please make such test cases integratabe into the selftests area for networking
and submit it along with this fix.

Otherwise this code will regress.

Thank you.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24 12:52 ` David Miller
@ 2019-09-24 12:55   ` Jason A. Donenfeld
  2019-09-24 13:30     ` David Miller
  2019-09-24 14:01   ` [PATCH v2] " Jason A. Donenfeld
  1 sibling, 1 reply; 10+ messages in thread
From: Jason A. Donenfeld @ 2019-09-24 12:55 UTC (permalink / raw)
  To: David Miller; +Cc: Netdev, LKML, stable

On Tue, Sep 24, 2019 at 2:53 PM David Miller <davem@davemloft.net> wrote:
> Please make such test cases integratabe into the selftests area for networking
> and submit it along with this fix.

That link is for a WireGuard test-case. When we get that upstream,
those will all live in selftests/ all the same as you'd like. For now,
it's running for every kernel on https://build.wireguard.com/ which in
turn runs for every new commit.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24 12:55   ` Jason A. Donenfeld
@ 2019-09-24 13:30     ` David Miller
  2019-09-24 13:49       ` Jason A. Donenfeld
  0 siblings, 1 reply; 10+ messages in thread
From: David Miller @ 2019-09-24 13:30 UTC (permalink / raw)
  To: Jason; +Cc: netdev, linux-kernel, stable

From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Tue, 24 Sep 2019 14:55:04 +0200

> On Tue, Sep 24, 2019 at 2:53 PM David Miller <davem@davemloft.net> wrote:
>> Please make such test cases integratabe into the selftests area for networking
>> and submit it along with this fix.
> 
> That link is for a WireGuard test-case. When we get that upstream,
> those will all live in selftests/ all the same as you'd like. For now,
> it's running for every kernel on https://build.wireguard.com/ which in
> turn runs for every new commit.

I'm asking you to make a non-wireguard test that triggers the problem.

Or would you like a situation you're interested in to break from time
to time.

Jason, please don't be difficult about this and write a proper test
case just like I would ask anyone else fixing bugs like this to write.

Thank you.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24 13:30     ` David Miller
@ 2019-09-24 13:49       ` Jason A. Donenfeld
  0 siblings, 0 replies; 10+ messages in thread
From: Jason A. Donenfeld @ 2019-09-24 13:49 UTC (permalink / raw)
  To: David Miller; +Cc: Netdev, LKML, stable

On Tue, Sep 24, 2019 at 3:30 PM David Miller <davem@davemloft.net> wrote
> I'm asking you to make a non-wireguard test that triggers the problem.
Oh, gotcha. No problem.

>
> Or would you like a situation you're interested in to break from time
> to time.
My test suite should catch it in the future now that it's there, so I'm fine.

> Jason, please don't be difficult about this and write a proper test
> case just like I would ask anyone else fixing bugs like this to write.
I'm not being difficult. I just thought you didn't see what the test
case I linked to actually was. I have no qualms about reimplementing
it with the dummy interface, for a v2 of this patch. Coming your way
shortly.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24 12:52 ` David Miller
  2019-09-24 12:55   ` Jason A. Donenfeld
@ 2019-09-24 14:01   ` Jason A. Donenfeld
  2019-09-24 17:02     ` Wei Wang
                       ` (2 more replies)
  1 sibling, 3 replies; 10+ messages in thread
From: Jason A. Donenfeld @ 2019-09-24 14:01 UTC (permalink / raw)
  To: netdev, linux-kernel, davem, weiwan; +Cc: Jason A. Donenfeld, stable

Commit 7d9e5f422150 removed references from certain dsts, but accounting
for this never translated down into the fib6 suppression code. This bug
was triggered by WireGuard users who use wg-quick(8), which uses the
"suppress-prefix" directive to ip-rule(8) for routing all of their
internet traffic without routing loops. The test case added here
causes the reference underflow by causing packets to evaluate a suppress
rule.

Cc: stable@vger.kernel.org
Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
 net/ipv6/fib6_rules.c                    |  3 ++-
 tools/testing/selftests/net/fib_tests.sh | 17 ++++++++++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d22b6c140f23..f9e8fe3ff0c5 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -287,7 +287,8 @@ static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg
 	return false;
 
 suppress_route:
-	ip6_rt_put(rt);
+	if (!(arg->flags & FIB_LOOKUP_NOREF))
+		ip6_rt_put(rt);
 	return true;
 }
 
diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh
index 4465fc2dae14..c2c5f2bf0f95 100755
--- a/tools/testing/selftests/net/fib_tests.sh
+++ b/tools/testing/selftests/net/fib_tests.sh
@@ -9,7 +9,7 @@ ret=0
 ksft_skip=4
 
 # all tests in this script. Can be overridden with -t option
-TESTS="unregister down carrier nexthop ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics ipv4_route_v6_gw rp_filter"
+TESTS="unregister down carrier nexthop suppress ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics ipv4_route_v6_gw rp_filter"
 
 VERBOSE=0
 PAUSE_ON_FAIL=no
@@ -614,6 +614,20 @@ fib_nexthop_test()
 	cleanup
 }
 
+fib_suppress_test()
+{
+	$IP link add dummy1 type dummy
+	$IP link set dummy1 up
+	$IP -6 route add default dev dummy1
+	$IP -6 rule add table main suppress_prefixlength 0
+	ping -f -c 1000 -W 1 1234::1 || true
+	$IP -6 rule del table main suppress_prefixlength 0
+	$IP link del dummy1
+
+	# If we got here without crashing, we're good.
+	return 0
+}
+
 ################################################################################
 # Tests on route add and replace
 
@@ -1591,6 +1605,7 @@ do
 	fib_carrier_test|carrier)	fib_carrier_test;;
 	fib_rp_filter_test|rp_filter)	fib_rp_filter_test;;
 	fib_nexthop_test|nexthop)	fib_nexthop_test;;
+	fib_suppress_test|suppress)	fib_suppress_test;;
 	ipv6_route_test|ipv6_rt)	ipv6_route_test;;
 	ipv4_route_test|ipv4_rt)	ipv4_route_test;;
 	ipv6_addr_metric)		ipv6_addr_metric_test;;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24 14:01   ` [PATCH v2] " Jason A. Donenfeld
@ 2019-09-24 17:02     ` Wei Wang
  2019-09-26  7:35     ` David Miller
  2019-09-26 14:43     ` David Ahern
  2 siblings, 0 replies; 10+ messages in thread
From: Wei Wang @ 2019-09-24 17:02 UTC (permalink / raw)
  To: Jason A. Donenfeld
  Cc: Linux Kernel Network Developers, lkml, David S . Miller, stable

On Tue, Sep 24, 2019 at 7:01 AM Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> Commit 7d9e5f422150 removed references from certain dsts, but accounting
> for this never translated down into the fib6 suppression code. This bug
> was triggered by WireGuard users who use wg-quick(8), which uses the
> "suppress-prefix" directive to ip-rule(8) for routing all of their
> internet traffic without routing loops. The test case added here
> causes the reference underflow by causing packets to evaluate a suppress
> rule.
>
> Cc: stable@vger.kernel.org
> Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
> ---
Acked-by: Wei Wang <weiwan@google.com>

Good catch. Thanks for the fix.

>  net/ipv6/fib6_rules.c                    |  3 ++-
>  tools/testing/selftests/net/fib_tests.sh | 17 ++++++++++++++++-
>  2 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
> index d22b6c140f23..f9e8fe3ff0c5 100644
> --- a/net/ipv6/fib6_rules.c
> +++ b/net/ipv6/fib6_rules.c
> @@ -287,7 +287,8 @@ static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg
>         return false;
>
>  suppress_route:
> -       ip6_rt_put(rt);
> +       if (!(arg->flags & FIB_LOOKUP_NOREF))
> +               ip6_rt_put(rt);
>         return true;
>  }
>
> diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh
> index 4465fc2dae14..c2c5f2bf0f95 100755
> --- a/tools/testing/selftests/net/fib_tests.sh
> +++ b/tools/testing/selftests/net/fib_tests.sh
> @@ -9,7 +9,7 @@ ret=0
>  ksft_skip=4
>
>  # all tests in this script. Can be overridden with -t option
> -TESTS="unregister down carrier nexthop ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics ipv4_route_v6_gw rp_filter"
> +TESTS="unregister down carrier nexthop suppress ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics ipv4_route_v6_gw rp_filter"
>
>  VERBOSE=0
>  PAUSE_ON_FAIL=no
> @@ -614,6 +614,20 @@ fib_nexthop_test()
>         cleanup
>  }
>
> +fib_suppress_test()
> +{
> +       $IP link add dummy1 type dummy
> +       $IP link set dummy1 up
> +       $IP -6 route add default dev dummy1
> +       $IP -6 rule add table main suppress_prefixlength 0
> +       ping -f -c 1000 -W 1 1234::1 || true
> +       $IP -6 rule del table main suppress_prefixlength 0
> +       $IP link del dummy1
> +
> +       # If we got here without crashing, we're good.
> +       return 0
> +}
> +
>  ################################################################################
>  # Tests on route add and replace
>
> @@ -1591,6 +1605,7 @@ do
>         fib_carrier_test|carrier)       fib_carrier_test;;
>         fib_rp_filter_test|rp_filter)   fib_rp_filter_test;;
>         fib_nexthop_test|nexthop)       fib_nexthop_test;;
> +       fib_suppress_test|suppress)     fib_suppress_test;;
>         ipv6_route_test|ipv6_rt)        ipv6_route_test;;
>         ipv4_route_test|ipv4_rt)        ipv4_route_test;;
>         ipv6_addr_metric)               ipv6_addr_metric_test;;
> --
> 2.21.0
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24 14:01   ` [PATCH v2] " Jason A. Donenfeld
  2019-09-24 17:02     ` Wei Wang
@ 2019-09-26  7:35     ` David Miller
  2019-09-26 14:43     ` David Ahern
  2 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2019-09-26  7:35 UTC (permalink / raw)
  To: Jason; +Cc: netdev, linux-kernel, weiwan, stable

From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Tue, 24 Sep 2019 16:01:28 +0200

> Commit 7d9e5f422150 removed references from certain dsts, but accounting
> for this never translated down into the fib6 suppression code. This bug
> was triggered by WireGuard users who use wg-quick(8), which uses the
> "suppress-prefix" directive to ip-rule(8) for routing all of their
> internet traffic without routing loops. The test case added here
> causes the reference underflow by causing packets to evaluate a suppress
> rule.
> 
> Cc: stable@vger.kernel.org

Please don't CC: stable for networking fixes, I handle these manually as per
the netdev FAQ.

> Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>

Applied and queued up for -stable, thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule
  2019-09-24 14:01   ` [PATCH v2] " Jason A. Donenfeld
  2019-09-24 17:02     ` Wei Wang
  2019-09-26  7:35     ` David Miller
@ 2019-09-26 14:43     ` David Ahern
  2 siblings, 0 replies; 10+ messages in thread
From: David Ahern @ 2019-09-26 14:43 UTC (permalink / raw)
  To: Jason A. Donenfeld, netdev, linux-kernel, davem, weiwan; +Cc: stable

On 9/24/19 8:01 AM, Jason A. Donenfeld wrote:
> Commit 7d9e5f422150 removed references from certain dsts, but accounting
> for this never translated down into the fib6 suppression code. This bug
> was triggered by WireGuard users who use wg-quick(8), which uses the
> "suppress-prefix" directive to ip-rule(8) for routing all of their
> internet traffic without routing loops. The test case added here
> causes the reference underflow by causing packets to evaluate a suppress
> rule.
> 
> Cc: stable@vger.kernel.org
> Fixes: 7d9e5f422150 ("ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF")
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
> ---
>  net/ipv6/fib6_rules.c                    |  3 ++-
>  tools/testing/selftests/net/fib_tests.sh | 17 ++++++++++++++++-
>  2 files changed, 18 insertions(+), 2 deletions(-)

Thanks for adding the test case.

Reviewed-by: David Ahern <dsahern@gmail.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-09-26 14:43 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-24  7:36 [PATCH] ipv6: do not free rt if FIB_LOOKUP_NOREF is set on suppress rule Jason A. Donenfeld
2019-09-24  9:35 ` Jason A. Donenfeld
2019-09-24 12:52 ` David Miller
2019-09-24 12:55   ` Jason A. Donenfeld
2019-09-24 13:30     ` David Miller
2019-09-24 13:49       ` Jason A. Donenfeld
2019-09-24 14:01   ` [PATCH v2] " Jason A. Donenfeld
2019-09-24 17:02     ` Wei Wang
2019-09-26  7:35     ` David Miller
2019-09-26 14:43     ` David Ahern

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).