[RFC 14/14] tcp_md5: Use TCP extra-options on the input path
flat view
STALE3210d
SUPERSEDED: 1 (0M)
From: Christoph Paasch <hidden>
Date: 2017-12-18 21:51:46
Subsystem:
networking [general], networking [tcp], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Neal Cardwell, Linus Torvalds
Revision rfc of 2 in this series; 1 review trailer.
Revisions (2)
- rfc current
- v2 [diff vs current]
The checks are now being done through the extra-option framework. For TCP MD5 this means that the check happens a bit later than usual. Signed-off-by: Christoph Paasch <redacted> Reviewed-by: Mat Martineau <redacted> --- include/linux/tcp_md5.h | 23 +---------------------- net/ipv4/tcp_input.c | 8 -------- net/ipv4/tcp_ipv4.c | 9 --------- net/ipv4/tcp_md5.c | 29 ++++++++++++++++++++++++----- net/ipv6/tcp_ipv6.c | 9 --------- 5 files changed, 25 insertions(+), 53 deletions(-)
diff --git a/include/linux/tcp_md5.h b/include/linux/tcp_md5.h
index 509fc36335e7..bef277f55b36 100644
--- a/include/linux/tcp_md5.h
+++ b/include/linux/tcp_md5.h@@ -31,30 +31,9 @@ struct tcp_md5sig_key { 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); - -bool tcp_v6_inbound_md5_hash(const struct sock *sk, - const struct sk_buff *skb); - int tcp_md5_diag_get_aux(struct sock *sk, bool net_admin, struct sk_buff *skb); int tcp_md5_diag_get_aux_size(struct sock *sk, bool net_admin); -#else - -static inline bool tcp_v4_inbound_md5_hash(const struct sock *sk, - const struct sk_buff *skb) -{ - return false; -} - -static inline bool tcp_v6_inbound_md5_hash(const struct sock *sk, - const struct sk_buff *skb) -{ - return false; -} - -#endif - +#endif /* CONFIG_TCP_MD5SIG */ #endif /* _LINUX_TCP_MD5_H */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index db54bdbdee51..e4de06e28a85 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c@@ -3754,14 +3754,6 @@ void tcp_parse_options(const struct net *net, TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th; } break; -#ifdef CONFIG_TCP_MD5SIG - case TCPOPT_MD5SIG: - /* - * The MD5 Hash has already been - * checked (see tcp_v{4,6}_do_rcv()). - */ - break; -#endif case TCPOPT_FASTOPEN: tcp_parse_fastopen_option( opsize - TCPOLEN_FASTOPEN_BASE,
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 670d7751f814..707ad1a343ba 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c@@ -62,7 +62,6 @@ #include <linux/init.h> #include <linux/times.h> #include <linux/slab.h> -#include <linux/tcp_md5.h> #include <net/net_namespace.h> #include <net/icmp.h>
@@ -1249,11 +1248,6 @@ int tcp_v4_rcv(struct sk_buff *skb) struct sock *nsk; sk = req->rsk_listener; - if (unlikely(tcp_v4_inbound_md5_hash(sk, skb))) { - sk_drops_add(sk, skb); - reqsk_put(req); - goto discard_it; - } if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup;
@@ -1293,9 +1287,6 @@ int tcp_v4_rcv(struct sk_buff *skb) if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; - if (tcp_v4_inbound_md5_hash(sk, skb)) - goto discard_and_relse; - nf_reset(skb); if (tcp_filter(sk, skb))
diff --git a/net/ipv4/tcp_md5.c b/net/ipv4/tcp_md5.c
index 052f5a587783..723320d0741a 100644
--- a/net/ipv4/tcp_md5.c
+++ b/net/ipv4/tcp_md5.c@@ -29,6 +29,10 @@ static DEFINE_PER_CPU(struct tcp_md5sig_pool, tcp_md5sig_pool); static DEFINE_MUTEX(tcp_md5sig_mutex); static bool tcp_md5sig_pool_populated; +static bool tcp_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb, + struct tcp_options_received *opt_rx, + struct tcp_extopt_store *store); + static unsigned int tcp_md5_extopt_prepare(struct sk_buff *skb, u8 flags, unsigned int remaining, struct tcp_out_options *opts,
@@ -76,6 +80,7 @@ struct tcp_md5_extopt { static const struct tcp_extopt_ops tcp_md5_extra_ops = { .option_kind = TCPOPT_MD5SIG, + .check = tcp_inbound_md5_hash, .prepare = tcp_md5_extopt_prepare, .write = tcp_md5_extopt_write, .response_prepare = tcp_md5_send_response_prepare,
@@ -863,8 +868,8 @@ static struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk, } /* Called with rcu_read_lock() */ -bool tcp_v4_inbound_md5_hash(const struct sock *sk, - const struct sk_buff *skb) +static bool tcp_v4_inbound_md5_hash(const struct sock *sk, + const struct sk_buff *skb) { /* This gets called for each TCP segment that arrives * so we want to be efficient.
@@ -918,8 +923,8 @@ bool tcp_v4_inbound_md5_hash(const struct sock *sk, } #if IS_ENABLED(CONFIG_IPV6) -bool tcp_v6_inbound_md5_hash(const struct sock *sk, - const struct sk_buff *skb) +static bool tcp_v6_inbound_md5_hash(const struct sock *sk, + const struct sk_buff *skb) { const __u8 *hash_location = NULL; struct tcp_md5sig_key *hash_expected;
@@ -961,7 +966,6 @@ bool tcp_v6_inbound_md5_hash(const struct sock *sk, return false; } -EXPORT_SYMBOL_GPL(tcp_v6_inbound_md5_hash); static struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk, const struct sock *addr_sk)
@@ -971,6 +975,21 @@ static struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk, EXPORT_SYMBOL_GPL(tcp_v6_md5_lookup); #endif +static bool tcp_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb, + struct tcp_options_received *opt_rx, + struct tcp_extopt_store *store) +{ + if (skb->protocol == htons(ETH_P_IP)) { + return tcp_v4_inbound_md5_hash(sk, skb); +#if IS_ENABLED(CONFIG_IPV6) + } else { + return tcp_v6_inbound_md5_hash(sk, skb); +#endif + } + + return false; +} + static void tcp_diag_md5sig_fill(struct tcp_diag_md5sig *info, const struct tcp_md5sig_key *key) {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 890616fc5591..f5dc730d3abc 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c@@ -43,7 +43,6 @@ #include <linux/ipv6.h> #include <linux/icmpv6.h> #include <linux/random.h> -#include <linux/tcp_md5.h> #include <net/tcp.h> #include <net/ndisc.h>
@@ -1173,11 +1172,6 @@ static int tcp_v6_rcv(struct sk_buff *skb) struct sock *nsk; sk = req->rsk_listener; - if (tcp_v6_inbound_md5_hash(sk, skb)) { - sk_drops_add(sk, skb); - reqsk_put(req); - goto discard_it; - } if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup;
@@ -1214,9 +1208,6 @@ static int tcp_v6_rcv(struct sk_buff *skb) if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; - if (tcp_v6_inbound_md5_hash(sk, skb)) - goto discard_and_relse; - if (tcp_filter(sk, skb)) goto discard_and_relse; th = (const struct tcphdr *)skb->data;
--
2.15.0