diff mbox series

[net-next] mld: add missing rtnl_lock() in do_ipv6_getsockopt()

Message ID 20210330153106.31614-1-ap420073@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [net-next] mld: add missing rtnl_lock() in do_ipv6_getsockopt() | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Clearly marked for net-next
netdev/subject_prefix success Link
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 14 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link

Commit Message

Taehee Yoo March 30, 2021, 3:31 p.m. UTC
ip6_mc_msfget() should be called under RTNL because it accesses RTNL
protected data. but the caller doesn't acquire rtnl_lock().
So, data couldn't be protected.
Therefore, it adds rtnl_lock() in do_ipv6_getsockopt(),
which is the caller of ip6_mc_msfget().

Splat looks like:
=============================
WARNING: suspicious RCU usage
5.12.0-rc4+ #480 Tainted: G        W
-----------------------------
include/net/addrconf.h:314 suspicious rcu_dereference_check() usage!

other info that might help us debug this:

rcu_scheduler_active = 2, debug_locks = 1
1 lock held by sockopt_msfilte/4955:
 #0: ffff88800aa21370 (sk_lock-AF_INET6){+.+.}-{0:0}, at: \
	ipv6_get_msfilter+0xaf/0x190

stack backtrace:
Call Trace:
 dump_stack+0xa4/0xe5
 ip6_mc_find_dev_rtnl+0x117/0x150
 ip6_mc_msfget+0x17d/0x700
 ? lock_acquire+0x191/0x720
 ? ipv6_sock_mc_join_ssm+0x10/0x10
 ? lockdep_hardirqs_on_prepare+0x3e0/0x3e0
 ? mark_held_locks+0xb7/0x120
 ? lockdep_hardirqs_on_prepare+0x27c/0x3e0
 ? __local_bh_enable_ip+0xa5/0xf0
 ? lock_sock_nested+0x82/0xf0
 ipv6_get_msfilter+0xc3/0x190
 ? compat_ipv6_get_msfilter+0x300/0x300
 ? lock_downgrade+0x690/0x690
 do_ipv6_getsockopt.isra.6.constprop.13+0x1706/0x29f0
 ? do_ipv6_mcast_group_source+0x150/0x150
 ? __wake_up_common+0x620/0x620
 ? mutex_trylock+0x23f/0x2a0
[ ... ]

Fixes: 88e2ca308094 ("mld: convert ifmcaddr6 to RCU")
Reported-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---

commit 88e2ca308094 ("mld: convert ifmcaddr6 to RCU") is not yet merged
to "net" branch. So, target branch is "net-next"

 net/ipv6/ipv6_sockglue.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Eric Dumazet March 30, 2021, 3:40 p.m. UTC | #1
On Tue, Mar 30, 2021 at 5:31 PM Taehee Yoo <ap420073@gmail.com> wrote:
>
> ip6_mc_msfget() should be called under RTNL because it accesses RTNL
> protected data. but the caller doesn't acquire rtnl_lock().
> So, data couldn't be protected.
> Therefore, it adds rtnl_lock() in do_ipv6_getsockopt(),
> which is the caller of ip6_mc_msfget().
>
> Splat looks like:
> =============================
> WARNING: suspicious RCU usage
> 5.12.0-rc4+ #480 Tainted: G        W
> -----------------------------
> include/net/addrconf.h:314 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
> rcu_scheduler_active = 2, debug_locks = 1
> 1 lock held by sockopt_msfilte/4955:
>  #0: ffff88800aa21370 (sk_lock-AF_INET6){+.+.}-{0:0}, at: \
>         ipv6_get_msfilter+0xaf/0x190
>
> stack backtrace:
> Call Trace:
>  dump_stack+0xa4/0xe5
>  ip6_mc_find_dev_rtnl+0x117/0x150
>  ip6_mc_msfget+0x17d/0x700
>  ? lock_acquire+0x191/0x720
>  ? ipv6_sock_mc_join_ssm+0x10/0x10
>  ? lockdep_hardirqs_on_prepare+0x3e0/0x3e0
>  ? mark_held_locks+0xb7/0x120
>  ? lockdep_hardirqs_on_prepare+0x27c/0x3e0
>  ? __local_bh_enable_ip+0xa5/0xf0
>  ? lock_sock_nested+0x82/0xf0
>  ipv6_get_msfilter+0xc3/0x190
>  ? compat_ipv6_get_msfilter+0x300/0x300
>  ? lock_downgrade+0x690/0x690
>  do_ipv6_getsockopt.isra.6.constprop.13+0x1706/0x29f0
>  ? do_ipv6_mcast_group_source+0x150/0x150
>  ? __wake_up_common+0x620/0x620
>  ? mutex_trylock+0x23f/0x2a0
> [ ... ]
>
> Fixes: 88e2ca308094 ("mld: convert ifmcaddr6 to RCU")
> Reported-by: Eric Dumazet <edumazet@google.com>
> Signed-off-by: Taehee Yoo <ap420073@gmail.com>
> ---
>
> commit 88e2ca308094 ("mld: convert ifmcaddr6 to RCU") is not yet merged
> to "net" branch. So, target branch is "net-next"
>
>  net/ipv6/ipv6_sockglue.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
> index a6804a7e34c1..55dc35e09c68 100644
> --- a/net/ipv6/ipv6_sockglue.c
> +++ b/net/ipv6/ipv6_sockglue.c
> @@ -1137,9 +1137,12 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
>                 val = sk->sk_family;
>                 break;
>         case MCAST_MSFILTER:
> +               rtnl_lock();
>                 if (in_compat_syscall())
> -                       return compat_ipv6_get_msfilter(sk, optval, optlen);
> -               return ipv6_get_msfilter(sk, optval, optlen, len);
> +                       val = compat_ipv6_get_msfilter(sk, optval, optlen);
> +               val = ipv6_get_msfilter(sk, optval, optlen, len);
> +               rtnl_unlock();
> +               return val;


This seems a serious regression compared to old code (in net tree)

Have you added RTNL requirement in all this code ?

We would like to use RTNL only if strictly needed.
Taehee Yoo March 30, 2021, 4:02 p.m. UTC | #2
On 3/31/21 12:40 AM, Eric Dumazet wrote:
 > This seems a serious regression compared to old code (in net tree)
 >
 > Have you added RTNL requirement in all this code ?
 >
 > We would like to use RTNL only if strictly needed.

Yes, I agree with you.
This patchset actually relies on existed RTNL, which is 
setsockopt_needs_rtnl().
And remained RTNL was replaced by mc_lock.
So, this patchset actually doesn't add new RTNL except in this case.

Fortunately, I think It can be replaced by RCU because,
1. ip6_mc_msfget() doesn't need the sleepable functions.
2. It is not the write critical section.
So, RCU can be used instead of RTNL for ip6_mc_msfget().
How do you think about it?
Eric Dumazet March 30, 2021, 4:08 p.m. UTC | #3
On Tue, Mar 30, 2021 at 6:02 PM Taehee Yoo <ap420073@gmail.com> wrote:
>
> On 3/31/21 12:40 AM, Eric Dumazet wrote:
>  > This seems a serious regression compared to old code (in net tree)
>  >
>  > Have you added RTNL requirement in all this code ?
>  >
>  > We would like to use RTNL only if strictly needed.
>
> Yes, I agree with you.
> This patchset actually relies on existed RTNL, which is
> setsockopt_needs_rtnl().
> And remained RTNL was replaced by mc_lock.
> So, this patchset actually doesn't add new RTNL except in this case.
>
> Fortunately, I think It can be replaced by RCU because,
> 1. ip6_mc_msfget() doesn't need the sleepable functions.
> 2. It is not the write critical section.
> So, RCU can be used instead of RTNL for ip6_mc_msfget().
> How do you think about it?

Yes please, do not add RTNL here if we can avoid it.

Otherwise some applications will slow down the whole stack, even with
different containers/netns.

(There is a single RTNL for the whole machine)
Taehee Yoo March 30, 2021, 4:13 p.m. UTC | #4
On 3/31/21 1:08 AM, Eric Dumazet wrote:
 > On Tue, Mar 30, 2021 at 6:02 PM Taehee Yoo <ap420073@gmail.com> wrote:
 >>
 >> On 3/31/21 12:40 AM, Eric Dumazet wrote:
 >>   > This seems a serious regression compared to old code (in net tree)
 >>   >
 >>   > Have you added RTNL requirement in all this code ?
 >>   >
 >>   > We would like to use RTNL only if strictly needed.
 >>
 >> Yes, I agree with you.
 >> This patchset actually relies on existed RTNL, which is
 >> setsockopt_needs_rtnl().
 >> And remained RTNL was replaced by mc_lock.
 >> So, this patchset actually doesn't add new RTNL except in this case.
 >>
 >> Fortunately, I think It can be replaced by RCU because,
 >> 1. ip6_mc_msfget() doesn't need the sleepable functions.
 >> 2. It is not the write critical section.
 >> So, RCU can be used instead of RTNL for ip6_mc_msfget().
 >> How do you think about it?
 >
 > Yes please, do not add RTNL here if we can avoid it.
 >
Okay, I will send a new patch.

 > Otherwise some applications will slow down the whole stack, even with
 > different containers/netns.
 >
 > (There is a single RTNL for the whole machine)
 >

Thanks a lot for the review!
diff mbox series

Patch

diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index a6804a7e34c1..55dc35e09c68 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -1137,9 +1137,12 @@  static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
 		val = sk->sk_family;
 		break;
 	case MCAST_MSFILTER:
+		rtnl_lock();
 		if (in_compat_syscall())
-			return compat_ipv6_get_msfilter(sk, optval, optlen);
-		return ipv6_get_msfilter(sk, optval, optlen, len);
+			val = compat_ipv6_get_msfilter(sk, optval, optlen);
+		val = ipv6_get_msfilter(sk, optval, optlen, len);
+		rtnl_unlock();
+		return val;
 	case IPV6_2292PKTOPTIONS:
 	{
 		struct msghdr msg;