Commit e198987e authored by Taehee Yoo's avatar Taehee Yoo Committed by David S. Miller

gtp: fix suspicious RCU usage

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: 1e3a3abd ("gtp: make GTP sockets in gtp_newlink optional")
Signed-off-by: default avatarTaehee Yoo <ap420073@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ccd1479e
...@@ -289,12 +289,14 @@ static void gtp_encap_destroy(struct sock *sk) ...@@ -289,12 +289,14 @@ static void gtp_encap_destroy(struct sock *sk)
{ {
struct gtp_dev *gtp; struct gtp_dev *gtp;
gtp = rcu_dereference_sk_user_data(sk); lock_sock(sk);
gtp = sk->sk_user_data;
if (gtp) { if (gtp) {
udp_sk(sk)->encap_type = 0; udp_sk(sk)->encap_type = 0;
rcu_assign_sk_user_data(sk, NULL); rcu_assign_sk_user_data(sk, NULL);
sock_put(sk); sock_put(sk);
} }
release_sock(sk);
} }
static void gtp_encap_disable_sock(struct sock *sk) static void gtp_encap_disable_sock(struct sock *sk)
...@@ -796,7 +798,8 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, ...@@ -796,7 +798,8 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
goto out_sock; 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); sk = ERR_PTR(-EBUSY);
goto out_sock; goto out_sock;
} }
...@@ -812,6 +815,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, ...@@ -812,6 +815,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg); setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
out_sock: out_sock:
release_sock(sock->sk);
sockfd_put(sock); sockfd_put(sock);
return sk; return sk;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment