From patchwork Fri Feb 4 13:58:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guillaume Nault X-Patchwork-Id: 12735114 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8451DC433EF for ; Fri, 4 Feb 2022 13:58:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1359156AbiBDN6T (ORCPT ); Fri, 4 Feb 2022 08:58:19 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:51196 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233073AbiBDN6R (ORCPT ); Fri, 4 Feb 2022 08:58:17 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1643983097; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=PWpGiu67AiC3oE0/d+SzQJxNJGhbryomvnZcmmvtbDs=; b=XTzXLqp3VfV6eSQnYC4Vp+xUDdeVRX15eToviKssZpfnuOp/ZcMQ9gmX1p3JtZ1F5DrkvQ VwAl8YSlUWV+SgMwh2Oa/zJ409qOOFT5ZN2DG31Fdsd3KhUa2kzh2aDNFcubsYjWNErjpD PdqnLHvmJdsHzxv7OGJlRcslMqW7OW4= Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-372-AQemVu3CMgm9hL064MxcUA-1; Fri, 04 Feb 2022 08:58:16 -0500 X-MC-Unique: AQemVu3CMgm9hL064MxcUA-1 Received: by mail-wr1-f70.google.com with SMTP id j21-20020adfa555000000b001db55dd5a1dso2057410wrb.15 for ; Fri, 04 Feb 2022 05:58:16 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=PWpGiu67AiC3oE0/d+SzQJxNJGhbryomvnZcmmvtbDs=; b=eyzqsQOmwdTDoh/obdhEyNs9tX12519SpkdpwXRNnR4SA5riEAA4/H+5/B2m/hA4Bz E9fNG++ef+o805CxD4DFPem6gbCW2ta+YLhz92+0BjnpjyhO3JMjBh+hVJ51RAPj7JM2 apVNWa8k6Dmvc4blaFYa44uQ1M0Euyv9alhEA2QQMHYaEugu2WEHjqiddygRhyXX7RrK DotrjIKpkSSg12g7TtQ2B/2qBJPYc0ZEWRw1QYRI/PCOjmzRvv6NC93AaXTxB406XPVa u2bN1khwFPMx01SMhBIOdE8sZaRVRJASeSoF3T1235tEgjo1IR7xOmQ0Suq/IbhOFp8g 5TBQ== X-Gm-Message-State: AOAM533TOKoSVBaiNk7z84+4g61v9T5xKSV3+dCiwVwpB9QbNjpvTbQP SRBZDF2xHJSh/iGSWTLuaDkdQguJhyJJ+5j65UpvQSufW+i8lTDNm56BHPQ1FhBtCe4m7vBw4SM V953T7xncKhAm/xv6XXglsMit5W/S X-Received: by 2002:a05:600c:19ce:: with SMTP id u14mr2370014wmq.92.1643983094678; Fri, 04 Feb 2022 05:58:14 -0800 (PST) X-Google-Smtp-Source: ABdhPJz4+OfqDCsqaDt3ntATt5WQklrRMhtQlr+cjbb0SsYSl9Q+yfNo3bkBMxOst9TZqctPHUn0sA== X-Received: by 2002:a05:600c:19ce:: with SMTP id u14mr2370003wmq.92.1643983094424; Fri, 04 Feb 2022 05:58:14 -0800 (PST) Received: from pc-4.home (2a01cb058918ce00dd1a5a4f9908f2d5.ipv6.abo.wanadoo.fr. [2a01:cb05:8918:ce00:dd1a:5a4f:9908:f2d5]) by smtp.gmail.com with ESMTPSA id c13sm2049792wrv.24.2022.02.04.05.58.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Feb 2022 05:58:14 -0800 (PST) Date: Fri, 4 Feb 2022 14:58:11 +0100 From: Guillaume Nault To: David Miller , Jakub Kicinski Cc: netdev@vger.kernel.org, Hideaki YOSHIFUJI , David Ahern , Toke =?iso-8859-1?q?H=F8iland-J=F8rgensen?= , Shuah Khan , linux-kselftest@vger.kernel.org, Russell Strong , Dave Taht Subject: [PATCH net-next 1/4] ipv6: Define dscp_t and stop taking ECN bits into account in fib6-rules Message-ID: <2b4f1d6045d8885cf70a113f194795cf3e1ef453.1643981839.git.gnault@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Define a dscp_t type and its appropriate helpers that ensure ECN bits are not taken into account when handling DSCP. Use this new type to replace the tclass field of struct fib6_rule, so that fib6-rules don't get influenced by ECN bits anymore. Before this patch, fib6-rules didn't make any distinction between the DSCP and ECN bits. Therefore, rules specifying a DSCP (tos or dsfield options in iproute2) stopped working as soon a packets had at least one of its ECN bits set (as a work around one could create four rules for each DSCP value to match, one for each possible ECN value). After this patch fib6-rules only compare the DSCP bits. ECN doesn't influence the result anymore. Also, fib6-rules now must have the ECN bits cleared or they will be rejected. Signed-off-by: Guillaume Nault --- include/net/inet_dscp.h | 57 +++++++++++++++++++ include/net/ipv6.h | 6 ++ net/ipv6/fib6_rules.c | 19 +++++-- tools/testing/selftests/net/fib_rule_tests.sh | 30 +++++++++- 4 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 include/net/inet_dscp.h diff --git a/include/net/inet_dscp.h b/include/net/inet_dscp.h new file mode 100644 index 000000000000..72f250dffada --- /dev/null +++ b/include/net/inet_dscp.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * inet_dscp.h: helpers for handling differentiated services codepoints (DSCP) + * + * DSCP is defined in RFC 2474: + * + * 0 1 2 3 4 5 6 7 + * +---+---+---+---+---+---+---+---+ + * | DSCP | CU | + * +---+---+---+---+---+---+---+---+ + * + * DSCP: differentiated services codepoint + * CU: currently unused + * + * The whole DSCP + CU bits form the DS field. + * The DS field is also commonly called TOS or Traffic Class (for IPv6). + * + * Note: the CU bits are now used for Explicit Congestion Notification + * (RFC 3168). + */ + +#ifndef _INET_DSCP_H +#define _INET_DSCP_H + +#include + +/* Special type for storing DSCP values. + * + * A dscp_t variable stores a DS field with the CU (ECN) bits cleared. + * Using dscp_t allows to strictly separate DSCP and ECN bits, thus avoiding + * bugs where ECN bits are erroneously taken into account during FIB lookups + * or policy routing. + * + * Note: to get the real DSCP value contained in a dscp_t variable one would + * have to do a bit shift after calling inet_dscp_to_dsfield(). We could have + * a helper for that, but there's currently no users. + */ +typedef u8 __bitwise dscp_t; + +#define INET_DSCP_MASK 0xfc + +static inline dscp_t inet_dsfield_to_dscp(__u8 dsfield) +{ + return (__force dscp_t)(dsfield & INET_DSCP_MASK); +} + +static inline __u8 inet_dscp_to_dsfield(dscp_t dscp) +{ + return (__force __u8)dscp; +} + +static inline bool inet_validate_dscp(__u8 val) +{ + return !(val & ~INET_DSCP_MASK); +} + +#endif /* _INET_DSCP_H */ diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 082f30256f59..3d898eb6df9c 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -975,6 +976,11 @@ static inline u8 ip6_tclass(__be32 flowinfo) return ntohl(flowinfo & IPV6_TCLASS_MASK) >> IPV6_TCLASS_SHIFT; } +static inline dscp_t ip6_dscp(__be32 flowinfo) +{ + return inet_dsfield_to_dscp(ip6_tclass(flowinfo)); +} + static inline __be32 ip6_make_flowinfo(unsigned int tclass, __be32 flowlabel) { return htonl(tclass << IPV6_TCLASS_SHIFT) | flowlabel; diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index ec029c86ae06..e2a7b0059669 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -25,14 +26,14 @@ struct fib6_rule { struct fib_rule common; struct rt6key src; struct rt6key dst; - u8 tclass; + dscp_t dscp; }; static bool fib6_rule_matchall(const struct fib_rule *rule) { struct fib6_rule *r = container_of(rule, struct fib6_rule, common); - if (r->dst.plen || r->src.plen || r->tclass) + if (r->dst.plen || r->src.plen || r->dscp) return false; return fib_rule_matchall(rule); } @@ -323,7 +324,7 @@ INDIRECT_CALLABLE_SCOPE int fib6_rule_match(struct fib_rule *rule, return 0; } - if (r->tclass && r->tclass != ip6_tclass(fl6->flowlabel)) + if (r->dscp && r->dscp != ip6_dscp(fl6->flowlabel)) return 0; if (rule->ip_proto && (rule->ip_proto != fl6->flowi6_proto)) @@ -349,6 +350,13 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, struct net *net = sock_net(skb->sk); struct fib6_rule *rule6 = (struct fib6_rule *) rule; + if (!inet_validate_dscp(frh->tos)) { + NL_SET_ERR_MSG(extack, + "Invalid dsfield (tos): ECN bits must be 0"); + goto errout; + } + rule6->dscp = inet_dsfield_to_dscp(frh->tos); + if (rule->action == FR_ACT_TO_TBL && !rule->l3mdev) { if (rule->table == RT6_TABLE_UNSPEC) { NL_SET_ERR_MSG(extack, "Invalid table"); @@ -369,7 +377,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, rule6->src.plen = frh->src_len; rule6->dst.plen = frh->dst_len; - rule6->tclass = frh->tos; if (fib_rule_requires_fldissect(rule)) net->ipv6.fib6_rules_require_fldissect++; @@ -402,7 +409,7 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, if (frh->dst_len && (rule6->dst.plen != frh->dst_len)) return 0; - if (frh->tos && (rule6->tclass != frh->tos)) + if (frh->tos && inet_dscp_to_dsfield(rule6->dscp) != frh->tos) return 0; if (frh->src_len && @@ -423,7 +430,7 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->dst_len = rule6->dst.plen; frh->src_len = rule6->src.plen; - frh->tos = rule6->tclass; + frh->tos = inet_dscp_to_dsfield(rule6->dscp); if ((rule6->dst.plen && nla_put_in6_addr(skb, FRA_DST, &rule6->dst.addr)) || diff --git a/tools/testing/selftests/net/fib_rule_tests.sh b/tools/testing/selftests/net/fib_rule_tests.sh index 3b0489910422..d7a9ab3be1d3 100755 --- a/tools/testing/selftests/net/fib_rule_tests.sh +++ b/tools/testing/selftests/net/fib_rule_tests.sh @@ -114,10 +114,25 @@ fib_rule6_test_match_n_redirect() log_test $? 0 "rule6 del by pref: $description" } +fib_rule6_test_reject() +{ + local match="$1" + local rc + + $IP -6 rule add $match table $RTABLE 2>/dev/null + rc=$? + log_test $rc 2 "rule6 check: $match" + + if [ $rc -eq 0 ]; then + $IP -6 rule del $match table $RTABLE + fi +} + fib_rule6_test() { local getmatch local match + local cnt # setup the fib rule redirect route $IP -6 route add table $RTABLE default via $GW_IP6 dev $DEV onlink @@ -128,8 +143,21 @@ fib_rule6_test() match="from $SRC_IP6 iif $DEV" fib_rule6_test_match_n_redirect "$match" "$match" "iif redirect to table" + # Reject dsfield (tos) options which have ECN bits set + for cnt in $(seq 1 3); do + match="dsfield $cnt" + fib_rule6_test_reject "$match" + done + + # Don't take ECN bits into account when matching on dsfield match="tos 0x10" - fib_rule6_test_match_n_redirect "$match" "$match" "tos redirect to table" + for cnt in "0x10" "0x11" "0x12" "0x13"; do + # Using option 'tos' instead of 'dsfield' as old iproute2 + # versions don't support 'dsfield' in ip rule show. + getmatch="tos $cnt" + fib_rule6_test_match_n_redirect "$match" "$getmatch" \ + "$getmatch redirect to table" + done match="fwmark 0x64" getmatch="mark 0x64" From patchwork Fri Feb 4 13:58:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guillaume Nault X-Patchwork-Id: 12735115 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 27164C433F5 for ; Fri, 4 Feb 2022 13:58:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1359114AbiBDN6U (ORCPT ); Fri, 4 Feb 2022 08:58:20 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:58674 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1359154AbiBDN6T (ORCPT ); Fri, 4 Feb 2022 08:58:19 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1643983099; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=MBMyk3IZsR5ozoJLuOW+sHZ0Vu+57g26uCSnHB4yqHg=; b=RmWj8lULiS3JwegvZMNYJFj1sxEqzvUVCAkJtbD6aHTO6qHIbswmy7pyIAoK5G1r9aZpa+ U105yEcMDs5Gf0vdYO8TDU+Y88tN6z1mM6X3fL7nVXNYffeP8qcrkGw9q03QR7YGi9k+nd jQMzmeKds21n2DJSXC1ee7aNJ7ASpoA= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-173-NR5Q1XJAPs2Dta6bcj72lA-1; Fri, 04 Feb 2022 08:58:18 -0500 X-MC-Unique: NR5Q1XJAPs2Dta6bcj72lA-1 Received: by mail-wr1-f72.google.com with SMTP id c10-20020adfa30a000000b001d79c73b64bso2065692wrb.1 for ; Fri, 04 Feb 2022 05:58:17 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=MBMyk3IZsR5ozoJLuOW+sHZ0Vu+57g26uCSnHB4yqHg=; b=b+hi8gOirhvsL5C4Ezx84k2fpSwopDTi3vjo2vDLG4AdgS8VTko7WUVwZ/sao9loht oyL5QIPDLlCofd3gFoJwRP+e5w4jFyu40rlMuLoQn8Z61IjGTmglEvt1LgVolQ0zeD5O gOOpWVpp78Z/oVY9rR54lHko2gss0WL2iFxioOFbkOL9yRQxeuoLjnbdZc5oujPyZr9v vuiRb8aUTdOQLaduPq0Ey1k+ws75gI/xXUhgziJhwk/YjpGb6lwh1yTtURudL6HaY4kr rP1ha1N6bPDqj0kYl111sIz53W/otTyOxvpAOMPnJmK/oGQKOz4sGyZBHD8z1nqRIz9/ HaBQ== X-Gm-Message-State: AOAM533XI2cgwFyF+mjpY5DcZxrrMNm8w/2yVd/Bd/DAHyXvkqd9GHYQ L8nbm6n1pzAYPQPXNNO7RvdS44ZayJXN4eXqy43sr2qKyVY/safq1iVUY8Mf+UYog8ehqaCQ0eL NFBP5WdSWZ6uOvW4IhZkDzqZlCkr2 X-Received: by 2002:a05:6000:25c:: with SMTP id m28mr2505934wrz.511.1643983096746; Fri, 04 Feb 2022 05:58:16 -0800 (PST) X-Google-Smtp-Source: ABdhPJxwFnp0E5TKW9qae8qOTeJ2DC4Arzk0wVFQek4amDQpq4oIdfQziIY2s9OwcMQeIpq8RT1BUQ== X-Received: by 2002:a05:6000:25c:: with SMTP id m28mr2505922wrz.511.1643983096587; Fri, 04 Feb 2022 05:58:16 -0800 (PST) Received: from pc-4.home (2a01cb058918ce00dd1a5a4f9908f2d5.ipv6.abo.wanadoo.fr. [2a01:cb05:8918:ce00:dd1a:5a4f:9908:f2d5]) by smtp.gmail.com with ESMTPSA id bg26sm10366044wmb.48.2022.02.04.05.58.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Feb 2022 05:58:16 -0800 (PST) Date: Fri, 4 Feb 2022 14:58:14 +0100 From: Guillaume Nault To: David Miller , Jakub Kicinski Cc: netdev@vger.kernel.org, Hideaki YOSHIFUJI , David Ahern , Toke =?iso-8859-1?q?H=F8iland-J=F8rgensen?= , Shuah Khan , linux-kselftest@vger.kernel.org, Russell Strong , Dave Taht Subject: [PATCH net-next 2/4] ipv4: Stop taking ECN bits into account in fib4-rules Message-ID: <706ed5f33756ea0989373f1e312e248095d458d5.1643981839.git.gnault@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Use the new dscp_t type to replace the tos field of struct fib4_rule, so that fib4-rules consistently ignore ECN bits. Before this patch, fib4-rules did accept rules with the high order ECN bit set (but not the low order one). Also, it relied on its callers masking the ECN bits of ->flowi4_tos to prevent those from influencing the result. This was brittle and a few call paths still do the lookup without masking the ECN bits first. After this patch fib4-rules only compare the DSCP bits. ECN can't influence the result anymore, even if the caller didn't mask these bits. Also, fib4-rules now must have both ECN bits cleared or they will be rejected. Signed-off-by: Guillaume Nault --- net/ipv4/fib_rules.c | 18 ++++++----- tools/testing/selftests/net/fib_rule_tests.sh | 30 ++++++++++++++++++- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index e0b6c8b6de57..117c48571cf0 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,7 @@ struct fib4_rule { struct fib_rule common; u8 dst_len; u8 src_len; - u8 tos; + dscp_t dscp; __be32 src; __be32 srcmask; __be32 dst; @@ -49,7 +50,7 @@ static bool fib4_rule_matchall(const struct fib_rule *rule) { struct fib4_rule *r = container_of(rule, struct fib4_rule, common); - if (r->dst_len || r->src_len || r->tos) + if (r->dst_len || r->src_len || r->dscp) return false; return fib_rule_matchall(rule); } @@ -185,7 +186,7 @@ INDIRECT_CALLABLE_SCOPE int fib4_rule_match(struct fib_rule *rule, ((daddr ^ r->dst) & r->dstmask)) return 0; - if (r->tos && (r->tos != fl4->flowi4_tos)) + if (r->dscp && r->dscp != inet_dsfield_to_dscp(fl4->flowi4_tos)) return 0; if (rule->ip_proto && (rule->ip_proto != fl4->flowi4_proto)) @@ -225,10 +226,12 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, int err = -EINVAL; struct fib4_rule *rule4 = (struct fib4_rule *) rule; - if (frh->tos & ~IPTOS_TOS_MASK) { - NL_SET_ERR_MSG(extack, "Invalid tos"); + if (!inet_validate_dscp(frh->tos)) { + NL_SET_ERR_MSG(extack, + "Invalid dsfield (tos): ECN bits must be 0"); goto errout; } + rule4->dscp = inet_dsfield_to_dscp(frh->tos); /* split local/main if they are not already split */ err = fib_unmerge(net); @@ -270,7 +273,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, rule4->srcmask = inet_make_mask(rule4->src_len); rule4->dst_len = frh->dst_len; rule4->dstmask = inet_make_mask(rule4->dst_len); - rule4->tos = frh->tos; net->ipv4.fib_has_custom_rules = true; @@ -313,7 +315,7 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, if (frh->dst_len && (rule4->dst_len != frh->dst_len)) return 0; - if (frh->tos && (rule4->tos != frh->tos)) + if (frh->tos && inet_dscp_to_dsfield(rule4->dscp) != frh->tos) return 0; #ifdef CONFIG_IP_ROUTE_CLASSID @@ -337,7 +339,7 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, frh->dst_len = rule4->dst_len; frh->src_len = rule4->src_len; - frh->tos = rule4->tos; + frh->tos = inet_dscp_to_dsfield(rule4->dscp); if ((rule4->dst_len && nla_put_in_addr(skb, FRA_DST, rule4->dst)) || diff --git a/tools/testing/selftests/net/fib_rule_tests.sh b/tools/testing/selftests/net/fib_rule_tests.sh index d7a9ab3be1d3..4f70baad867d 100755 --- a/tools/testing/selftests/net/fib_rule_tests.sh +++ b/tools/testing/selftests/net/fib_rule_tests.sh @@ -215,10 +215,25 @@ fib_rule4_test_match_n_redirect() log_test $? 0 "rule4 del by pref: $description" } +fib_rule4_test_reject() +{ + local match="$1" + local rc + + $IP rule add $match table $RTABLE 2>/dev/null + rc=$? + log_test $rc 2 "rule4 check: $match" + + if [ $rc -eq 0 ]; then + $IP rule del $match table $RTABLE + fi +} + fib_rule4_test() { local getmatch local match + local cnt # setup the fib rule redirect route $IP route add table $RTABLE default via $GW_IP4 dev $DEV onlink @@ -234,8 +249,21 @@ fib_rule4_test() fib_rule4_test_match_n_redirect "$match" "$match" "iif redirect to table" ip netns exec testns sysctl -qw net.ipv4.ip_forward=0 + # Reject dsfield (tos) options which have ECN bits set + for cnt in $(seq 1 3); do + match="dsfield $cnt" + fib_rule4_test_reject "$match" + done + + # Don't take ECN bits into account when matching on dsfield match="tos 0x10" - fib_rule4_test_match_n_redirect "$match" "$match" "tos redirect to table" + for cnt in "0x10" "0x11" "0x12" "0x13"; do + # Using option 'tos' instead of 'dsfield' as old iproute2 + # versions don't support 'dsfield' in ip rule show. + getmatch="tos $cnt" + fib_rule4_test_match_n_redirect "$match" "$getmatch" \ + "$getmatch redirect to table" + done match="fwmark 0x64" getmatch="mark 0x64" From patchwork Fri Feb 4 13:58:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guillaume Nault X-Patchwork-Id: 12735116 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95A0CC433F5 for ; Fri, 4 Feb 2022 13:58:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1359172AbiBDN62 (ORCPT ); Fri, 4 Feb 2022 08:58:28 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:42056 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1359163AbiBDN6V (ORCPT ); Fri, 4 Feb 2022 08:58:21 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1643983101; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=huLoFadblEn2s3rt9PCLve07r8DRe9hm65RauLtf9Y8=; b=dlGE2ZyCPTnbdXXpZf/voWFK9TeQXQrFgW4MJVycGuC+rEvHh5t87C9ID67wxXpdYH3O6/ 1Av7kSqWDFF2uj3Wog2C5AIo5tgrqwOpwzAAeCCzzMR5pH8/WiQs9e1AZ5jrjKRz8pNPwm Igh3I7kOmtyAZAhhl9zc0gy1gGWYkbc= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-674-6wL5vuekOKyPAPqU-Ea4Kw-1; Fri, 04 Feb 2022 08:58:20 -0500 X-MC-Unique: 6wL5vuekOKyPAPqU-Ea4Kw-1 Received: by mail-wm1-f71.google.com with SMTP id l5-20020a05600c088500b0037b98300c70so592517wmp.5 for ; Fri, 04 Feb 2022 05:58:20 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=huLoFadblEn2s3rt9PCLve07r8DRe9hm65RauLtf9Y8=; b=JhzPZj0Ye2ddr3oQqMHHqfZ+piNnxoIM7dFMu8ubhcbWbn+lkXogHqN9+mPOp9Tl5i 2BA7//9miW9ezceKbThIgnA8lYM3ETzq6kEpJU+2ew+DAy+hbQs4egnZYK0ErmSpsR20 wznY88sPimtuh6ODGu0bxKA0/ewFuStMBVGiB8H50Edg+nOvWpkq0wi+1CO3fP723BoE EfsNJYHOshUccuCwQP4UUZC0sj664u96aNiX7SxEDr/Yngc9cKQ8tgWLp5PoYhpj7uff bX5YDzxlChZTiN05qCeF4UOAA6IHrv/BklfZT8f+QeoGftT99LIrVJpeU2FICTaYXkx0 ElOw== X-Gm-Message-State: AOAM533yX+GNKL3NGWLg7Skos+uFrRCKg8Id7LVtD8wFNMxaGG0A4foT nef2K/muj3l40SkHDy6SbqgnE3DQ0jEn6RQBJz7JshsbV1Kj4S1KUxXoJ8wLkUngZ6aRxNPpO8a JTllfW9K3M/Gx/srRlJ/14BXzpxsV X-Received: by 2002:adf:f750:: with SMTP id z16mr786426wrp.239.1643983099111; Fri, 04 Feb 2022 05:58:19 -0800 (PST) X-Google-Smtp-Source: ABdhPJz9n7xqbaODP/c2niZ8sZmsya6PVRtmFseh5p6sdFV0nfmo3BUQb4qtexbScYv/kP0iTRNYQg== X-Received: by 2002:adf:f750:: with SMTP id z16mr786414wrp.239.1643983098926; Fri, 04 Feb 2022 05:58:18 -0800 (PST) Received: from pc-4.home (2a01cb058918ce00dd1a5a4f9908f2d5.ipv6.abo.wanadoo.fr. [2a01:cb05:8918:ce00:dd1a:5a4f:9908:f2d5]) by smtp.gmail.com with ESMTPSA id o14sm2280445wry.104.2022.02.04.05.58.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Feb 2022 05:58:18 -0800 (PST) Date: Fri, 4 Feb 2022 14:58:16 +0100 From: Guillaume Nault To: David Miller , Jakub Kicinski Cc: netdev@vger.kernel.org, Hideaki YOSHIFUJI , David Ahern , Toke =?iso-8859-1?q?H=F8iland-J=F8rgensen?= , Shuah Khan , linux-kselftest@vger.kernel.org, Russell Strong , Dave Taht Subject: [PATCH net-next 3/4] ipv4: Reject routes specifying ECN bits in rtm_tos Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Use the new dscp_t type to replace the fc_tos field of fib_config, to ensure IPv4 routes aren't influenced by ECN bits when configured with non-zero rtm_tos. Before this patch, IPv4 routes specifying an rtm_tos with some of the ECN bits set were accepted. However they wouldn't work (never match) as IPv4 normally clears the ECN bits with IPTOS_RT_MASK before doing a FIB lookup (although a few buggy code paths don't). After this patch, IPv4 routes specifying an rtm_tos with any ECN bit set is rejected. Note: IPv6 routes ignore rtm_tos altogether, any rtm_tos is accepted, but treated as if it were 0. Signed-off-by: Guillaume Nault --- Shuah, FYI, this is the patch I was refering to in our discussion about testing invalid tos values: https://lore.kernel.org/netdev/20220202232555.GC15826@pc-4.home/ include/net/ip_fib.h | 3 +- net/ipv4/fib_frontend.c | 11 +++- net/ipv4/fib_trie.c | 7 ++- tools/testing/selftests/net/fib_tests.sh | 76 ++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 4 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index c4297704bbcb..6a82bcb8813b 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,7 @@ struct fib_config { u8 fc_dst_len; - u8 fc_tos; + dscp_t fc_dscp; u8 fc_protocol; u8 fc_scope; u8 fc_type; diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 4d61ddd8a0ec..c60e1d1ed2b0 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -735,8 +736,16 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, memset(cfg, 0, sizeof(*cfg)); rtm = nlmsg_data(nlh); + + if (!inet_validate_dscp(rtm->rtm_tos)) { + NL_SET_ERR_MSG(extack, + "Invalid dsfield (tos): ECN bits must be 0"); + err = -EINVAL; + goto errout; + } + cfg->fc_dscp = inet_dsfield_to_dscp(rtm->rtm_tos); + cfg->fc_dst_len = rtm->rtm_dst_len; - cfg->fc_tos = rtm->rtm_tos; cfg->fc_table = rtm->rtm_table; cfg->fc_protocol = rtm->rtm_protocol; cfg->fc_scope = rtm->rtm_scope; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 8060524f4256..d937eeebb812 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -1210,9 +1211,9 @@ int fib_table_insert(struct net *net, struct fib_table *tb, struct fib_info *fi; u8 plen = cfg->fc_dst_len; u8 slen = KEYLENGTH - plen; - u8 tos = cfg->fc_tos; u32 key; int err; + u8 tos; key = ntohl(cfg->fc_dst); @@ -1227,6 +1228,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, goto err; } + tos = inet_dscp_to_dsfield(cfg->fc_dscp); l = fib_find_node(t, &tp, key); fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority, tb->tb_id, false) : NULL; @@ -1703,8 +1705,8 @@ int fib_table_delete(struct net *net, struct fib_table *tb, struct key_vector *l, *tp; u8 plen = cfg->fc_dst_len; u8 slen = KEYLENGTH - plen; - u8 tos = cfg->fc_tos; u32 key; + u8 tos; key = ntohl(cfg->fc_dst); @@ -1715,6 +1717,7 @@ int fib_table_delete(struct net *net, struct fib_table *tb, if (!l) return -ESRCH; + tos = inet_dscp_to_dsfield(cfg->fc_dscp); fa = fib_find_alias(&l->leaf, slen, tos, 0, tb->tb_id, false); if (!fa) return -ESRCH; diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh index 996af1ae3d3d..bb73235976b3 100755 --- a/tools/testing/selftests/net/fib_tests.sh +++ b/tools/testing/selftests/net/fib_tests.sh @@ -1447,6 +1447,81 @@ ipv4_local_rt_cache() log_test $? 0 "Cached route removed from VRF port device" } +ipv4_rt_dsfield() +{ + echo + echo "IPv4 route with dsfield tests" + + run_cmd "$IP route flush 172.16.102.0/24" + + # New routes should reject dsfield options that interfere with ECN + run_cmd "$IP route add 172.16.102.0/24 dsfield 0x01 via 172.16.101.2" + log_test $? 2 "Reject route with dsfield 0x01" + + run_cmd "$IP route add 172.16.102.0/24 dsfield 0x02 via 172.16.101.2" + log_test $? 2 "Reject route with dsfield 0x02" + + run_cmd "$IP route add 172.16.102.0/24 dsfield 0x03 via 172.16.101.2" + log_test $? 2 "Reject route with dsfield 0x03" + + # A generic route that doesn't take DSCP into account + run_cmd "$IP route add 172.16.102.0/24 via 172.16.101.2" + + # A more specific route for DSCP 0x10 + run_cmd "$IP route add 172.16.102.0/24 dsfield 0x10 via 172.16.103.2" + + # DSCP 0x10 should match the specific route, no matter the ECN bits + $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \ + grep -q "via 172.16.103.2" + log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT" + + $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \ + grep -q "via 172.16.103.2" + log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)" + + $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \ + grep -q "via 172.16.103.2" + log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)" + + $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \ + grep -q "via 172.16.103.2" + log_test $? 0 "IPv4 route with DSCP and ECN:CE" + + # Unknown DSCP should match the generic route, no matter the ECN bits + $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT" + + $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)" + + $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)" + + $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE" + + # Null DSCP should match the generic route, no matter the ECN bits + $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT" + + $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)" + + $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)" + + $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \ + grep -q "via 172.16.101.2" + log_test $? 0 "IPv4 route with no DSCP and ECN:CE" +} + ipv4_route_test() { route_setup @@ -1454,6 +1529,7 @@ ipv4_route_test() ipv4_rt_add ipv4_rt_replace ipv4_local_rt_cache + ipv4_rt_dsfield route_cleanup }