All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Toke Høiland-Jørgensen" <toke@redhat.com>
To: Petar Penkov <ppenkov.kernel@gmail.com>,
	netdev@vger.kernel.org, bpf@vger.kernel.org
Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net,
	edumazet@google.com, lmb@cloudflare.com, sdf@google.com,
	Petar Penkov <ppenkov@google.com>
Subject: Re: [bpf-next 3/6] bpf: add bpf_tcp_gen_syncookie helper
Date: Tue, 23 Jul 2019 14:33:02 +0200	[thread overview]
Message-ID: <8736ix3p8h.fsf@toke.dk> (raw)
In-Reply-To: <20190723002042.105927-4-ppenkov.kernel@gmail.com>

Petar Penkov <ppenkov.kernel@gmail.com> writes:

> From: Petar Penkov <ppenkov@google.com>
>
> This helper function allows BPF programs to try to generate SYN
> cookies, given a reference to a listener socket. The function works
> from XDP and with an skb context since bpf_skc_lookup_tcp can lookup a
> socket in both cases.
>
> Signed-off-by: Petar Penkov <ppenkov@google.com>
> Suggested-by: Eric Dumazet <edumazet@google.com>
> ---
>  include/uapi/linux/bpf.h | 30 ++++++++++++++++-
>  net/core/filter.c        | 73 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 102 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 6f68438aa4ed..20baee7b2219 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -2713,6 +2713,33 @@ union bpf_attr {
>   *		**-EPERM** if no permission to send the *sig*.
>   *
>   *		**-EAGAIN** if bpf program can try again.
> + *
> + * s64 bpf_tcp_gen_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
> + *	Description
> + *		Try to issue a SYN cookie for the packet with corresponding
> + *		IP/TCP headers, *iph* and *th*, on the listening socket in *sk*.
> + *
> + *		*iph* points to the start of the IPv4 or IPv6 header, while
> + *		*iph_len* contains **sizeof**\ (**struct iphdr**) or
> + *		**sizeof**\ (**struct ip6hdr**).
> + *
> + *		*th* points to the start of the TCP header, while *th_len*
> + *		contains the length of the TCP header.
> + *
> + *	Return
> + *		On success, lower 32 bits hold the generated SYN cookie in
> + *		followed by 16 bits which hold the MSS value for that cookie,
> + *		and the top 16 bits are unused.
> + *
> + *		On failure, the returned value is one of the following:
> + *
> + *		**-EINVAL** SYN cookie cannot be issued due to error
> + *
> + *		**-ENOENT** SYN cookie should not be issued (no SYN flood)
> + *
> + *		**-ENOTSUPP** kernel configuration does not enable SYN
> cookies

nit: This should be EOPNOTSUPP - the other one is for NFS...

> + *
> + *		**-EPROTONOSUPPORT** IP packet version is not 4 or 6
>   */
>  #define __BPF_FUNC_MAPPER(FN)		\
>  	FN(unspec),			\
> @@ -2824,7 +2851,8 @@ union bpf_attr {
>  	FN(strtoul),			\
>  	FN(sk_storage_get),		\
>  	FN(sk_storage_delete),		\
> -	FN(send_signal),
> +	FN(send_signal),		\
> +	FN(tcp_gen_syncookie),
>  
>  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
>   * function eBPF program intends to call
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 47f6386fb17a..92114271eff6 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -5850,6 +5850,75 @@ static const struct bpf_func_proto bpf_tcp_check_syncookie_proto = {
>  	.arg5_type	= ARG_CONST_SIZE,
>  };
>  
> +BPF_CALL_5(bpf_tcp_gen_syncookie, struct sock *, sk, void *, iph, u32, iph_len,
> +	   struct tcphdr *, th, u32, th_len)
> +{
> +#ifdef CONFIG_SYN_COOKIES
> +	u32 cookie;
> +	u16 mss;
> +
> +	if (unlikely(th_len < sizeof(*th) || th_len != th->doff * 4))
> +		return -EINVAL;
> +
> +	if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN)
> +		return -EINVAL;
> +
> +	if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies)
> +		return -ENOENT;
> +
> +	if (!th->syn || th->ack || th->fin || th->rst)
> +		return -EINVAL;
> +
> +	if (unlikely(iph_len < sizeof(struct iphdr)))
> +		return -EINVAL;
> +
> +	/* Both struct iphdr and struct ipv6hdr have the version field at the
> +	 * same offset so we can cast to the shorter header (struct iphdr).
> +	 */
> +	switch (((struct iphdr *)iph)->version) {
> +	case 4:
> +		if (sk->sk_family == AF_INET6 && sk->sk_ipv6only)
> +			return -EINVAL;
> +
> +		mss = tcp_v4_get_syncookie(sk, iph, th, &cookie);
> +		break;
> +
> +#if IS_BUILTIN(CONFIG_IPV6)
> +	case 6:
> +		if (unlikely(iph_len < sizeof(struct ipv6hdr)))
> +			return -EINVAL;
> +
> +		if (sk->sk_family != AF_INET6)
> +			return -EINVAL;
> +
> +		mss = tcp_v6_get_syncookie(sk, iph, th, &cookie);
> +		break;
> +#endif /* CONFIG_IPV6 */
> +
> +	default:
> +		return -EPROTONOSUPPORT;
> +	}
> +	if (mss <= 0)
> +		return -ENOENT;
> +
> +	return cookie | ((u64)mss << 32);
> +#else
> +	return -ENOTSUPP;

See above

> +#endif /* CONFIG_SYN_COOKIES */
> +}
> +
> +static const struct bpf_func_proto bpf_tcp_gen_syncookie_proto = {
> +	.func		= bpf_tcp_gen_syncookie,
> +	.gpl_only	= true, /* __cookie_v*_init_sequence() is GPL */
> +	.pkt_access	= true,
> +	.ret_type	= RET_INTEGER,
> +	.arg1_type	= ARG_PTR_TO_SOCK_COMMON,
> +	.arg2_type	= ARG_PTR_TO_MEM,
> +	.arg3_type	= ARG_CONST_SIZE,
> +	.arg4_type	= ARG_PTR_TO_MEM,
> +	.arg5_type	= ARG_CONST_SIZE,
> +};
> +
>  #endif /* CONFIG_INET */
>  
>  bool bpf_helper_changes_pkt_data(void *func)
> @@ -6135,6 +6204,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
>  		return &bpf_tcp_check_syncookie_proto;
>  	case BPF_FUNC_skb_ecn_set_ce:
>  		return &bpf_skb_ecn_set_ce_proto;
> +	case BPF_FUNC_tcp_gen_syncookie:
> +		return &bpf_tcp_gen_syncookie_proto;
>  #endif
>  	default:
>  		return bpf_base_func_proto(func_id);
> @@ -6174,6 +6245,8 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
>  		return &bpf_xdp_skc_lookup_tcp_proto;
>  	case BPF_FUNC_tcp_check_syncookie:
>  		return &bpf_tcp_check_syncookie_proto;
> +	case BPF_FUNC_tcp_gen_syncookie:
> +		return &bpf_tcp_gen_syncookie_proto;
>  #endif
>  	default:
>  		return bpf_base_func_proto(func_id);
> -- 
> 2.22.0.657.g960e92d24f-goog

  reply	other threads:[~2019-07-23 12:33 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-23  0:20 [bpf-next 0/6] Introduce a BPF helper to generate SYN cookies Petar Penkov
2019-07-23  0:20 ` [bpf-next 1/6] tcp: tcp_syn_flood_action read port from socket Petar Penkov
2019-07-23  0:20 ` [bpf-next 2/6] tcp: add skb-less helpers to retrieve SYN cookie Petar Penkov
2019-07-24  6:05   ` kbuild test robot
2019-07-24  6:19   ` kbuild test robot
2019-07-23  0:20 ` [bpf-next 3/6] bpf: add bpf_tcp_gen_syncookie helper Petar Penkov
2019-07-23 12:33   ` Toke Høiland-Jørgensen [this message]
2019-07-24  0:15     ` Petar Penkov
2019-07-23  0:20 ` [bpf-next 4/6] bpf: sync bpf.h to tools/ Petar Penkov
2019-07-23  0:20 ` [bpf-next 5/6] selftests/bpf: bpf_tcp_gen_syncookie->bpf_helpers Petar Penkov
2019-07-23  0:20 ` [bpf-next 6/6] selftests/bpf: add test for bpf_tcp_gen_syncookie Petar Penkov
2019-07-23  9:37   ` Lorenz Bauer
2019-07-23 20:46     ` Alexei Starovoitov
2019-07-23  6:30 ` [bpf-next 0/6] Introduce a BPF helper to generate SYN cookies Eric Dumazet
2019-07-23 10:27 ` Lorenz Bauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8736ix3p8h.fsf@toke.dk \
    --to=toke@redhat.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=lmb@cloudflare.com \
    --cc=netdev@vger.kernel.org \
    --cc=ppenkov.kernel@gmail.com \
    --cc=ppenkov@google.com \
    --cc=sdf@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.