gtp: fix suspicious RCU usage
[ Upstream commit e198987e7dd7d3645a53875151cd6f8fc425b706 ]
gtp_encap_enable_socket() and gtp_encap_destroy() are not protected
by rcu_read_lock(). and it's not safe to write sk->sk_user_data.
This patch make these functions to use lock_sock() instead of
rcu_dereference_sk_user_data().
Test commands:
gtp-link add gtp1
Splat looks like:
[ 83.238315] =============================
[ 83.239127] WARNING: suspicious RCU usage
[ 83.239702] 5.2.0-rc6+ #49 Not tainted
[ 83.240268] -----------------------------
[ 83.241205] drivers/net/gtp.c:799 suspicious rcu_dereference_check() usage!
[ 83.243828]
[ 83.243828] other info that might help us debug this:
[ 83.243828]
[ 83.246325]
[ 83.246325] rcu_scheduler_active = 2, debug_locks = 1
[ 83.247314] 1 lock held by gtp-link/1008:
[ 83.248523] #0: 0000000017772c7f (rtnl_mutex){+.+.}, at: __rtnl_newlink+0x5f5/0x11b0
[ 83.251503]
[ 83.251503] stack backtrace:
[ 83.252173] CPU: 0 PID: 1008 Comm: gtp-link Not tainted 5.2.0-rc6+ #49
[ 83.253271] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 83.254562] Call Trace:
[ 83.254995] dump_stack+0x7c/0xbb
[ 83.255567] gtp_encap_enable_socket+0x2df/0x360 [gtp]
[ 83.256415] ? gtp_find_dev+0x1a0/0x1a0 [gtp]
[ 83.257161] ? memset+0x1f/0x40
[ 83.257843] gtp_newlink+0x90/0xa21 [gtp]
[ 83.258497] ? __netlink_ns_capable+0xc3/0xf0
[ 83.259260] __rtnl_newlink+0xb9f/0x11b0
[ 83.260022] ? rtnl_link_unregister+0x230/0x230
[ ... ]
Fixes: 1e3a3abd8b
("gtp: make GTP sockets in gtp_newlink optional")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
202de90df2
commit
e117a04133
1 changed files with 6 additions and 2 deletions
|
@ -293,12 +293,14 @@ static void gtp_encap_destroy(struct sock *sk)
|
|||
{
|
||||
struct gtp_dev *gtp;
|
||||
|
||||
gtp = rcu_dereference_sk_user_data(sk);
|
||||
lock_sock(sk);
|
||||
gtp = sk->sk_user_data;
|
||||
if (gtp) {
|
||||
udp_sk(sk)->encap_type = 0;
|
||||
rcu_assign_sk_user_data(sk, NULL);
|
||||
sock_put(sk);
|
||||
}
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
static void gtp_encap_disable_sock(struct sock *sk)
|
||||
|
@ -800,7 +802,8 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
|
|||
goto out_sock;
|
||||
}
|
||||
|
||||
if (rcu_dereference_sk_user_data(sock->sk)) {
|
||||
lock_sock(sock->sk);
|
||||
if (sock->sk->sk_user_data) {
|
||||
sk = ERR_PTR(-EBUSY);
|
||||
goto out_sock;
|
||||
}
|
||||
|
@ -816,6 +819,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
|
|||
setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
|
||||
|
||||
out_sock:
|
||||
release_sock(sock->sk);
|
||||
sockfd_put(sock);
|
||||
return sk;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue