From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ECC22C43381 for ; Fri, 22 Feb 2019 09:51:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BA7D12081B for ; Fri, 22 Feb 2019 09:51:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b="mmGu1h25" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726632AbfBVJvY (ORCPT ); Fri, 22 Feb 2019 04:51:24 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:52642 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726497AbfBVJvY (ORCPT ); Fri, 22 Feb 2019 04:51:24 -0500 Received: by mail-wm1-f68.google.com with SMTP id m1so1368298wml.2 for ; Fri, 22 Feb 2019 01:51:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hJp3Etgjs7BX5g0Sj3Lm+2SfD3AP7bgFHYpRb07PyxM=; b=mmGu1h25GhY8D0peEoIN+67RfVT7DPKqny7Z+BUvuvmRGyPiy/lfDyTEsy/H2bhLtR 8dP/tqR+4kc9AmQV3nZChycfyXmaBDnrlcNiUtVeK6/BdJjJLiz+iO1HdaYbaH470+l+ RJEIDe917foeq46LyjUwqkBXxMx5C9p52l8P4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hJp3Etgjs7BX5g0Sj3Lm+2SfD3AP7bgFHYpRb07PyxM=; b=cFoAg32xLKZtrES5V9wpLehF60M27tVeRAiHMUChvVAay5X8fmXtV3u5/u5Oz2K830 z+NVzIbnI1GAYqK58L2dwRYTBtVEPsbnDswxih2fl6UjVJ/nfnjyOqCMix1EkNn4Sz3v ekP7f4fyIVlfSU//Wm2vQFDwv95dMEiaG0mM5+YJjw6uiRkYdLkp5DSWlirkvw/iBlb1 asP4XIGcPvEm4olJ73JITnfNKf2nKjYH1sb7wI2Z00n69QpcOPjqr0359Q8/gDZDsLva JzL8AArHpQmhnVzkkcEl2+LRZVZ+0tY+OAW+IZh9SgaESpZu3bRUzfBlqbjjxfg91vJH u2PQ== X-Gm-Message-State: AHQUAuaf0tEx6LtpeTwuvCnCB8W/WEGPVDrJ0l4hPmT2R/PAs+gVqwgO bD3F02Zb/2x4lTsSIKBadiD09g== X-Google-Smtp-Source: AHgI3IbDX14s1Qa9IejxiKCB9lsaxcPWczg+YpYw342H2mf27uBu+cRjDD3N/TSLxBnaCoKs5DufRw== X-Received: by 2002:a1c:a756:: with SMTP id q83mr1854897wme.8.1550829080983; Fri, 22 Feb 2019 01:51:20 -0800 (PST) Received: from localhost.localdomain (9.6.e.f.2.f.3.d.e.1.8.a.3.e.5.2.0.0.0.0.3.c.c.0.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:cc3:0:25e3:a81e:d3f2:fe69]) by smtp.gmail.com with ESMTPSA id f68sm2680492wmg.5.2019.02.22.01.51.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 22 Feb 2019 01:51:20 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, netdev@vger.kernel.org Cc: linux-api@vger.kernel.org, Lorenz Bauer Subject: [PATCH 1/3] bpf: add helper to check for a valid SYN cookie Date: Fri, 22 Feb 2019 09:50:55 +0000 Message-Id: <20190222095057.9442-2-lmb@cloudflare.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190222095057.9442-1-lmb@cloudflare.com> References: <20190222095057.9442-1-lmb@cloudflare.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Using bpf_sk_lookup_tcp it's possible to ascertain whether a packet belongs to a known connection. However, there is one corner case: no sockets are created if SYN cookies are active. This means that the final ACK in the 3WHS is misclassified. Using the helper, we can look up the listening socket via bpf_sk_lookup_tcp and then check whether a packet is a valid SYN cookie ACK. Signed-off-by: Lorenz Bauer --- include/uapi/linux/bpf.h | 18 ++++++++++- net/core/filter.c | 68 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index bcdd2474eee7..bc2af87e9621 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2359,6 +2359,21 @@ union bpf_attr { * Return * A **struct bpf_tcp_sock** pointer on success, or NULL in * case of failure. + * + * int bpf_sk_check_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len) + * Description + * Check whether iph and th contain a valid SYN cookie ACK for + * 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 + * sizeof(struct tcphdr). + * + * Return + * 0 if iph and th are a valid SYN cookie ACK, or a negative error + * otherwise. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2457,7 +2472,8 @@ union bpf_attr { FN(spin_lock), \ FN(spin_unlock), \ FN(sk_fullsock), \ - FN(tcp_sock), + FN(tcp_sock), \ + FN(sk_check_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 85749f6ec789..9e68897cc7ed 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -5426,6 +5426,70 @@ static const struct bpf_func_proto bpf_tcp_sock_proto = { .arg1_type = ARG_PTR_TO_SOCK_COMMON, }; +BPF_CALL_5(bpf_sk_check_syncookie, struct sock *, sk, void *, iph, u32, iph_len, + struct tcphdr *, th, u32, th_len) +{ +#if IS_ENABLED(CONFIG_SYN_COOKIES) + u32 cookie; + int ret; + + if (unlikely(th_len < sizeof(*th))) + return -EINVAL; + + /* sk_listener() allows TCP_NEW_SYN_RECV, which makes no sense here. */ + if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN) + return -EINVAL; + + if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies) + return -EINVAL; + + if (!th->ack || th->rst) + return -ENOENT; + + cookie = ntohl(th->ack_seq) - 1; + + switch (sk->sk_family) { + case AF_INET: + if (unlikely(iph_len < sizeof(struct iphdr))) + return -EINVAL; + + ret = __cookie_v4_check((struct iphdr *)iph, th, cookie); + break; + +#if IS_ENABLED(CONFIG_IPV6) + case AF_INET6: + if (unlikely(iph_len < sizeof(struct ipv6hdr))) + return -EINVAL; + + ret = __cookie_v6_check((struct ipv6hdr *)iph, th, cookie); + break; +#endif /* CONFIG_IPV6 */ + + default: + return -EPROTONOSUPPORT; + } + + if (ret > 0) + return 0; + + return -ENOENT; +#else + return -ENOTSUP; +#endif +} + +static const struct bpf_func_proto bpf_sk_check_syncookie_proto = { + .func = bpf_sk_check_syncookie, + .gpl_only = true, + .pkt_access = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_SOCKET, + .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) @@ -5678,6 +5742,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_sk_release_proto; case BPF_FUNC_tcp_sock: return &bpf_tcp_sock_proto; + case BPF_FUNC_sk_check_syncookie: + return &bpf_sk_check_syncookie_proto; #endif default: return bpf_base_func_proto(func_id); @@ -5713,6 +5779,8 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_xdp_sk_lookup_tcp_proto; case BPF_FUNC_sk_release: return &bpf_sk_release_proto; + case BPF_FUNC_sk_check_syncookie: + return &bpf_sk_check_syncookie_proto; #endif default: return bpf_base_func_proto(func_id); -- 2.19.1