diff options
Diffstat (limited to 'net/core/sock_map.c')
| -rw-r--r-- | net/core/sock_map.c | 22 | 
1 files changed, 10 insertions, 12 deletions
diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 9402889840bf..d3dbb92153f2 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -423,9 +423,6 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,  	struct sock *sk;  	int err = 0; -	if (irqs_disabled()) -		return -EOPNOTSUPP; /* locks here are hardirq-unsafe */ -  	spin_lock_bh(&stab->lock);  	sk = *psk;  	if (!sk_test || sk_test == sk) @@ -948,9 +945,6 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key)  	struct bpf_shtab_elem *elem;  	int ret = -ENOENT; -	if (irqs_disabled()) -		return -EOPNOTSUPP; /* locks here are hardirq-unsafe */ -  	hash = sock_hash_bucket_hash(key, key_size);  	bucket = sock_hash_select_bucket(htab, hash); @@ -1680,19 +1674,23 @@ void sock_map_close(struct sock *sk, long timeout)  	lock_sock(sk);  	rcu_read_lock(); -	psock = sk_psock_get(sk); -	if (unlikely(!psock)) { -		rcu_read_unlock(); -		release_sock(sk); -		saved_close = READ_ONCE(sk->sk_prot)->close; -	} else { +	psock = sk_psock(sk); +	if (likely(psock)) {  		saved_close = psock->saved_close;  		sock_map_remove_links(sk, psock); +		psock = sk_psock_get(sk); +		if (unlikely(!psock)) +			goto no_psock;  		rcu_read_unlock();  		sk_psock_stop(psock);  		release_sock(sk);  		cancel_delayed_work_sync(&psock->work);  		sk_psock_put(sk, psock); +	} else { +		saved_close = READ_ONCE(sk->sk_prot)->close; +no_psock: +		rcu_read_unlock(); +		release_sock(sk);  	}  	/* Make sure we do not recurse. This is a bug.  |