From patchwork Thu Feb 1 00:07:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Paasch X-Patchwork-Id: 868114 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=apple.com header.i=@apple.com header.b="CLEWgCyf"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zX16N6j8lz9ryk for ; Thu, 1 Feb 2018 11:22:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932097AbeBAAWu (ORCPT ); Wed, 31 Jan 2018 19:22:50 -0500 Received: from mail-out25.apple.com ([17.171.2.35]:50282 "EHLO mail-in25.apple.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755910AbeBAAWp (ORCPT ); Wed, 31 Jan 2018 19:22:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; d=apple.com; s=mailout2048s; c=relaxed/simple; q=dns/txt; i=@apple.com; t=1517443656; x=2381357256; h=From:Sender:Reply-To:Subject:Date:Message-id:To:Cc:MIME-Version:Content-Type: Content-transfer-encoding:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-reply-to:References:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=VrxMZz4rY1pJnUc7Y957bDRm8FXQ+aU5GdghMUXm2xM=; b=CLEWgCyfQS9HFFmhDt5KIpbxUbnsOi4oR0DKzDD/STHMWVdVHnMmtv9b2zrTH71d 739ODM5SObkAhr9pem6gXmyAmyXD2CCOawMbMJsiDW759VNuynGc7CvdmMZbecVV bVIMC/YZEeE9Zdpa/xsVkaHN+i4Lng8XwVxwyrmsj0AqlCxmj00YwNyqBFAa+sto Rh4rzquhZPrDdGDC/Z3kSe7gSBkvnFS+/skBQhY98YzAIECQo3p+N0ICHY7do81E htvLiU+JwuBRvLNW3tbAkL8QmEYE47bI8u55unserzefTiITnlc4PC95gT1HwaYF YwRmm7keY43t1AoM010VGQ==; Received: from relay7.apple.com (relay7.apple.com [17.128.113.101]) (using TLS with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mail-in25.apple.com (Apple Secure Mail Relay) with SMTP id 6A.63.14365.74A527A5; Wed, 31 Jan 2018 16:07:36 -0800 (PST) X-AuditID: 11ab0219-e904d9e00000381d-fa-5a725a47a00c Received: from nwk-mmpp-sz13.apple.com (nwk-mmpp-sz13.apple.com [17.128.115.216]) by relay7.apple.com (Apple SCV relay) with SMTP id D3.0D.05443.74A527A5; Wed, 31 Jan 2018 16:07:35 -0800 (PST) Content-transfer-encoding: 7BIT Received: from localhost ([17.226.23.225]) by nwk-mmpp-sz13.apple.com (Oracle Communications Messaging Server 8.0.2.1.20180104 64bit (built Jan 4 2018)) with ESMTPSA id <0P3G00BIB30NWZC0@nwk-mmpp-sz13.apple.com>; Wed, 31 Jan 2018 16:07:35 -0800 (PST) From: Christoph Paasch To: netdev@vger.kernel.org Cc: Eric Dumazet , Mat Martineau , Ivan Delalande Subject: [RFC v2 13/14] tcp_md5: Cleanup TCP-code Date: Wed, 31 Jan 2018 16:07:15 -0800 Message-id: <20180201000716.69301-14-cpaasch@apple.com> X-Mailer: git-send-email 2.16.1 In-reply-to: <20180201000716.69301-1-cpaasch@apple.com> References: <20180201000716.69301-1-cpaasch@apple.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprDLMWRmVeSWpSXmKPExsUi2FCYqusRVRRlMHOKgMXuu+EWT489Yrf4 29LPYnFsgZgDi8fu6U2MHgs2lXrMOxno8XmTXABLFJdNSmpOZllqkb5dAlfGkf63jAULZjFW nLnB38A4sbaLkZNDQsBEoq/pKlsXIxeHkMBaJolj7Q3MMIktLbtYIRKHGCU2df0FSnBwMAvI Sxw8LwsRb2SS6OpYxwjSICwgKdF95w5YM5uAlsTb2+2sILaIgJTExx3b2UEamAWaGCUeLTzH AtFgKHF7yT02EJtFQFVi5eoesEG8AuYSE/bsY4O4Ql7i8JsmsEGcQPGGXXPYQWwhATOJz9cX M4MMlRA4wSbRNfEk2wRGwVkIBy5gZFzFKJybmJmjm5lnZKqXWFCQk6qXnJ+7iREUnKuZJHcw fn1teIhRgINRiYd3woXCKCHWxLLiytxDjNIcLErivJHKWVFCAumJJanZqakFqUXxRaU5qcWH GJk4OKUaGOfpdKwym312nXLo9E21lwprmIWcSltDe3uv14rvez6h5ILCZ+4XZn9OzAo1zan+ yKzWfGPWupt/A3eeVmTS/jFp38PQoDc92p82eGvnrP1slrHusmT8m+V1vCej2CaE79YValxo wX93QtAdg4u7S6Xbmd6JVvNoRE56zXfrtqfTeUN9d5sWJSWW4oxEQy3mouJEANfcZucvAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrGLMWRmVeSWpSXmKPExsUi2FB8Q9c9qijK4P51XYvdd8Mtnh57xG7x t6WfxeLYAjEHFo/d05sYPRZsKvWYdzLQ4/MmuQCWKEObtPyi8sSiFIWi5IISW6XijMSU/PJ4 S2MjU4fEgoKcVL3k/FwlfTublNSczLLUIn27BMOMI/1vGQsWzGKsOHODv4FxYm0XIyeHhICJ xJaWXaxdjFwcQgKHGCU2df1l7mLk4GAWkJc4eF4WIt7IJNHVsY4RpEFYQFKi+84dZhCbTUBL 4u3tdlYQW0RASuLjju3sIA3MAk2MEo8WnmOBaDCUuL3kHhuIzSKgKrFydQ/YIF4Bc4kJe/ax QVwhL3H4TRPYIE6geMOuOewgtpCAmcTn64uZJzDyzUK4aQEj4ypGgaLUnMRKcz24bzcxggOz MHUHY+Nyq0OMAhyMSjy8Ly4VRgmxJpYVV+YCPcfBrCTCu1GkKEqINyWxsiq1KD++qDQntfgQ ow/QbROZpUST84FRk1cSb2hsYWxpYmFgYGJpZoJDWEmc94gS0CyB9MSS1OzU1ILUIphxTByc Ug2MCgH7suqzvx4/aFLcxtebwjTRdCHDv9/y/5+JnVvyWv8eX4yT6SEnJZHJd+/MtxRymH38 dmN65LHYKzNj1os4rjjtvjN9rbKc656O7zF6l/MeO7Bct5XIFdCw6I0OCW3v80nz2Vj78FAZ f7Cu1IMbC1lU6muyqlPbFz17dqP+S+ZcYWOlGxuVWIDpwlCLuag4EQBXW6xweQIAAA== Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Now that we have consolidated the TCP_MD5 output path, we can cleanup TCP and its callbacks to MD5. These callbacks are solely there to handle the different address-familiese (v4, v6 and v4mapped). Now that we have isolated the TCP_MD5-code it is acceptable to add a bit more complexity inside tcp_md5.c to handle these address-families at the benefit of getting rid of these callbacks in tcp_sock, together with its assignments in tcp_v4/6_connect,... Cc: Ivan Delalande Signed-off-by: Christoph Paasch Reviewed-by: Mat Martineau --- include/linux/tcp.h | 5 - include/linux/tcp_md5.h | 18 +-- include/net/tcp.h | 24 ---- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_ipv4.c | 8 -- net/ipv4/tcp_md5.c | 340 ++++++++++++++++++++++-------------------------- net/ipv6/tcp_ipv6.c | 17 --- 7 files changed, 155 insertions(+), 259 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index d4d22b9c19be..36f9bedeb6b1 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -388,11 +388,6 @@ struct tcp_sock { * while socket was owned by user. */ -#ifdef CONFIG_TCP_MD5SIG -/* TCP AF-Specific parts; only used by MD5 Signature support so far */ - const struct tcp_sock_af_ops *af_specific; -#endif - /* TCP fastopen related information */ struct tcp_fastopen_request *fastopen_req; /* fastopen_rsk points to request_sock that resulted in this big diff --git a/include/linux/tcp_md5.h b/include/linux/tcp_md5.h index 94a29c4f6fd1..441be65ec893 100644 --- a/include/linux/tcp_md5.h +++ b/include/linux/tcp_md5.h @@ -27,28 +27,14 @@ struct tcp_md5sig_key { struct rcu_head rcu; }; -extern const struct tcp_sock_af_ops tcp_sock_ipv4_specific; -extern const struct tcp_sock_af_ops tcp_sock_ipv6_specific; -extern const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; - /* - functions */ -int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, - const struct sock *sk, const struct sk_buff *skb); -struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, - const struct sock *addr_sk); +int tcp_md5_parse_keys(struct sock *sk, int optname, char __user *optval, + int optlen); bool tcp_v4_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb); -struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk, - const struct sock *addr_sk); - -int tcp_v6_md5_hash_skb(char *md5_hash, - const struct tcp_md5sig_key *key, - const struct sock *sk, - const struct sk_buff *skb); - bool tcp_v6_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb); diff --git a/include/net/tcp.h b/include/net/tcp.h index d2738cb01cf2..ceb8ac1e17bd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1730,32 +1730,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, const struct tcp_request_sock_ops *af_ops, struct sock *sk, struct sk_buff *skb); -/* TCP af-specific functions */ -struct tcp_sock_af_ops { -#ifdef CONFIG_TCP_MD5SIG - struct tcp_md5sig_key *(*md5_lookup) (const struct sock *sk, - const struct sock *addr_sk); - int (*calc_md5_hash)(char *location, - const struct tcp_md5sig_key *md5, - const struct sock *sk, - const struct sk_buff *skb); - int (*md5_parse)(struct sock *sk, - int optname, - char __user *optval, - int optlen); -#endif -}; - struct tcp_request_sock_ops { u16 mss_clamp; -#ifdef CONFIG_TCP_MD5SIG - struct tcp_md5sig_key *(*req_md5_lookup)(const struct sock *sk, - const struct sock *addr_sk); - int (*calc_md5_hash) (char *location, - const struct tcp_md5sig_key *md5, - const struct sock *sk, - const struct sk_buff *skb); -#endif void (*init_req)(struct request_sock *req, const struct sock *sk_listener, struct sk_buff *skb); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fc5c9cb19b9b..ffff795f2dfb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2828,7 +2828,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, case TCP_MD5SIG: case TCP_MD5SIG_EXT: /* Read the IP->Key mappings from userspace */ - err = tp->af_specific->md5_parse(sk, optname, optval, optlen); + err = tcp_md5_parse_keys(sk, optname, optval, optlen); break; #endif case TCP_USER_TIMEOUT: diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 694089b0536b..6a839c1280b3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -889,10 +889,6 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { .mss_clamp = TCP_MSS_DEFAULT, -#ifdef CONFIG_TCP_MD5SIG - .req_md5_lookup = tcp_v4_md5_lookup, - .calc_md5_hash = tcp_v4_md5_hash_skb, -#endif .init_req = tcp_v4_init_req, #ifdef CONFIG_SYN_COOKIES .cookie_init_seq = cookie_v4_init_sequence, @@ -1450,10 +1446,6 @@ static int tcp_v4_init_sock(struct sock *sk) icsk->icsk_af_ops = &ipv4_specific; -#ifdef CONFIG_TCP_MD5SIG - tcp_sk(sk)->af_specific = &tcp_sock_ipv4_specific; -#endif - return 0; } diff --git a/net/ipv4/tcp_md5.c b/net/ipv4/tcp_md5.c index 2c238c853a56..e05db5af06ee 100644 --- a/net/ipv4/tcp_md5.c +++ b/net/ipv4/tcp_md5.c @@ -336,12 +336,13 @@ static int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, return crypto_ahash_update(hp->md5_req); } -static int tcp_v4_parse_md5_keys(struct sock *sk, int optname, - char __user *optval, int optlen) +int tcp_md5_parse_keys(struct sock *sk, int optname, char __user *optval, + int optlen) { + u8 prefixlen = 32, maxprefixlen; + union tcp_md5_addr *tcpmd5addr; struct tcp_md5sig cmd; - struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; - u8 prefixlen = 32; + unsigned short family; if (optlen < sizeof(cmd)) return -EINVAL; @@ -349,76 +350,48 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, int optname, if (copy_from_user(&cmd, optval, sizeof(cmd))) return -EFAULT; - if (sin->sin_family != AF_INET) - return -EINVAL; - - if (optname == TCP_MD5SIG_EXT && - cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) { - prefixlen = cmd.tcpm_prefixlen; - if (prefixlen > 32) - return -EINVAL; - } + family = cmd.tcpm_addr.ss_family; - if (!cmd.tcpm_keylen) - return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, - AF_INET, prefixlen); - - if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) + if (family != AF_INET && family != AF_INET6) return -EINVAL; - return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, - AF_INET, prefixlen, cmd.tcpm_key, cmd.tcpm_keylen, - GFP_KERNEL); -} - -#if IS_ENABLED(CONFIG_IPV6) -static int tcp_v6_parse_md5_keys(struct sock *sk, int optname, - char __user *optval, int optlen) -{ - struct tcp_md5sig cmd; - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; - u8 prefixlen; - - if (optlen < sizeof(cmd)) + if (sk->sk_family != family) return -EINVAL; - if (copy_from_user(&cmd, optval, sizeof(cmd))) - return -EFAULT; + if (family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; - if (sin6->sin6_family != AF_INET6) - return -EINVAL; + if (!ipv6_addr_v4mapped(&sin6->sin6_addr)) { + tcpmd5addr = (union tcp_md5_addr *)&sin6->sin6_addr; + maxprefixlen = 128; + } else { + tcpmd5addr = (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3]; + family = AF_INET; + maxprefixlen = 32; + } + } else { + struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; + + tcpmd5addr = (union tcp_md5_addr *)&sin->sin_addr; + maxprefixlen = 32; + } if (optname == TCP_MD5SIG_EXT && cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) { prefixlen = cmd.tcpm_prefixlen; - if (prefixlen > 128 || (ipv6_addr_v4mapped(&sin6->sin6_addr) && - prefixlen > 32)) + if (prefixlen > maxprefixlen) return -EINVAL; - } else { - prefixlen = ipv6_addr_v4mapped(&sin6->sin6_addr) ? 32 : 128; } - if (!cmd.tcpm_keylen) { - if (ipv6_addr_v4mapped(&sin6->sin6_addr)) - return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3], - AF_INET, prefixlen); - return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr, - AF_INET6, prefixlen); - } + if (!cmd.tcpm_keylen) + return tcp_md5_do_del(sk, tcpmd5addr, family, prefixlen); if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) return -EINVAL; - if (ipv6_addr_v4mapped(&sin6->sin6_addr)) - return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3], - AF_INET, prefixlen, cmd.tcpm_key, - cmd.tcpm_keylen, GFP_KERNEL); - - return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr, - AF_INET6, prefixlen, cmd.tcpm_key, + return tcp_md5_do_add(sk, tcpmd5addr, family, prefixlen, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); } -#endif static int tcp_v4_md5_hash_headers(struct tcp_md5sig_pool *hp, __be32 daddr, __be32 saddr, @@ -670,6 +643,102 @@ static int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, return 0; } +static int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, + const struct sock *sk, const struct sk_buff *skb) +{ + struct tcp_md5sig_pool *hp; + struct ahash_request *req; + const struct tcphdr *th = tcp_hdr(skb); + __be32 saddr, daddr; + + if (sk) { /* valid for establish/request sockets */ + saddr = sk->sk_rcv_saddr; + daddr = sk->sk_daddr; + } else { + const struct iphdr *iph = ip_hdr(skb); + + saddr = iph->saddr; + daddr = iph->daddr; + } + + hp = tcp_get_md5sig_pool(); + if (!hp) + goto clear_hash_noput; + req = hp->md5_req; + + if (crypto_ahash_init(req)) + goto clear_hash; + + if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, skb->len)) + goto clear_hash; + if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2)) + goto clear_hash; + if (tcp_md5_hash_key(hp, key)) + goto clear_hash; + ahash_request_set_crypt(req, NULL, md5_hash, 0); + if (crypto_ahash_final(req)) + goto clear_hash; + + tcp_put_md5sig_pool(); + return 0; + +clear_hash: + tcp_put_md5sig_pool(); +clear_hash_noput: + memset(md5_hash, 0, 16); + return 1; +} + +#if IS_ENABLED(CONFIG_IPV6) +static int tcp_v6_md5_hash_skb(char *md5_hash, + const struct tcp_md5sig_key *key, + const struct sock *sk, + const struct sk_buff *skb) +{ + const struct in6_addr *saddr, *daddr; + struct tcp_md5sig_pool *hp; + struct ahash_request *req; + const struct tcphdr *th = tcp_hdr(skb); + + if (sk) { /* valid for establish/request sockets */ + saddr = &sk->sk_v6_rcv_saddr; + daddr = &sk->sk_v6_daddr; + } else { + const struct ipv6hdr *ip6h = ipv6_hdr(skb); + + saddr = &ip6h->saddr; + daddr = &ip6h->daddr; + } + + hp = tcp_get_md5sig_pool(); + if (!hp) + goto clear_hash_noput; + req = hp->md5_req; + + if (crypto_ahash_init(req)) + goto clear_hash; + + if (tcp_v6_md5_hash_headers(hp, daddr, saddr, th, skb->len)) + goto clear_hash; + if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2)) + goto clear_hash; + if (tcp_md5_hash_key(hp, key)) + goto clear_hash; + ahash_request_set_crypt(req, NULL, md5_hash, 0); + if (crypto_ahash_final(req)) + goto clear_hash; + + tcp_put_md5sig_pool(); + return 0; + +clear_hash: + tcp_put_md5sig_pool(); +clear_hash_noput: + memset(md5_hash, 0, 16); + return 1; +} +#endif + static int tcp_v4_md5_send_response_prepare(struct sk_buff *skb, u8 flags, unsigned int remaining, struct tcp_out_options *opts, @@ -784,114 +853,14 @@ static __be32 *tcp_md5_send_response_write(__be32 *ptr, struct sk_buff *orig, return tcp_v4_md5_send_response_write(ptr, orig, th, opts, sk); } -struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, - const struct sock *addr_sk) +static struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, + const struct sock *addr_sk) { const union tcp_md5_addr *addr; addr = (const union tcp_md5_addr *)&addr_sk->sk_daddr; return tcp_md5_do_lookup(sk, addr, AF_INET); } -EXPORT_SYMBOL(tcp_v4_md5_lookup); - -int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, - const struct sock *sk, - const struct sk_buff *skb) -{ - struct tcp_md5sig_pool *hp; - struct ahash_request *req; - const struct tcphdr *th = tcp_hdr(skb); - __be32 saddr, daddr; - - if (sk) { /* valid for establish/request sockets */ - saddr = sk->sk_rcv_saddr; - daddr = sk->sk_daddr; - } else { - const struct iphdr *iph = ip_hdr(skb); - - saddr = iph->saddr; - daddr = iph->daddr; - } - - hp = tcp_get_md5sig_pool(); - if (!hp) - goto clear_hash_noput; - req = hp->md5_req; - - if (crypto_ahash_init(req)) - goto clear_hash; - - if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, skb->len)) - goto clear_hash; - if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2)) - goto clear_hash; - if (tcp_md5_hash_key(hp, key)) - goto clear_hash; - ahash_request_set_crypt(req, NULL, md5_hash, 0); - if (crypto_ahash_final(req)) - goto clear_hash; - - tcp_put_md5sig_pool(); - return 0; - -clear_hash: - tcp_put_md5sig_pool(); -clear_hash_noput: - memset(md5_hash, 0, 16); - return 1; -} -EXPORT_SYMBOL(tcp_v4_md5_hash_skb); - -#if IS_ENABLED(CONFIG_IPV6) -int tcp_v6_md5_hash_skb(char *md5_hash, - const struct tcp_md5sig_key *key, - const struct sock *sk, - const struct sk_buff *skb) -{ - const struct in6_addr *saddr, *daddr; - struct tcp_md5sig_pool *hp; - struct ahash_request *req; - const struct tcphdr *th = tcp_hdr(skb); - - if (sk) { /* valid for establish/request sockets */ - saddr = &sk->sk_v6_rcv_saddr; - daddr = &sk->sk_v6_daddr; - } else { - const struct ipv6hdr *ip6h = ipv6_hdr(skb); - - saddr = &ip6h->saddr; - daddr = &ip6h->daddr; - } - - hp = tcp_get_md5sig_pool(); - if (!hp) - goto clear_hash_noput; - req = hp->md5_req; - - if (crypto_ahash_init(req)) - goto clear_hash; - - if (tcp_v6_md5_hash_headers(hp, daddr, saddr, th, skb->len)) - goto clear_hash; - if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2)) - goto clear_hash; - if (tcp_md5_hash_key(hp, key)) - goto clear_hash; - ahash_request_set_crypt(req, NULL, md5_hash, 0); - if (crypto_ahash_final(req)) - goto clear_hash; - - tcp_put_md5sig_pool(); - return 0; - -clear_hash: - tcp_put_md5sig_pool(); -clear_hash_noput: - memset(md5_hash, 0, 16); - return 1; -} -EXPORT_SYMBOL_GPL(tcp_v6_md5_hash_skb); -#endif /* Called with rcu_read_lock() */ bool tcp_v4_inbound_md5_hash(const struct sock *sk, @@ -994,8 +963,8 @@ bool tcp_v6_inbound_md5_hash(const struct sock *sk, } EXPORT_SYMBOL_GPL(tcp_v6_inbound_md5_hash); -struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk, - const struct sock *addr_sk) +static struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk, + const struct sock *addr_sk) { return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr); } @@ -1103,10 +1072,17 @@ static int tcp_md5_extopt_add_header_len(const struct sock *orig, const struct sock *sk, struct tcp_extopt_store *store) { - struct tcp_sock *tp = tcp_sk(sk); - - if (tp->af_specific->md5_lookup(orig, sk)) +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6 && + !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) { + if (tcp_v6_md5_lookup(orig, sk)) + return TCPOLEN_MD5SIG_ALIGNED; + } else +#endif +{ + if (tcp_v4_md5_lookup(orig, sk)) return TCPOLEN_MD5SIG_ALIGNED; +} return 0; } @@ -1120,19 +1096,29 @@ static unsigned int tcp_md5_extopt_prepare(struct sk_buff *skb, u8 flags, int ret = 0; if (sk_fullsock(sk)) { - struct tcp_sock *tp = tcp_sk(sk); - - opts->md5 = tp->af_specific->md5_lookup(sk, sk); +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6 && !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) + opts->md5 = tcp_v6_md5_lookup(sk, sk); + else +#endif + opts->md5 = tcp_v4_md5_lookup(sk, sk); } else { struct request_sock *req = inet_reqsk(sk); struct sock *listener = req->rsk_listener; + struct inet_request_sock *ireq = inet_rsk(req); /* Coming from tcp_make_synack, unlock is in * tcp_md5_extopt_write */ rcu_read_lock(); - opts->md5 = tcp_rsk(req)->af_specific->req_md5_lookup(listener, sk); +#if IS_ENABLED(CONFIG_IPV6) + if (ireq->ireq_family == AF_INET6 && + !ipv6_addr_v4mapped(&ireq->ir_v6_rmt_addr)) + opts->md5 = tcp_v6_md5_lookup(listener, sk); + else +#endif + opts->md5 = tcp_v4_md5_lookup(listener, sk); if (!opts->md5) rcu_read_unlock(); @@ -1352,25 +1338,3 @@ static void tcp_md5_extopt_destroy(struct tcp_extopt_store *store) kfree_rcu(md5_opt, rcu); } } - -const struct tcp_sock_af_ops tcp_sock_ipv4_specific = { - .md5_lookup = tcp_v4_md5_lookup, - .calc_md5_hash = tcp_v4_md5_hash_skb, - .md5_parse = tcp_v4_parse_md5_keys, -}; - -#if IS_ENABLED(CONFIG_IPV6) -const struct tcp_sock_af_ops tcp_sock_ipv6_specific = { - .md5_lookup = tcp_v6_md5_lookup, - .calc_md5_hash = tcp_v6_md5_hash_skb, - .md5_parse = tcp_v6_parse_md5_keys, -}; -EXPORT_SYMBOL_GPL(tcp_sock_ipv6_specific); - -const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { - .md5_lookup = tcp_v4_md5_lookup, - .calc_md5_hash = tcp_v4_md5_hash_skb, - .md5_parse = tcp_v6_parse_md5_keys, -}; -EXPORT_SYMBOL_GPL(tcp_sock_ipv6_mapped_specific); -#endif diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3c48283a76c1..8800e5d75677 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -207,9 +207,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, icsk->icsk_af_ops = &ipv6_mapped; sk->sk_backlog_rcv = tcp_v4_do_rcv; -#ifdef CONFIG_TCP_MD5SIG - tp->af_specific = &tcp_sock_ipv6_mapped_specific; -#endif err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); @@ -217,9 +214,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, icsk->icsk_ext_hdr_len = exthdrlen; icsk->icsk_af_ops = &ipv6_specific; sk->sk_backlog_rcv = tcp_v6_do_rcv; -#ifdef CONFIG_TCP_MD5SIG - tp->af_specific = &tcp_sock_ipv6_specific; -#endif goto failure; } np->saddr = sk->sk_v6_rcv_saddr; @@ -542,10 +536,6 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = { static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr), -#ifdef CONFIG_TCP_MD5SIG - .req_md5_lookup = tcp_v6_md5_lookup, - .calc_md5_hash = tcp_v6_md5_hash_skb, -#endif .init_req = tcp_v6_init_req, #ifdef CONFIG_SYN_COOKIES .cookie_init_seq = cookie_v6_init_sequence, @@ -820,9 +810,6 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; newsk->sk_backlog_rcv = tcp_v4_do_rcv; -#ifdef CONFIG_TCP_MD5SIG - newtp->af_specific = &tcp_sock_ipv6_mapped_specific; -#endif newnp->ipv6_mc_list = NULL; newnp->ipv6_ac_list = NULL; @@ -1429,10 +1416,6 @@ static int tcp_v6_init_sock(struct sock *sk) icsk->icsk_af_ops = &ipv6_specific; -#ifdef CONFIG_TCP_MD5SIG - tcp_sk(sk)->af_specific = &tcp_sock_ipv6_specific; -#endif - return 0; }