diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 16 | 
1 files changed, 16 insertions, 0 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 883df0ad5bfe..6d664d83cd16 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -117,6 +117,21 @@ static u32 tcp_v6_init_ts_off(const struct net *net, const struct sk_buff *skb)  				   ipv6_hdr(skb)->saddr.s6_addr32);  } +static int tcp_v6_pre_connect(struct sock *sk, struct sockaddr *uaddr, +			      int addr_len) +{ +	/* This check is replicated from tcp_v6_connect() and intended to +	 * prevent BPF program called below from accessing bytes that are out +	 * of the bound specified by user in addr_len. +	 */ +	if (addr_len < SIN6_LEN_RFC2133) +		return -EINVAL; + +	sock_owned_by_me(sk); + +	return BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr); +} +  static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,  			  int addr_len)  { @@ -1925,6 +1940,7 @@ struct proto tcpv6_prot = {  	.name			= "TCPv6",  	.owner			= THIS_MODULE,  	.close			= tcp_close, +	.pre_connect		= tcp_v6_pre_connect,  	.connect		= tcp_v6_connect,  	.disconnect		= tcp_disconnect,  	.accept			= inet_csk_accept,  | 
