On Wed, Apr 24, 2019 at 2:58 AM Guillaume Nault <gna...@redhat.com> wrote: > > On Tue, Apr 23, 2019 at 09:43:26AM -0700, Eric Dumazet wrote: > > Canonical way to fetch sk_user_data from an encap_rcv() handler called > > from UDP stack in rcu protected section is to use > > rcu_dereference_sk_user_data(), > > otherwise compiler might read it multiple times. > > > That reminds me the more general problem we have with ->sk_user_data: > https://lore.kernel.org/netdev/20180117.142538.1972806008716856078.da...@davemloft.net/ > > We're not even guarateed that ->sk_user_data points to a struct l2tp_tunnel > (some external modules can still probably override it). >
RCU rules should prevail. An RCU grace period must be enforced if the same UDP socket has its sk_user_data changed. Normally, UDP socket observes an RCU grace period at close/destroy time. (SOCK_RCU_FREE) If we detect the same UDP socket has not been closed between clearing sk_user_data and setting it again to a non NULL value, we must insert a synchronize_rcu() A generic change could look like the following (but we must check that all rcu_assign_sk_user_data() callers can sleep) diff --git a/include/net/sock.h b/include/net/sock.h index 784cd19d5ff76b53865f79d4580f3fa269fa2408..3cf0dfd9d83a956220d69138339561b62407addd 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -522,7 +522,6 @@ enum sk_pacing { #define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data))) #define rcu_dereference_sk_user_data(sk) rcu_dereference(__sk_user_data((sk))) -#define rcu_assign_sk_user_data(sk, ptr) rcu_assign_pointer(__sk_user_data((sk)), ptr) /* * SK_CAN_REUSE and SK_NO_REUSE on a socket mean that the socket is OK @@ -811,6 +810,7 @@ enum sock_flags { SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */ SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */ SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */ + SOCK_USER_DATA_SET, SOCK_TXTIME, SOCK_XDP, /* XDP is attached */ SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */ @@ -2582,4 +2582,15 @@ static inline bool sk_dev_equal_l3scope(struct sock *sk, int dif) return false; } +static inline void rcu_assign_sk_user_data(struct sock *sk, void *ptr) +{ + if (ptr) { + might_sleep(); + if (sock_flag(sk, SOCK_USER_DATA_SET)) + synchronize_net(); + } + rcu_assign_pointer(__sk_user_data((sk)), ptr); + if (ptr) + sock_set_flag(sk, SOCK_USER_DATA_SET); +} #endif /* _SOCK_H */ > There were some locking rules defined for setting ->sk_user_data: > https://lore.kernel.org/netdev/20180124203541.3172-3-...@quantonium.net/ > Converting all users to either avoid using ->sk_user_data or using it > under the proper pre-conditions has been on my TODO list for a while... > I'll try to revive this effort. Avoiding using sk_user_data seems not practical. However making sure it is not blindly overwritten by a buggy module is doable. > > > Fixes: d00fa9adc528 ("il2tp: fix races with tunnel socket close") > ^ > Spurious "i". Vi user? :) I am not a vi user ;) > > > Signed-off-by: Eric Dumazet <eduma...@google.com> > > Cc: James Chapman <jchap...@katalix.com> > > --- > > net/l2tp/l2tp_core.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c > > index > > fed6becc5daf86afa2ad9188bb28e151244bb5a6..aee33d1320184e411dbedff72b5bf5199481e53f > > 100644 > > --- a/net/l2tp/l2tp_core.c > > +++ b/net/l2tp/l2tp_core.c > > @@ -909,7 +909,7 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff > > *skb) > > { > > struct l2tp_tunnel *tunnel; > > > > - tunnel = l2tp_tunnel(sk); > > + tunnel = rcu_dereference_sk_user_data(sk); > > if (tunnel == NULL) > > goto pass_up; > > > > -- > > 2.21.0.593.g511ec345e18-goog > >