From patchwork Thu Feb 1 00:07:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Paasch X-Patchwork-Id: 868105 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="T7xHpphx"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zX0nH4m39z9s7M for ; Thu, 1 Feb 2018 11:08:03 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932106AbeBAAIB (ORCPT ); Wed, 31 Jan 2018 19:08:01 -0500 Received: from mail-out4.apple.com ([17.151.62.26]:62940 "EHLO mail-in4.apple.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754449AbeBAAHf (ORCPT ); Wed, 31 Jan 2018 19:07:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; d=apple.com; s=mailout2048s; c=relaxed/simple; q=dns/txt; i=@apple.com; t=1517443653; x=2381357253; 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=lndFsBCVqdfEpTGVBmNCtRVqlCxdJK/JTMA1CXa41+I=; b=T7xHpphxaAugWZTDEXdOjW70/9ufjQJBel3b2QUsK5A8PuSH91xKfSpT92tixC8l 1yCazgQ4nKH/WwllxWvUtrDuSO87/a116Fp+Q9j7/DVju1F2OQvsB4GNhkcj485D zmTGGopt/CgdUWVPrKlovEwzF8NVaAnt2Z0CK2fSMnr7jo6s84TmfveNCfWdk/0x RPeBh+mhPcxIR+O3CKNy1f1P2RkSqoEl05Koqp9sTR8F96lWDbtEBv4DQXC8E9sn VUYpdys0Rm4PZVNHb8BOsmlIq23OUeI/dIVJ0mYJON4DXmbGx/4Tn9Ntd9UcKkQx /MctTqL5MlyGWZqQQo7BJg==; Received: from relay3.apple.com (relay3.apple.com [17.128.113.83]) (using TLS with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mail-in4.apple.com (Apple Secure Mail Relay) with SMTP id B8.8A.10621.54A527A5; Wed, 31 Jan 2018 16:07:33 -0800 (PST) X-AuditID: 11973e12-c67d59e00000297d-6d-5a725a456b3d Received: from nwk-mmpp-sz13.apple.com (nwk-mmpp-sz13.apple.com [17.128.115.216]) by relay3.apple.com (Apple SCV relay) with SMTP id A0.8C.12852.54A527A5; Wed, 31 Jan 2018 16:07:33 -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 <0P3G006E130L15B0@nwk-mmpp-sz13.apple.com>; Wed, 31 Jan 2018 16:07:33 -0800 (PST) From: Christoph Paasch To: netdev@vger.kernel.org Cc: Eric Dumazet , Mat Martineau , Ivan Delalande Subject: [RFC v2 09/14] tcp_md5: Detect key inside tcp_v6_send_response instead of passing it as an argument Date: Wed, 31 Jan 2018 16:07:11 -0800 Message-id: <20180201000716.69301-10-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+NgFprFLMWRmVeSWpSXmKPExsUi2FAYrOsaVRRl0NjNZ7H7brjF02OP2C3+ tvSzWBxbIObA4rF7ehOjx4JNpR7zTgZ6fN4kF8ASxWWTkpqTWZZapG+XwJVxaudqpoIN1hVt XycxNTAu1u9i5OSQEDCRWH9xHROILSSwmkni5+IAmPiawydZuxi5gOKHGCW+NO0Fcjg4mAXk JQ6el4WINzJJnP36gwWkQVhAUqL7zh1mEJtNQEvi7e12VhBbREBK4uOO7ewgDcwCTYwSjxae g2rIkzj89hLYZhYBVYlZtxeA2bwC5hIrl95mhbhCXuLwmyYwmxMo3rBrDjvEpWYSn68vZgYZ KiFwhE1i84THLBMYBWchHLiAkXEVo1BuYmaObmaeiV5iQUFOql5yfu4mRlBgTrcT2sF4apXV IUYBDkYlHt4JFwqjhFgTy4orcw8xSnOwKInzeokWRQkJpCeWpGanphakFsUXleakFh9iZOLg lGpgzO+YdSFF7vWxa+qtE+6FVOWdj/Nk/P5jt7iP3fpdoYl+q9cdnvGLc+Xuyynf3VoPxq6K 60wMmVbxa8WyD6FvbEo6FWca+d+M2yMkPTco4kT/yl27Eg/zvfY3Nf+aa7rSOsb6zA+1PUr2 d92UzOxuGh35Llf7Sj/loW6zz2HLxGVHwysL5fzTlViKMxINtZiLihMB9K2dQS0CAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrGLMWRmVeSWpSXmKPExsUi2FB8Q9c1qijK4Ptabovdd8Mtnh57xG7x t6WfxeLYAjEHFo/d05sYPRZsKvWYdzLQ4/MmuQCWKEObtPyi8sSiFIWi5IISW6XijMSU/PJ4 S2MjU4fEgoKcVL3k/FwlfTublNSczLLUIn27BMOMUztXMxVssK5o+zqJqYFxsX4XIyeHhICJ xJrDJ1m7GLk4hAQOMUp8adoL5HBwMAvISxw8LwsRb2SSOPv1BwtIg7CApET3nTvMIDabgJbE 29vtrCC2iICUxMcd29lBGpgFmhglHi08B9WQJ3H47SUmEJtFQFVi1u0FYDavgLnEyqW3WSGu kJc4/KYJzOYEijfsmsMOYgsJmEl8vr6YeQIj3yyEmxYwMq5iFChKzUmsNNaD+3YTIzgwC4N3 MP5ZZnWIUYCDUYmHd8KFwigh1sSy4spcoOc4mJVEeDeKFEUJ8aYkVlalFuXHF5XmpBYfYvQB um0is5Rocj4wavJK4g2NLYwtTSwMDEwszUxwCCuJ8x5RApolkJ5YkpqdmlqQWgQzjomDU6qB sWOHuFTJf0e+A0tXXwlR1j2t57Ln9PIQZaf9Xq8dHyYYcv18duP5c+FAGYa9rjb75MK2Cl6b L31tn/ffFb/jE9YyS4jN0/zSEP/PU1n8+tyEVa+v1p2+2fXJ+0n4kd4+oZpr32oPcLvaHPjJ eO+2w9OWFTnpD53VMsouyVpeevPPaeY8j3qDU0oswHRhqMVcVJwIAMnVrD15AgAA Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org We want to move all the TCP-MD5 code to a single place which enables us to factor the TCP-MD5 code out of the TCP-stack into the extra-option framework. Detection of whether or not to drop the segment (as done in tcp_v6_send_reset()) has now been moved to tcp_v6_send_response(). So we needed to adapt the latter so that it can handle the case where we want to exit without sending anything. Cc: Ivan Delalande Signed-off-by: Christoph Paasch Reviewed-by: Mat Martineau --- net/ipv6/tcp_ipv6.c | 119 +++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 62 deletions(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 202bf011f462..8c6d0362299e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -82,12 +82,6 @@ static const struct inet_connection_sock_af_ops ipv6_specific; #ifdef CONFIG_TCP_MD5SIG static const struct tcp_sock_af_ops tcp_sock_ipv6_specific; static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; -#else -static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(const struct sock *sk, - const struct in6_addr *addr) -{ - return NULL; -} #endif static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) @@ -779,12 +773,11 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 tsval, u32 tsecr, - int oif, struct tcp_md5sig_key *key, int rst, - u8 tclass, __be32 label) + int oif, int rst, u8 tclass, __be32 label) { const struct tcphdr *th = tcp_hdr(skb); struct tcphdr *t1; - struct sk_buff *buff; + struct sk_buff *buff = NULL; struct flowi6 fl6; struct net *net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev); struct sock *ctl_sk = net->ipv6.tcp_sk; @@ -793,10 +786,54 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 __be32 *topt; struct hlist_head *extopt_list = NULL; struct tcp_out_options extraopts; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key = NULL; + const __u8 *hash_location = NULL; + struct ipv6hdr *ipv6h = ipv6_hdr(skb); +#endif if (tsecr) tot_len += TCPOLEN_TSTAMP_ALIGNED; #ifdef CONFIG_TCP_MD5SIG + rcu_read_lock(); + hash_location = tcp_parse_md5sig_option(th); + if (sk && sk_fullsock(sk)) { + key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr); + } else if (sk && sk->sk_state == TCP_TIME_WAIT) { + struct tcp_timewait_sock *tcptw = tcp_twsk(sk); + + key = tcp_twsk_md5_key(tcptw); + } else if (sk && sk->sk_state == TCP_NEW_SYN_RECV) { + key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr); + } else if (hash_location) { + unsigned char newhash[16]; + struct sock *sk1 = NULL; + int genhash; + + /* active side is lost. Try to find listening socket through + * source port, and then find md5 key through listening socket. + * we are not loose security here: + * Incoming packet is checked with md5 hash with finding key, + * no RST generated if md5 hash doesn't match. + */ + sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), + &tcp_hashinfo, NULL, 0, + &ipv6h->saddr, + th->source, &ipv6h->daddr, + ntohs(th->source), tcp_v6_iif(skb), + tcp_v6_sdif(skb)); + if (!sk1) + goto out; + + key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr); + if (!key) + goto out; + + genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb); + if (genhash || memcmp(hash_location, newhash, 16) != 0) + goto out; + } + if (key) tot_len += TCPOLEN_MD5SIG_ALIGNED; #endif @@ -823,7 +860,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); if (!buff) - return; + goto out; skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); @@ -900,24 +937,21 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 TCP_INC_STATS(net, TCP_MIB_OUTSEGS); if (rst) TCP_INC_STATS(net, TCP_MIB_OUTRSTS); - return; + buff = NULL; } +out: kfree_skb(buff); + +#ifdef CONFIG_TCP_MD5SIG + rcu_read_unlock(); +#endif } static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) { const struct tcphdr *th = tcp_hdr(skb); u32 seq = 0, ack_seq = 0; - struct tcp_md5sig_key *key = NULL; -#ifdef CONFIG_TCP_MD5SIG - const __u8 *hash_location = NULL; - struct ipv6hdr *ipv6h = ipv6_hdr(skb); - unsigned char newhash[16]; - int genhash; - struct sock *sk1 = NULL; -#endif int oif = 0; if (th->rst) @@ -929,38 +963,6 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) if (!sk && !ipv6_unicast_destination(skb)) return; -#ifdef CONFIG_TCP_MD5SIG - rcu_read_lock(); - hash_location = tcp_parse_md5sig_option(th); - if (sk && sk_fullsock(sk)) { - key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr); - } else if (hash_location) { - /* - * active side is lost. Try to find listening socket through - * source port, and then find md5 key through listening socket. - * we are not loose security here: - * Incoming packet is checked with md5 hash with finding key, - * no RST generated if md5 hash doesn't match. - */ - sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), - &tcp_hashinfo, NULL, 0, - &ipv6h->saddr, - th->source, &ipv6h->daddr, - ntohs(th->source), tcp_v6_iif(skb), - tcp_v6_sdif(skb)); - if (!sk1) - goto out; - - key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr); - if (!key) - goto out; - - genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb); - if (genhash || memcmp(hash_location, newhash, 16) != 0) - goto out; - } -#endif - if (th->ack) seq = ntohl(th->ack_seq); else @@ -972,20 +974,14 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) trace_tcp_send_reset(sk, skb); } - tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0); - -#ifdef CONFIG_TCP_MD5SIG -out: - rcu_read_unlock(); -#endif + tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, 1, 0, 0); } static void tcp_v6_send_ack(const struct sock *sk, struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 tsval, u32 tsecr, int oif, - struct tcp_md5sig_key *key, u8 tclass, - __be32 label) + u8 tclass, __be32 label) { - tcp_v6_send_response(sk, skb, seq, ack, win, tsval, tsecr, oif, key, 0, + tcp_v6_send_response(sk, skb, seq, ack, win, tsval, tsecr, oif, 0, tclass, label); } @@ -997,7 +993,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcp_time_stamp_raw() + tcptw->tw_ts_offset, - tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), + tcptw->tw_ts_recent, tw->tw_bound_dev_if, tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel)); inet_twsk_put(tw); @@ -1020,7 +1016,6 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, tcp_time_stamp_raw() + tcp_rsk(req)->ts_off, req->ts_recent, sk->sk_bound_dev_if, - tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr), 0, 0); }