diff options
Diffstat (limited to 'kernel/bpf/sockmap.c')
| -rw-r--r-- | kernel/bpf/sockmap.c | 11 | 
1 files changed, 9 insertions, 2 deletions
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 5ee2e41893d9..1712d319c2d8 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c @@ -591,8 +591,15 @@ static void sock_map_free(struct bpf_map *map)  		write_lock_bh(&sock->sk_callback_lock);  		psock = smap_psock_sk(sock); -		smap_list_remove(psock, &stab->sock_map[i]); -		smap_release_sock(psock, sock); +		/* This check handles a racing sock event that can get the +		 * sk_callback_lock before this case but after xchg happens +		 * causing the refcnt to hit zero and sock user data (psock) +		 * to be null and queued for garbage collection. +		 */ +		if (likely(psock)) { +			smap_list_remove(psock, &stab->sock_map[i]); +			smap_release_sock(psock, sock); +		}  		write_unlock_bh(&sock->sk_callback_lock);  	}  	rcu_read_unlock();  |