Messages in this thread | | | Date | Wed, 22 May 2013 12:12:56 +0400 | From | Roman Gushchin <> | Subject | Re: [ 072/102] ipv6: do not clear pinet6 field |
| |
On 22.05.2013 01:47, Eric Dumazet wrote: > On Tue, 2013-05-21 at 15:44 +0400, Roman Gushchin wrote: >> Hi, all! >> >> I think, it's good, but not enough. >> >> We still can't rely on the sk->sk_family field by dereferencing the >> inet_sk(sk)->pinet6 field, because we can set the sk_family field to >> the PF_INET6 value before setting pinet6 to an appropriate value >> (assuming it is NULL just because it was not a PF_INET6 socket in a >> previous life). >> >> net/ipv6/af_inet6.c: >> static int inet6_create(struct net *net, struct socket *sock, int >> protocol, int kern) >> { >> <...> >> err = -ENOBUFS; >> sk = sk_alloc(net, PF_INET6, GFP_KERNEL, answer_prot); >> if (sk == NULL) >> goto out; >> <...> >> sk->sk_destruct = inet_sock_destruct; >> sk->sk_family = PF_INET6; >> sk->sk_protocol = protocol; >> >> sk->sk_backlog_rcv = answer->prot->backlog_rcv; >> >> inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk); >> <...> >> } >> >> net/core/sock.c: >> struct sock *sk_alloc(struct net *net, int family, gfp_t priority, >> struct proto *prot) >> { >> struct sock *sk; >> >> sk = sk_prot_alloc(prot, priority | __GFP_ZERO, family); >> if (sk) { >> sk->sk_family = family; >> <...> >> } >> >> >> So, we need to care about setting sk_family to PF_INET6 _strictly_ after >> setting the pinet6 field to a valid value (using rcu_assign_pointer(), >> for instance). > > This can never happen. > > A socket cannot be find in a hash chain while pinet6 is not set. > > For a given socket pointer sk (say TCP or UDP), pinet6 is a constant and > cannot change. (This is a property of SLAB_DESTROY_BY_RCU : slab cannot > be merged, so all objects are of the same type)
I missed that. > > So the order of writing sk_family / pinet6 is irrelevant.
Agree.
Thank you for clarification!
Regards, Roman
| |