Received: by 2002:a05:6a10:9afc:0:0:0:0 with SMTP id t28csp1046680pxm; Wed, 23 Feb 2022 16:46:28 -0800 (PST) X-Google-Smtp-Source: ABdhPJw/9XCKWtqTSRRuG24KXlHgVY3mC9SgdEBS3MkIcv/FHcyX4R6qDHdTa74wVfJVNWzbrNET X-Received: by 2002:a17:902:e747:b0:150:2a7:735e with SMTP id p7-20020a170902e74700b0015002a7735emr402666plf.32.1645663587829; Wed, 23 Feb 2022 16:46:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1645663587; cv=none; d=google.com; s=arc-20160816; b=pIhgD1qtgvnJAOTk9kBCl54CqvC3ApOOJc9rhMpVpQ4/SQ8P3JxLdVOY3mE01gbpYw nZF0nk7jAxKJCmjsGLBVMIEiX16FJgOEDZUt9510ENHM7Hr/C/zoE+foY1Tzm+egUUSW jTSy7cygApgH4MMPmCzTkj+iHK2+KPAyb/4LJjMzd08L4yGlzWu/g8z6b7JH1E8Wb8Zy Aqm63nediQp63zo1i8t5LKXTuABGunwuZtvgHJU41dYCeq6NKA08L02sININQ5UFglhh jw8ZqTRmw3Qn1I7W91GkVFeeYW2NuHQAISZh47BKLOvFj+xWA8mOJuTI1sSpVmMTMeod Fy/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=AcFlk5NLo4FXRllcKSpbB7UHXIeMkr/gx8QJaFZjkzo=; b=hJGFbZ4RijJ2ruNqjaOVmpycLpSvGdYDX9m+reSr2lYW5dWGOrPJ4ww+UASX48EVzV 5jO8W1jgAZnZ6KbKXP3RY7thljAFdFyxFNVW02jg0ob1okTKkrFyeqaMgRYUEGtr/PBP Ho9lqKu0rwTwVTW1kvyG8wHX4//TE0mgoOUobxpQFfErJACAZOxubGpRDfCR84Y1s7S0 WCVZl5Upckgvg49F8fhpWNiPVYv2LiXo5zNGA73gWIxMpOeXErJTc6cx72AqT3e3kLOk Lc/JTth8VitIRrTShliDYRlZfCDTWbMBISRQBpG64UDRosgIR1v20YUKMOIzKGHt+3iP 4r/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@arista.com header.s=google header.b=hs1THwKZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=arista.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id c194si963597pfc.292.2022.02.23.16.46.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Feb 2022 16:46:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@arista.com header.s=google header.b=hs1THwKZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=arista.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EBFB6C6238; Wed, 23 Feb 2022 16:42:29 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236147AbiBWMST (ORCPT + 99 others); Wed, 23 Feb 2022 07:18:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240420AbiBWMSS (ORCPT ); Wed, 23 Feb 2022 07:18:18 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F59C9E9E4 for ; Wed, 23 Feb 2022 04:17:50 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id u1so39265737wrg.11 for ; Wed, 23 Feb 2022 04:17:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=AcFlk5NLo4FXRllcKSpbB7UHXIeMkr/gx8QJaFZjkzo=; b=hs1THwKZ7T7H2frd5gsuHEYyP1/BhO3xo0caGPCDJJWJ5q/Jc+KI1o+Vl6YVLJP/Cx GheQEFQT4vV81r89PzsBIJQdiAcG7xgA60FgJFdktV3giInXemsXl67lui9azxEVlvh3 u5nloWrtzrTCqSTsHkUpd37NlzlcbUuFL2mxf72HThDjJ/o+A4T6p2CTyw7Fk3pO9U3t 3h7p9QHrBWxc3vm6xwZMCtag5KUbgcqTsyWh/OCAKocyrX9vCHjUp0myhJ8pQ0r9e92M mYPQhsPv6f1mJeP+YSae6lAaE8mgRwoymwifANPE2epgYZjo5+x38Ry+a/SCR/8x3uEo ++lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=AcFlk5NLo4FXRllcKSpbB7UHXIeMkr/gx8QJaFZjkzo=; b=P0Go9H9VBq/djZ4duN8gzV2rsWFY/inXvo8AlfIQkA5bFInR5zh89q5qrJsvFlESir LtHhfoQjGo5zt8QT0f9zqp7AkiMVdmW1sxuhMkSyGwSSZ6VEJbhJ7BZjduR89/TBq7hZ TFod2kARcUDGP/J0r5A+ZFaX+FqRu4TLSY76/bvsg8aD/pfFaE/3hdHdlsdgRUochbOI Z5oZC/4r+6bbCdaiX59rYtUQxQkBu0kUcBDHOablORVunLGgIQbR+UrVL9czeyB4R1CN 5s8afPUaiYLqlp7jx3mNqgPlqwR38qdHjxKOFwe6jsUzfw2DR7Ir31JGmb9RUOejpY5u sBTQ== X-Gm-Message-State: AOAM5302xbgI6rXzxQ1JV5IoUiKR21qqJK4J+rqmgc6pc17tO+tRfAJR V/KmAK2DTJvDeGdE8LzCLfe+7r1pf43NyA== X-Received: by 2002:a5d:64ac:0:b0:1e7:1415:2548 with SMTP id m12-20020a5d64ac000000b001e714152548mr23575408wrp.267.1645618668611; Wed, 23 Feb 2022 04:17:48 -0800 (PST) Received: from localhost.localdomain ([2a02:8084:e84:2480:228:f8ff:fe6f:83a8]) by smtp.gmail.com with ESMTPSA id u15sm68958630wrs.18.2022.02.23.04.17.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Feb 2022 04:17:48 -0800 (PST) From: Dmitry Safonov To: linux-kernel@vger.kernel.org Cc: Dmitry Safonov <0x7f454c46@gmail.com>, Dmitry Safonov , Eric Dumazet , "David S. Miller" , Jakub Kicinski , Hideaki YOSHIFUJI , David Ahern , netdev@vger.kernel.org Subject: [PATCH v2] net/tcp: Merge TCP-MD5 inbound callbacks Date: Wed, 23 Feb 2022 12:17:46 +0000 Message-Id: <20220223121746.421327-1-dima@arista.com> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The functions do essentially the same work to verify TCP-MD5 sign. Code can be merged into one family-independent function in order to reduce copy'n'paste and generated code. Later with TCP-AO option added, this will allow to create one function that's responsible for segment verification, that will have all the different checks for MD5/AO/non-signed packets, which in turn will help to see checks for all corner-cases in one function, rather than spread around different families and functions. Cc: Eric Dumazet Cc: "David S. Miller" Cc: Jakub Kicinski Cc: Hideaki YOSHIFUJI Cc: David Ahern Cc: netdev@vger.kernel.org Signed-off-by: Dmitry Safonov --- v2: Rebased on net-next include/net/tcp.h | 12 +++++++ net/ipv4/tcp.c | 70 ++++++++++++++++++++++++++++++++++++++++ net/ipv4/tcp_ipv4.c | 78 +++------------------------------------------ net/ipv6/tcp_ipv6.c | 62 +++-------------------------------- 4 files changed, 91 insertions(+), 131 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 04f4650e0ff0..2e60864d7865 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1674,6 +1674,11 @@ tcp_md5_do_lookup(const struct sock *sk, int l3index, return NULL; return __tcp_md5_do_lookup(sk, l3index, addr, family); } +bool tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb, + enum skb_drop_reason *reason, + const void *saddr, const void *daddr, + int family, int dif, int sdif); + #define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key) #else @@ -1683,6 +1688,13 @@ tcp_md5_do_lookup(const struct sock *sk, int l3index, { return NULL; } +static inline bool tcp_inbound_md5_hash(const struct sock *sk, + const struct sk_buff *skb, + const void *saddr, const void *daddr, + int family, int dif, int sdif) +{ + return false; +} #define tcp_twsk_md5_key(twsk) NULL #endif diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 760e8221d321..68f1236b2858 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -4431,6 +4431,76 @@ int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, const struct tcp_md5sig_key *ke } EXPORT_SYMBOL(tcp_md5_hash_key); +/* Called with rcu_read_lock() */ +bool tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb, + enum skb_drop_reason *reason, + const void *saddr, const void *daddr, + int family, int dif, int sdif) +{ + /* + * This gets called for each TCP segment that arrives + * so we want to be efficient. + * We have 3 drop cases: + * o No MD5 hash and one expected. + * o MD5 hash and we're not expecting one. + * o MD5 hash and its wrong. + */ + const __u8 *hash_location = NULL; + struct tcp_md5sig_key *hash_expected; + const struct tcphdr *th = tcp_hdr(skb); + struct tcp_sock *tp = tcp_sk(sk); + int genhash, l3index; + u8 newhash[16]; + + /* sdif set, means packet ingressed via a device + * in an L3 domain and dif is set to the l3mdev + */ + l3index = sdif ? dif : 0; + + hash_expected = tcp_md5_do_lookup(sk, l3index, saddr, family); + hash_location = tcp_parse_md5sig_option(th); + + /* We've parsed the options - do we have a hash? */ + if (!hash_expected && !hash_location) + return false; + + if (hash_expected && !hash_location) { + *reason = SKB_DROP_REASON_TCP_MD5NOTFOUND; + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); + return true; + } + + if (!hash_expected && hash_location) { + *reason = SKB_DROP_REASON_TCP_MD5UNEXPECTED; + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); + return true; + } + + /* check the signature */ + genhash = tp->af_specific->calc_md5_hash(newhash, hash_expected, + NULL, skb); + + if (genhash || memcmp(hash_location, newhash, 16) != 0) { + *reason = SKB_DROP_REASON_TCP_MD5FAILURE; + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE); + if (family == AF_INET) { + net_info_ratelimited("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s L3 index %d\n", + saddr, ntohs(th->source), + daddr, ntohs(th->dest), + genhash ? " tcp_v4_calc_md5_hash failed" + : "", l3index); + } else { + net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u L3 index %d\n", + genhash ? "failed" : "mismatch", + saddr, ntohs(th->source), + daddr, ntohs(th->dest), l3index); + } + return true; + } + return false; +} +EXPORT_SYMBOL(tcp_inbound_md5_hash); + #endif void tcp_done(struct sock *sk) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d42824aedc36..411357ad9757 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1409,76 +1409,6 @@ EXPORT_SYMBOL(tcp_v4_md5_hash_skb); #endif -/* Called with rcu_read_lock() */ -static bool tcp_v4_inbound_md5_hash(const struct sock *sk, - const struct sk_buff *skb, - int dif, int sdif, - enum skb_drop_reason *reason) -{ -#ifdef CONFIG_TCP_MD5SIG - /* - * This gets called for each TCP segment that arrives - * so we want to be efficient. - * We have 3 drop cases: - * o No MD5 hash and one expected. - * o MD5 hash and we're not expecting one. - * o MD5 hash and its wrong. - */ - const __u8 *hash_location = NULL; - struct tcp_md5sig_key *hash_expected; - const struct iphdr *iph = ip_hdr(skb); - const struct tcphdr *th = tcp_hdr(skb); - const union tcp_md5_addr *addr; - unsigned char newhash[16]; - int genhash, l3index; - - /* sdif set, means packet ingressed via a device - * in an L3 domain and dif is set to the l3mdev - */ - l3index = sdif ? dif : 0; - - addr = (union tcp_md5_addr *)&iph->saddr; - hash_expected = tcp_md5_do_lookup(sk, l3index, addr, AF_INET); - hash_location = tcp_parse_md5sig_option(th); - - /* We've parsed the options - do we have a hash? */ - if (!hash_expected && !hash_location) - return false; - - if (hash_expected && !hash_location) { - *reason = SKB_DROP_REASON_TCP_MD5NOTFOUND; - NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); - return true; - } - - if (!hash_expected && hash_location) { - *reason = SKB_DROP_REASON_TCP_MD5UNEXPECTED; - NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); - return true; - } - - /* Okay, so this is hash_expected and hash_location - - * so we need to calculate the checksum. - */ - genhash = tcp_v4_md5_hash_skb(newhash, - hash_expected, - NULL, skb); - - if (genhash || memcmp(hash_location, newhash, 16) != 0) { - *reason = SKB_DROP_REASON_TCP_MD5FAILURE; - NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE); - net_info_ratelimited("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s L3 index %d\n", - &iph->saddr, ntohs(th->source), - &iph->daddr, ntohs(th->dest), - genhash ? " tcp_v4_calc_md5_hash failed" - : "", l3index); - return true; - } - return false; -#endif - return false; -} - static void tcp_v4_init_req(struct request_sock *req, const struct sock *sk_listener, struct sk_buff *skb) @@ -2035,8 +1965,9 @@ int tcp_v4_rcv(struct sk_buff *skb) struct sock *nsk; sk = req->rsk_listener; - if (unlikely(tcp_v4_inbound_md5_hash(sk, skb, dif, sdif, - &drop_reason))) { + if (unlikely(tcp_inbound_md5_hash(sk, skb, &drop_reason, + &iph->saddr, &iph->daddr, + AF_INET, dif, sdif))) { sk_drops_add(sk, skb); reqsk_put(req); goto discard_it; @@ -2110,7 +2041,8 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_and_relse; } - if (tcp_v4_inbound_md5_hash(sk, skb, dif, sdif, &drop_reason)) + if (tcp_inbound_md5_hash(sk, skb, &drop_reason, &iph->saddr, + &iph->daddr, AF_INET, dif, sdif)) goto discard_and_relse; nf_reset_ct(skb); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 749de8529c83..e98af869ff3a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -773,61 +773,6 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, #endif -static bool tcp_v6_inbound_md5_hash(const struct sock *sk, - const struct sk_buff *skb, - int dif, int sdif, - enum skb_drop_reason *reason) -{ -#ifdef CONFIG_TCP_MD5SIG - const __u8 *hash_location = NULL; - struct tcp_md5sig_key *hash_expected; - const struct ipv6hdr *ip6h = ipv6_hdr(skb); - const struct tcphdr *th = tcp_hdr(skb); - int genhash, l3index; - u8 newhash[16]; - - /* sdif set, means packet ingressed via a device - * in an L3 domain and dif is set to the l3mdev - */ - l3index = sdif ? dif : 0; - - hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr, l3index); - hash_location = tcp_parse_md5sig_option(th); - - /* We've parsed the options - do we have a hash? */ - if (!hash_expected && !hash_location) - return false; - - if (hash_expected && !hash_location) { - *reason = SKB_DROP_REASON_TCP_MD5NOTFOUND; - NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND); - return true; - } - - if (!hash_expected && hash_location) { - *reason = SKB_DROP_REASON_TCP_MD5UNEXPECTED; - NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED); - return true; - } - - /* check the signature */ - genhash = tcp_v6_md5_hash_skb(newhash, - hash_expected, - NULL, skb); - - if (genhash || memcmp(hash_location, newhash, 16) != 0) { - *reason = SKB_DROP_REASON_TCP_MD5FAILURE; - NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE); - net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u L3 index %d\n", - genhash ? "failed" : "mismatch", - &ip6h->saddr, ntohs(th->source), - &ip6h->daddr, ntohs(th->dest), l3index); - return true; - } -#endif - return false; -} - static void tcp_v6_init_req(struct request_sock *req, const struct sock *sk_listener, struct sk_buff *skb) @@ -1687,8 +1632,8 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) struct sock *nsk; sk = req->rsk_listener; - if (tcp_v6_inbound_md5_hash(sk, skb, dif, sdif, - &drop_reason)) { + if (tcp_inbound_md5_hash(sk, skb, &drop_reason, &hdr->saddr, + &hdr->daddr, AF_INET6, dif, sdif)) { sk_drops_add(sk, skb); reqsk_put(req); goto discard_it; @@ -1759,7 +1704,8 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) goto discard_and_relse; } - if (tcp_v6_inbound_md5_hash(sk, skb, dif, sdif, &drop_reason)) + if (tcp_inbound_md5_hash(sk, skb, &drop_reason, &hdr->saddr, + &hdr->daddr, AF_INET6, dif, sdif)) goto discard_and_relse; if (tcp_filter(sk, skb)) { base-commit: 922ea87ff6f2b63f413c6afa2c25b287dce76639 prerequisite-patch-id: f4dc7ba51eadb9fccabb755c41854bedeeaf8954 -- 2.35.1