diff options
Diffstat (limited to 'net/core/sock.c')
| -rw-r--r-- | net/core/sock.c | 15 | 
1 files changed, 11 insertions, 4 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 9b7b6bbb2a23..415f441c63b9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1654,6 +1654,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)  		sock_copy(newsk, sk); +		newsk->sk_prot_creator = sk->sk_prot; +  		/* SANITY */  		if (likely(newsk->sk_net_refcnt))  			get_net(sock_net(newsk)); @@ -1675,20 +1677,28 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)  		newsk->sk_dst_pending_confirm = 0;  		newsk->sk_wmem_queued	= 0;  		newsk->sk_forward_alloc = 0; + +		/* sk->sk_memcg will be populated at accept() time */ +		newsk->sk_memcg = NULL; +  		atomic_set(&newsk->sk_drops, 0);  		newsk->sk_send_head	= NULL;  		newsk->sk_userlocks	= sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;  		atomic_set(&newsk->sk_zckey, 0);  		sock_reset_flag(newsk, SOCK_DONE); +		cgroup_sk_alloc(&newsk->sk_cgrp_data); -		filter = rcu_dereference_protected(newsk->sk_filter, 1); +		rcu_read_lock(); +		filter = rcu_dereference(sk->sk_filter);  		if (filter != NULL)  			/* though it's an empty new sock, the charging may fail  			 * if sysctl_optmem_max was changed between creation of  			 * original socket and cloning  			 */  			is_charged = sk_filter_charge(newsk, filter); +		RCU_INIT_POINTER(newsk->sk_filter, filter); +		rcu_read_unlock();  		if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) {  			/* We need to make sure that we don't uncharge the new @@ -1709,9 +1719,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)  		newsk->sk_incoming_cpu = raw_smp_processor_id();  		atomic64_set(&newsk->sk_cookie, 0); -		mem_cgroup_sk_alloc(newsk); -		cgroup_sk_alloc(&newsk->sk_cgrp_data); -  		/*  		 * Before updating sk_refcnt, we must commit prior changes to memory  		 * (Documentation/RCU/rculist_nulls.txt for details)  |