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.9 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_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable 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 5523CC33CA4 for ; Fri, 10 Jan 2020 10:50:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2C2072082E for ; Fri, 10 Jan 2020 10:50:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b="O5LOnDj+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727649AbgAJKus (ORCPT ); Fri, 10 Jan 2020 05:50:48 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:34082 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727631AbgAJKuj (ORCPT ); Fri, 10 Jan 2020 05:50:39 -0500 Received: by mail-wr1-f67.google.com with SMTP id t2so1370474wrr.1 for ; Fri, 10 Jan 2020 02:50:37 -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=oiCVl4px+tKVEh+6rXZ/+jXk8tt2rRze7absviz4v7k=; b=O5LOnDj+g+7Y/USSVr6fszlZDvyPmhsMiC1zYKPUEXhnol6X3N8Cy701W/szF3qfEE EEjvvkNnMuxbU44TJSlZAf1wjLHBpqEQ7yz3BBK0q8CufllB9k0Jt2d8xwx81HB6LaNb +ORFYNl1mlyk04iID0KB4SLIX3heGXR0P8uuU= 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=oiCVl4px+tKVEh+6rXZ/+jXk8tt2rRze7absviz4v7k=; b=lt/s2Kj4L12iZsJWk709bUdE0svVjpz04MXnUGf2Kb55CUGbcwVLvuuyFB88X4SRPH 5VHX3ExnhUhcNYwXIIhRtTD5DD5fYltrlaafm+tpvF4Qxdys07qSqQjOo346dKn8QQW0 w5ujJPSUV/ozf/I0UTDTl70Jmc+PHJv/BqmhFgqUJeo6peIoWHBAXzNcROzF7It2Tu4T x0oo4l7dD1XRFX4cY7InbNAuzaCF8ZiKfXf5WmShjXXfDf4f6CwO9eurT+I1jzGXH14c czMfbOjqM1rvL3LbWAl7LaY2/eYVnNTOa4+cZ+KsQjON3k62rk4oI3uHd3vgy9U7LlL7 DIlw== X-Gm-Message-State: APjAAAUEWurQTBQWUCSMH71LS/tRRXfcEYugI4Cc4MbWDH5DL8XTa8f9 I9vZ0h3+gckAaXKWx6YxsNw/TsC0efAPvg== X-Google-Smtp-Source: APXvYqyYdmyJL0QAvkRZyyiYEHv2c1mJkjDPY33o7SN4gbE5f+WVlgof3s8G+TenFNPchalYjqexsw== X-Received: by 2002:adf:f491:: with SMTP id l17mr2794568wro.149.1578653436241; Fri, 10 Jan 2020 02:50:36 -0800 (PST) Received: from cloudflare.com ([176.221.114.230]) by smtp.gmail.com with ESMTPSA id y17sm1763597wma.36.2020.01.10.02.50.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jan 2020 02:50:35 -0800 (PST) From: Jakub Sitnicki To: bpf@vger.kernel.org Cc: netdev@vger.kernel.org, kernel-team@cloudflare.com, Eric Dumazet , John Fastabend , Lorenz Bauer , Martin KaFai Lau Subject: [PATCH bpf-next v2 05/11] bpf, sockmap: Allow inserting listening TCP sockets into sockmap Date: Fri, 10 Jan 2020 11:50:21 +0100 Message-Id: <20200110105027.257877-6-jakub@cloudflare.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200110105027.257877-1-jakub@cloudflare.com> References: <20200110105027.257877-1-jakub@cloudflare.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org In order for sockmap type to become a generic collection for storing TCP sockets we need to loosen the checks during map update, while tightening the checks in redirect helpers. Currently sockmap requires the TCP socket to be in established state (or transitioning out of SYN_RECV into established state when done from BPF), which prevents inserting listening sockets. Change the update pre-checks so that the socket can also be in listening state. If the state is not white-listed, return -EINVAL to be consistent with REUSEPORT_SOCKARRY map type. Since it doesn't make sense to redirect with sockmap to listening sockets, add appropriate socket state checks to BPF redirect helpers too. Signed-off-by: Jakub Sitnicki --- net/core/sock_map.c | 46 ++++++++++++++++++++----- tools/testing/selftests/bpf/test_maps.c | 6 +--- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/net/core/sock_map.c b/net/core/sock_map.c index eb114ee419b6..99daea502508 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -396,6 +396,23 @@ static bool sock_map_sk_is_suitable(const struct sock *sk) sk->sk_protocol == IPPROTO_TCP; } +/* Is sock in a state that allows inserting into the map? + * SYN_RECV is needed for updates on BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB. + */ +static bool sock_map_update_okay(const struct sock *sk) +{ + return (1 << sk->sk_state) & (TCPF_ESTABLISHED | + TCPF_SYN_RECV | + TCPF_LISTEN); +} + +/* Is sock in a state that allows redirecting into it? */ +static bool sock_map_redirect_okay(const struct sock *sk) +{ + return (1 << sk->sk_state) & (TCPF_ESTABLISHED | + TCPF_SYN_RECV); +} + static int sock_map_update_elem(struct bpf_map *map, void *key, void *value, u64 flags) { @@ -413,11 +430,14 @@ static int sock_map_update_elem(struct bpf_map *map, void *key, ret = -EINVAL; goto out; } - if (!sock_map_sk_is_suitable(sk) || - sk->sk_state != TCP_ESTABLISHED) { + if (!sock_map_sk_is_suitable(sk)) { ret = -EOPNOTSUPP; goto out; } + if (!sock_map_update_okay(sk)) { + ret = -EINVAL; + goto out; + } sock_map_sk_acquire(sk); ret = sock_map_update_common(map, idx, sk, flags); @@ -433,6 +453,7 @@ BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, sops, WARN_ON_ONCE(!rcu_read_lock_held()); if (likely(sock_map_sk_is_suitable(sops->sk) && + sock_map_update_okay(sops->sk) && sock_map_op_okay(sops))) return sock_map_update_common(map, *(u32 *)key, sops->sk, flags); @@ -454,13 +475,17 @@ BPF_CALL_4(bpf_sk_redirect_map, struct sk_buff *, skb, struct bpf_map *, map, u32, key, u64, flags) { struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); + struct sock *sk; if (unlikely(flags & ~(BPF_F_INGRESS))) return SK_DROP; - tcb->bpf.flags = flags; - tcb->bpf.sk_redir = __sock_map_lookup_elem(map, key); - if (!tcb->bpf.sk_redir) + + sk = __sock_map_lookup_elem(map, key); + if (!sk || !sock_map_redirect_okay(sk)) return SK_DROP; + + tcb->bpf.flags = flags; + tcb->bpf.sk_redir = sk; return SK_PASS; } @@ -477,12 +502,17 @@ const struct bpf_func_proto bpf_sk_redirect_map_proto = { BPF_CALL_4(bpf_msg_redirect_map, struct sk_msg *, msg, struct bpf_map *, map, u32, key, u64, flags) { + struct sock *sk; + if (unlikely(flags & ~(BPF_F_INGRESS))) return SK_DROP; - msg->flags = flags; - msg->sk_redir = __sock_map_lookup_elem(map, key); - if (!msg->sk_redir) + + sk = __sock_map_lookup_elem(map, key); + if (!sk || !sock_map_redirect_okay(sk)) return SK_DROP; + + msg->flags = flags; + msg->sk_redir = sk; return SK_PASS; } diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c index 02eae1e864c2..c6766b2cff85 100644 --- a/tools/testing/selftests/bpf/test_maps.c +++ b/tools/testing/selftests/bpf/test_maps.c @@ -756,11 +756,7 @@ static void test_sockmap(unsigned int tasks, void *data) /* Test update without programs */ for (i = 0; i < 6; i++) { err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); - if (i < 2 && !err) { - printf("Allowed update sockmap '%i:%i' not in ESTABLISHED\n", - i, sfd[i]); - goto out_sockmap; - } else if (i >= 2 && err) { + if (err) { printf("Failed noprog update sockmap '%i:%i'\n", i, sfd[i]); goto out_sockmap; -- 2.24.1