From patchwork Mon Dec 18 21:51:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Paasch X-Patchwork-Id: 850425 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="TH3Yu+9G"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3z0vrX25nsz9s7v for ; Tue, 19 Dec 2017 08:51:56 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965067AbdLRVvy (ORCPT ); Mon, 18 Dec 2017 16:51:54 -0500 Received: from mail-out6.apple.com ([17.151.62.28]:65236 "EHLO mail-in6.apple.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S937547AbdLRVvm (ORCPT ); Mon, 18 Dec 2017 16:51:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; d=apple.com; s=mailout2048s; c=relaxed/simple; q=dns/txt; i=@apple.com; t=1513633897; 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=LkVRtaJH5Dc81pN6I0Qip3uC+OkdY+r5F+jVxQOGdpU=; b=TH3Yu+9GlszsVhC9WM4mJQpoHHBMcx4YsfFW6T7EfJhNOteA76ih40GHv9st0d0Y meb+yG1JU0vhNJ72jP28QzFSPn/2XjidkE5zsFhanW5T9v3fnGF/got8V1Emj6I+ SwqWamkM64bo364hzlv12D7nqedkSgEkctWC54tHkyUpQOWNSls4lD1mpQm2mGRB uyqmZMEgS/yT+RWFu0iQ/Iq2tMoTtF7xWei2BsgTRqsOimHRaQ/SquKzHouwQvU+ HSdAczqnYCFwr/KLAwTuEEWIcrb158odRhXixOIxqeIgQapynpzUsJPHxpmfchc3 jF0XjnTRMLSEdBULWG54Cw==; Received: from relay5.apple.com (relay5.apple.com [17.128.113.88]) (using TLS with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mail-in6.apple.com (Apple Secure Mail Relay) with SMTP id 9C.23.20985.968383A5; Mon, 18 Dec 2017 13:51:37 -0800 (PST) X-AuditID: 11973e15-7125b9c0000051f9-45-5a383869fedb Received: from nwk-mmpp-sz13.apple.com (nwk-mmpp-sz13.apple.com [17.128.115.216]) by relay5.apple.com (Apple SCV relay) with SMTP id 17.E8.18983.868383A5; Mon, 18 Dec 2017 13:51:36 -0800 (PST) Content-transfer-encoding: 7BIT Received: from localhost ([17.226.23.135]) by nwk-mmpp-sz13.apple.com (Oracle Communications Messaging Server 8.0.2.1.20171204 64bit (built Dec 4 2017)) with ESMTPSA id <0P1600HV9FE0VT70@nwk-mmpp-sz13.apple.com>; Mon, 18 Dec 2017 13:51:36 -0800 (PST) From: Christoph Paasch To: netdev@vger.kernel.org Cc: Eric Dumazet , Mat Martineau , Alexei Starovoitov Subject: [RFC 09/14] tcp_md5: Detect key inside tcp_v6_send_response instead of passing it as an argument Date: Mon, 18 Dec 2017 13:51:04 -0800 Message-id: <20171218215109.38700-10-cpaasch@apple.com> X-Mailer: git-send-email 2.15.0 In-reply-to: <20171218215109.38700-1-cpaasch@apple.com> References: <20171218215109.38700-1-cpaasch@apple.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprGLMWRmVeSWpSXmKPExsUi2FAYoZtpYRFlsCHV4svP2+wWT489Yrf4 29LPYnFsgZgDi8eCTaUem1Z1snnMOxno8XmTXABLFJdNSmpOZllqkb5dAlfGunmT2As6rCs2 vJrA2MDYoN/FyMEhIWAiMfFEUhcjF4eQwGomiX1HVrJ2MXKCxR9unssCYgsJHGKU+DHTHqSe WUBe4uB5WYj6RiaJD3N2g9ULC0hKdN+5wwxiswloSby93Q4WFxGQkvi4Yzs7iM0s0MwosXOO CER9tsT2p6/ZQGwWAVWJA42/2UDm8wqYS/xeWgZxgrzE4u87wUo4gcI9Xx+xQ5xjJnH+50sm iJojbBIXH8lPYBSchXDdAkbGVYxCuYmZObqZeWZ6iQUFOal6yfm5mxhBATndTnQH45lVVocY BTgYlXh4Z1w1jxJiTSwrrsw9xCjNwaIkznux2iRKSCA9sSQ1OzW1ILUovqg0J7X4ECMTB6dU A6P+JydpTb5ysU3MJ5+rVk81WNZs9zDrxr61nJfEQ1ZITDUqlHu0N41F3anG41HPi8ebuNPY pk/6x+MapHpkpbVqwBrG62fU98w6FWCxNXfGur42a2uJZ+I6k5oKe5Z+fscbE+KxROaSjb7e ld2p/JwxFxLObpobIXvrzQ2/Cy7rP/+8kLY0/7gSS3FGoqEWc1FxIgANLo4cKQIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrCLMWRmVeSWpSXmKPExsUi2FB8QzfDwiLKoGGKtcWXn7fZLZ4ee8Ru 8beln8Xi2AIxBxaPBZtKPTat6mTzmHcy0OPzJrkAlihDm7T8ovLEohSFouSCElul4ozElPzy eEtjI1OHxIKCnFS95PxcJX07m5TUnMyy1CJ9uwTDjHXzJrEXdFhXbHg1gbGBsUG/i5GTQ0LA ROLh5rksILaQwCFGiR8z7bsYOTiYBeQlDp6X7WLkAgo3Mkl8mLObFaRGWEBSovvOHWYQm01A S+Lt7XawuIiAlMTHHdvZQWxmgWZGiZ1zRCDqsyW2P33NBmKzCKhKHGj8zQYyn1fAXOL30jKI E+QlFn/fCVbCCRTu+fqIHeIcM4nzP18yTWDkm4Vw0QJGxlWMAkWpOYmVpnpwr25iBAdlYcQO xv/LrA4xCnAwKvHwzrhqHiXEmlhWXJkL9BkHs5IIr99ZoBBvSmJlVWpRfnxRaU5q8SFGH6DT JjJLiSbnAyMmryTe0NjC2NLEwsDAxNLMBIewkjiv+yqgWQLpiSWp2ampBalFMOOYODilGhhL DgpxfFJr8vk+NSubMWr7y58/fVbfbXaLVlo6tWZpl4Ls0yUWle6paQ8nvucW2Wj2KF7j3xSb /+Vr9h1Nk63/VqbesFflCvt5fmveL4q7RRWPB7CvY1p9fYmK/w/ekh/NWx0XZa786Zgy513H 49ithdH3tWXXZK44rLtr8q/op/s5JTwOLVdXYgEmCkMt5qLiRAC+wwnCdwIAAA== 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. 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 5af5dcc1ac83..202a59511950 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) @@ -780,12 +774,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; @@ -794,10 +787,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 @@ -824,7 +861,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); @@ -901,24 +938,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) @@ -930,38 +964,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 @@ -973,20 +975,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); } @@ -998,7 +994,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); @@ -1021,7 +1017,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); }