linux/net/l2tp
Guillaume Nault ee40fb2e1e l2tp: protect sock pointer of struct pppol2tp_session with RCU
pppol2tp_session_create() registers sessions that can't have their
corresponding socket initialised. This socket has to be created by
userspace, then connected to the session by pppol2tp_connect().
Therefore, we need to protect the pppol2tp socket pointer of L2TP
sessions, so that it can safely be updated when userspace is connecting
or closing the socket. This will eventually allow pppol2tp_connect()
to avoid generating transient states while initialising its parts of the
session.

To this end, this patch protects the pppol2tp socket pointer using RCU.

The pppol2tp socket pointer is still set in pppol2tp_connect(), but
only once we know the function isn't going to fail. It's eventually
reset by pppol2tp_release(), which now has to wait for a grace period
to elapse before it can drop the last reference on the socket. This
ensures that pppol2tp_session_get_sock() can safely grab a reference
on the socket, even after ps->sk is reset to NULL but before this
operation actually gets visible from pppol2tp_session_get_sock().

The rest is standard RCU conversion: pppol2tp_recv(), which already
runs in atomic context, is simply enclosed by rcu_read_lock() and
rcu_read_unlock(), while other functions are converted to use
pppol2tp_session_get_sock() followed by sock_put().
pppol2tp_session_setsockopt() is a special case. It used to retrieve
the pppol2tp socket from the L2TP session, which itself was retrieved
from the pppol2tp socket. Therefore we can just avoid dereferencing
ps->sk and directly use the original socket pointer instead.

With all users of ps->sk now handling NULL and concurrent updates, the
L2TP ->ref() and ->deref() callbacks aren't needed anymore. Therefore,
rather than converting pppol2tp_session_sock_hold() and
pppol2tp_session_sock_put(), we can just drop them.

Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-10-29 11:16:22 +09:00
..
Kconfig l2tp: Call udp_sock_create 2014-07-14 16:12:15 -07:00
l2tp_core.c l2tp: don't register sessions in l2tp_session_create() 2017-10-29 11:16:21 +09:00
l2tp_core.h l2tp: don't register sessions in l2tp_session_create() 2017-10-29 11:16:21 +09:00
l2tp_debugfs.c net, l2tp: convert l2tp_tunnel.ref_count from atomic_t to refcount_t 2017-07-04 22:35:15 +01:00
l2tp_eth.c l2tp: initialise l2tp_eth sessions before registering them 2017-10-29 11:16:22 +09:00
l2tp_ip6.c l2tp: fix race in l2tp_recv_common() 2017-04-01 20:16:41 -07:00
l2tp_ip.c l2tp: fix race in l2tp_recv_common() 2017-04-01 20:16:41 -07:00
l2tp_netlink.c l2tp: cleanup l2tp_tunnel_delete calls 2017-10-27 13:48:32 +09:00
l2tp_ppp.c l2tp: protect sock pointer of struct pppol2tp_session with RCU 2017-10-29 11:16:22 +09:00
Makefile l2tp: introduce L2TPv3 IP encapsulation support for IPv6 2012-05-01 09:30:55 -04:00