diff options
Diffstat (limited to 'net/core/sock_map.c')
| -rw-r--r-- | net/core/sock_map.c | 38 | 
1 files changed, 24 insertions, 14 deletions
| diff --git a/net/core/sock_map.c b/net/core/sock_map.c index f39ef79ced67..1827669eedd6 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -167,8 +167,11 @@ static void sock_map_del_link(struct sock *sk,  		write_lock_bh(&sk->sk_callback_lock);  		if (strp_stop)  			sk_psock_stop_strp(sk, psock); -		else +		if (verdict_stop)  			sk_psock_stop_verdict(sk, psock); + +		if (psock->psock_update_sk_prot) +			psock->psock_update_sk_prot(sk, psock, false);  		write_unlock_bh(&sk->sk_callback_lock);  	}  } @@ -282,32 +285,38 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk)  	if (msg_parser)  		psock_set_prog(&psock->progs.msg_parser, msg_parser); +	if (stream_parser) +		psock_set_prog(&psock->progs.stream_parser, stream_parser); +	if (stream_verdict) +		psock_set_prog(&psock->progs.stream_verdict, stream_verdict); +	if (skb_verdict) +		psock_set_prog(&psock->progs.skb_verdict, skb_verdict); +	/* msg_* and stream_* programs references tracked in psock after this +	 * point. Reference dec and cleanup will occur through psock destructor +	 */  	ret = sock_map_init_proto(sk, psock); -	if (ret < 0) -		goto out_drop; +	if (ret < 0) { +		sk_psock_put(sk, psock); +		goto out; +	}  	write_lock_bh(&sk->sk_callback_lock);  	if (stream_parser && stream_verdict && !psock->saved_data_ready) {  		ret = sk_psock_init_strp(sk, psock); -		if (ret) -			goto out_unlock_drop; -		psock_set_prog(&psock->progs.stream_verdict, stream_verdict); -		psock_set_prog(&psock->progs.stream_parser, stream_parser); +		if (ret) { +			write_unlock_bh(&sk->sk_callback_lock); +			sk_psock_put(sk, psock); +			goto out; +		}  		sk_psock_start_strp(sk, psock);  	} else if (!stream_parser && stream_verdict && !psock->saved_data_ready) { -		psock_set_prog(&psock->progs.stream_verdict, stream_verdict);  		sk_psock_start_verdict(sk,psock);  	} else if (!stream_verdict && skb_verdict && !psock->saved_data_ready) { -		psock_set_prog(&psock->progs.skb_verdict, skb_verdict);  		sk_psock_start_verdict(sk, psock);  	}  	write_unlock_bh(&sk->sk_callback_lock);  	return 0; -out_unlock_drop: -	write_unlock_bh(&sk->sk_callback_lock); -out_drop: -	sk_psock_put(sk, psock);  out_progs:  	if (skb_verdict)  		bpf_prog_put(skb_verdict); @@ -320,6 +329,7 @@ out_put_stream_parser:  out_put_stream_verdict:  	if (stream_verdict)  		bpf_prog_put(stream_verdict); +out:  	return ret;  } @@ -1559,7 +1569,7 @@ static struct bpf_iter_reg sock_map_iter_reg = {  	.ctx_arg_info_size	= 2,  	.ctx_arg_info		= {  		{ offsetof(struct bpf_iter__sockmap, key), -		  PTR_TO_RDONLY_BUF_OR_NULL }, +		  PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY },  		{ offsetof(struct bpf_iter__sockmap, sk),  		  PTR_TO_BTF_ID_OR_NULL },  	}, |