From: Dmitry Safonov <dima@arista.com>
To: Eric Dumazet <edumazet@google.com>,
"David S. Miller" <davem@davemloft.net>,
linux-kernel@vger.kernel.org
Cc: Dmitry Safonov <dima@arista.com>,
Andy Lutomirski <luto@amacapital.net>,
Ard Biesheuvel <ardb@kernel.org>,
Bob Gilligan <gilligan@arista.com>,
David Ahern <dsahern@kernel.org>,
Dmitry Safonov <0x7f454c46@gmail.com>,
Eric Biggers <ebiggers@kernel.org>,
Francesco Ruggeri <fruggeri@arista.com>,
Herbert Xu <herbert@gondor.apana.org.au>,
Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>,
Ivan Delalande <colona@arista.com>,
Jakub Kicinski <kuba@kernel.org>,
Leonard Crestez <cdleonard@gmail.com>,
Paolo Abeni <pabeni@redhat.com>,
Salam Noureddine <noureddine@arista.com>,
Shuah Khan <shuah@kernel.org>,
netdev@vger.kernel.org, linux-crypto@vger.kernel.org
Subject: [PATCH 09/31] net/tcp: Prevent TCP-MD5 with TCP-AO being set
Date: Thu, 18 Aug 2022 17:59:43 +0100 [thread overview]
Message-ID: <20220818170005.747015-10-dima@arista.com> (raw)
In-Reply-To: <20220818170005.747015-1-dima@arista.com>
Be as conservative as possible: if there is TCP-MD5 key for a given peer
regardless of L3 interface - don't allow setting TCP-AO key for the same
peer. According to RFC5925, TCP-AO is supposed to replace TCP-MD5 and
there can't be any switch between both on any connected tuple.
Later it can be relaxed, if there's a use, but in the beginning restrict
any intersection.
Note: it's still should be possible to set both TCP-MD5 and TCP-AO keys
on a listening socket for *different* peers.
Co-developed-by: Francesco Ruggeri <fruggeri@arista.com>
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Co-developed-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
---
include/net/tcp.h | 23 +++++++++++++++++++++--
include/net/tcp_ao.h | 15 +++++++++++++++
net/ipv4/tcp_ao.c | 12 ++++++++++++
net/ipv4/tcp_ipv4.c | 10 ++++++++--
net/ipv4/tcp_output.c | 22 ++++++++++++++++++++++
net/ipv6/tcp_ao.c | 17 +++++++++++++++++
net/ipv6/tcp_ipv6.c | 22 ++++++++++++++++++----
7 files changed, 113 insertions(+), 8 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 278d0ab81796..9c71f48cc99c 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1670,14 +1670,23 @@ struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk,
extern struct static_key_false_deferred tcp_md5_needed;
struct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, int l3index,
const union tcp_md5_addr *addr,
- int family);
+ int family, bool any_l3index);
static inline struct tcp_md5sig_key *
tcp_md5_do_lookup(const struct sock *sk, int l3index,
const union tcp_md5_addr *addr, int family)
{
if (!static_branch_unlikely(&tcp_md5_needed.key))
return NULL;
- return __tcp_md5_do_lookup(sk, l3index, addr, family);
+ return __tcp_md5_do_lookup(sk, l3index, addr, family, false);
+}
+
+static inline struct tcp_md5sig_key *
+tcp_md5_do_lookup_any_l3index(const struct sock *sk,
+ const union tcp_md5_addr *addr, int family)
+{
+ if (!static_branch_unlikely(&tcp_md5_needed.key))
+ return NULL;
+ return __tcp_md5_do_lookup(sk, 0, addr, family, true);
}
enum skb_drop_reason
@@ -1695,6 +1704,13 @@ tcp_md5_do_lookup(const struct sock *sk, int l3index,
return NULL;
}
+static inline struct tcp_md5sig_key *
+tcp_md5_do_lookup_any_l3index(const struct sock *sk,
+ const union tcp_md5_addr *addr, int family)
+{
+ return NULL;
+}
+
static inline enum skb_drop_reason
tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb,
const void *saddr, const void *daddr,
@@ -2059,6 +2075,9 @@ struct tcp_sock_af_ops {
int optname,
sockptr_t optval,
int optlen);
+ struct tcp_ao_key *(*ao_lookup)(const struct sock *sk,
+ struct sock *addr_sk,
+ int sndid, int rcvid);
#endif
};
diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h
index 6d0d30e5542b..c550f1a6f5fd 100644
--- a/include/net/tcp_ao.h
+++ b/include/net/tcp_ao.h
@@ -91,12 +91,27 @@ struct tcp_ao_info {
int tcp_parse_ao(struct sock *sk, int cmd, unsigned short int family,
sockptr_t optval, int optlen);
void tcp_ao_destroy_sock(struct sock *sk);
+struct tcp_ao_key *tcp_ao_do_lookup(const struct sock *sk,
+ const union tcp_ao_addr *addr,
+ int family, int sndid, int rcvid, u16 port);
/* ipv4 specific functions */
int tcp_v4_parse_ao(struct sock *sk, int optname, sockptr_t optval, int optlen);
+struct tcp_ao_key *tcp_v4_ao_lookup(const struct sock *sk, struct sock *addr_sk,
+ int sndid, int rcvid);
/* ipv6 specific functions */
+struct tcp_ao_key *tcp_v6_ao_lookup(const struct sock *sk,
+ struct sock *addr_sk,
+ int sndid, int rcvid);
int tcp_v6_parse_ao(struct sock *sk, int cmd,
sockptr_t optval, int optlen);
#else
+static inline struct tcp_ao_key *tcp_ao_do_lookup(const struct sock *sk,
+ const union tcp_ao_addr *addr,
+ int family, int sndid, int rcvid, u16 port)
+{
+ return NULL;
+}
+
static inline void tcp_ao_destroy_sock(struct sock *sk)
{
}
diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c
index 7f53417ebdf7..be68eb6b4a92 100644
--- a/net/ipv4/tcp_ao.c
+++ b/net/ipv4/tcp_ao.c
@@ -176,6 +176,14 @@ void tcp_ao_destroy_sock(struct sock *sk)
kfree_rcu(ao, rcu);
}
+struct tcp_ao_key *tcp_v4_ao_lookup(const struct sock *sk, struct sock *addr_sk,
+ int sndid, int rcvid)
+{
+ union tcp_ao_addr *addr = (union tcp_ao_addr *)&addr_sk->sk_daddr;
+
+ return tcp_ao_do_lookup(sk, addr, AF_INET, sndid, rcvid, 0);
+}
+
static int tcp_ao_current_rnext(struct sock *sk, u16 tcpa_flags,
u8 tcpa_sndid, u8 tcpa_rcvid)
{
@@ -607,6 +615,10 @@ static int tcp_ao_add_cmd(struct sock *sk, unsigned short int family,
if (cmd.tcpa_keyflags & ~TCP_AO_KEYF_ALL)
return -EINVAL;
+ /* Don't allow keys for peers that have a matching TCP-MD5 key */
+ if (tcp_md5_do_lookup_any_l3index(sk, addr, family))
+ return -EKEYREJECTED;
+
ao_info = rcu_dereference_protected(tcp_sk(sk)->ao_info,
lockdep_sock_is_held(sk));
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 755154523ffc..fc65d64b9570 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1065,7 +1065,7 @@ static bool better_md5_match(struct tcp_md5sig_key *old, struct tcp_md5sig_key *
/* Find the Key structure for an address. */
struct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, int l3index,
const union tcp_md5_addr *addr,
- int family)
+ int family, bool any_l3index)
{
const struct tcp_sock *tp = tcp_sk(sk);
struct tcp_md5sig_key *key;
@@ -1084,7 +1084,8 @@ struct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, int l3index,
lockdep_sock_is_held(sk)) {
if (key->family != family)
continue;
- if (key->flags & TCP_MD5SIG_FLAG_IFINDEX && key->l3index != l3index)
+ if (!any_l3index && key->flags & TCP_MD5SIG_FLAG_IFINDEX &&
+ key->l3index != l3index)
continue;
if (family == AF_INET) {
mask = inet_make_mask(key->prefixlen);
@@ -1344,6 +1345,10 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, int optname,
if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
return -EINVAL;
+ /* Don't allow keys for peers that have a matching TCP-AO key */
+ if (tcp_ao_do_lookup(sk, addr, AF_INET, -1, -1, 0))
+ return -EKEYREJECTED;
+
return tcp_md5_do_add(sk, addr, AF_INET, prefixlen, l3index, flags,
cmd.tcpm_key, cmd.tcpm_keylen);
}
@@ -2239,6 +2244,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
.md5_parse = tcp_v4_parse_md5_keys,
#endif
#ifdef CONFIG_TCP_AO
+ .ao_lookup = tcp_v4_ao_lookup,
.ao_parse = tcp_v4_parse_ao,
#endif
};
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9e12845a8758..243ff6b99d17 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3837,6 +3837,28 @@ int tcp_connect(struct sock *sk)
tcp_call_bpf(sk, BPF_SOCK_OPS_TCP_CONNECT_CB, 0, NULL);
+#if defined(CONFIG_TCP_MD5SIG) && defined(CONFIG_TCP_AO)
+ /* Has to be checked late, after setting daddr/saddr/ops */
+ if (unlikely(rcu_dereference_protected(tp->md5sig_info,
+ lockdep_sock_is_held(sk)))) {
+ bool needs_md5 = !!tp->af_specific->md5_lookup(sk, sk);
+ bool needs_ao = !!tp->af_specific->ao_lookup(sk, sk, -1, -1);
+
+ if (needs_md5 && needs_ao)
+ return -EKEYREJECTED;
+ }
+#endif
+#ifdef CONFIG_TCP_AO
+ if (unlikely(rcu_dereference_protected(tp->ao_info,
+ lockdep_sock_is_held(sk)))) {
+ /* Don't allow connecting if ao is configured but no
+ * matching key is found.
+ */
+ if (tp->af_specific->ao_lookup(sk, sk, -1, -1) == NULL)
+ return -EKEYREJECTED;
+ }
+#endif
+
if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk))
return -EHOSTUNREACH; /* Routing failure or similar. */
diff --git a/net/ipv6/tcp_ao.c b/net/ipv6/tcp_ao.c
index f9f242a7e0f2..221b8adb4f73 100644
--- a/net/ipv6/tcp_ao.c
+++ b/net/ipv6/tcp_ao.c
@@ -13,6 +13,23 @@
#include <net/tcp.h>
#include <net/ipv6.h>
+struct tcp_ao_key *tcp_v6_ao_do_lookup(const struct sock *sk,
+ const struct in6_addr *addr,
+ int sndid, int rcvid)
+{
+ return tcp_ao_do_lookup(sk, (union tcp_ao_addr *)addr, AF_INET6,
+ sndid, rcvid, 0);
+}
+
+struct tcp_ao_key *tcp_v6_ao_lookup(const struct sock *sk,
+ struct sock *addr_sk,
+ int sndid, int rcvid)
+{
+ struct in6_addr *addr = &addr_sk->sk_v6_daddr;
+
+ return tcp_v6_ao_do_lookup(sk, addr, sndid, rcvid);
+}
+
int tcp_v6_parse_ao(struct sock *sk, int cmd,
sockptr_t optval, int optlen)
{
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 741cbeb52117..f5780a3fbd1b 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -602,6 +602,7 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
{
struct tcp_md5sig cmd;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
+ union tcp_ao_addr *addr;
int l3index = 0;
u8 prefixlen;
u8 flags;
@@ -656,13 +657,24 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
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],
+ if (ipv6_addr_v4mapped(&sin6->sin6_addr)) {
+ addr = (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3];
+
+ /* Don't allow keys for peers that have a matching TCP-AO key */
+ if (tcp_ao_do_lookup(sk, addr, AF_INET, -1, -1, 0))
+ return -EKEYREJECTED;
+ return tcp_md5_do_add(sk, addr,
AF_INET, prefixlen, l3index, flags,
cmd.tcpm_key, cmd.tcpm_keylen);
+ }
+
+ addr = (union tcp_md5_addr *)&sin6->sin6_addr;
+
+ /* Don't allow keys for peers that have a matching TCP-AO key */
+ if (tcp_ao_do_lookup(sk, addr, AF_INET6, -1, -1, 0))
+ return -EKEYREJECTED;
- return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
- AF_INET6, prefixlen, l3index, flags,
+ return tcp_md5_do_add(sk, addr, AF_INET6, prefixlen, l3index, flags,
cmd.tcpm_key, cmd.tcpm_keylen);
}
@@ -1891,6 +1903,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
.md5_parse = tcp_v6_parse_md5_keys,
#endif
#ifdef CONFIG_TCP_AO
+ .ao_lookup = tcp_v6_ao_lookup,
.ao_parse = tcp_v6_parse_ao,
#endif
};
@@ -1922,6 +1935,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
.md5_parse = tcp_v6_parse_md5_keys,
#endif
#ifdef CONFIG_TCP_AO
+ .ao_lookup = tcp_v6_ao_lookup,
.ao_parse = tcp_v6_parse_ao,
#endif
};
--
2.37.2
next prev parent reply other threads:[~2022-08-18 17:01 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-18 16:59 [PATCH 00/31] net/tcp: Add TCP-AO support Dmitry Safonov
2022-08-18 16:59 ` [PATCH 01/31] crypto: Introduce crypto_pool Dmitry Safonov
2022-08-18 16:59 ` [PATCH 02/31] crypto_pool: Add crypto_pool_reserve_scratch() Dmitry Safonov
2022-08-22 10:45 ` Dan Carpenter
2022-08-26 14:42 ` Dmitry Safonov
2022-08-18 16:59 ` [PATCH 03/31] net/tcp: Separate tcp_md5sig_info allocation into tcp_md5sig_info_add() Dmitry Safonov
2022-08-18 16:59 ` [PATCH 04/31] net/tcp: Disable TCP-MD5 static key on tcp_md5sig_info destruction Dmitry Safonov
2022-08-18 16:59 ` [PATCH 05/31] net/tcp: Use crypto_pool for TCP-MD5 Dmitry Safonov
2022-08-18 16:59 ` [PATCH 06/31] net/ipv6: sr: Switch to using crypto_pool Dmitry Safonov
2022-08-18 16:59 ` [PATCH 07/31] tcp: Add TCP-AO config and structures Dmitry Safonov
2022-08-18 16:59 ` [PATCH 08/31] net/tcp: Introduce TCP_AO setsockopt()s Dmitry Safonov
2022-08-18 18:50 ` kernel test robot
2022-08-18 18:50 ` kernel test robot
2022-08-23 14:45 ` Leonard Crestez
2022-08-31 18:48 ` Dmitry Safonov
2022-09-03 9:35 ` Leonard Crestez
2022-08-25 15:31 ` David Ahern
2022-08-25 18:21 ` David Laight
2022-08-18 16:59 ` Dmitry Safonov [this message]
2022-08-18 16:59 ` [PATCH 10/31] net/tcp: Calculate TCP-AO traffic keys Dmitry Safonov
2022-08-18 16:59 ` [PATCH 11/31] net/tcp: Add TCP-AO sign to outgoing packets Dmitry Safonov
2022-08-22 12:03 ` [kbuild] " Dan Carpenter
2022-08-29 17:55 ` Dmitry Safonov
2022-08-18 16:59 ` [PATCH 12/31] net/tcp: Add tcp_parse_auth_options() Dmitry Safonov
2022-08-18 19:00 ` kernel test robot
2022-08-18 16:59 ` [PATCH 13/31] net/tcp: Add AO sign to RST packets Dmitry Safonov
2022-08-18 16:59 ` [PATCH 14/31] net/tcp: Add TCP-AO sign to twsk Dmitry Safonov
2022-08-18 16:59 ` [PATCH 15/31] net/tcp: Wire TCP-AO to request sockets Dmitry Safonov
2022-08-18 16:59 ` [PATCH 16/31] net/tcp: Sign SYN-ACK segments with TCP-AO Dmitry Safonov
2022-08-18 16:59 ` [PATCH 17/31] net/tcp: Verify inbound TCP-AO signed segments Dmitry Safonov
2022-08-18 16:59 ` [PATCH 18/31] net/tcp: Add TCP-AO segments counters Dmitry Safonov
2022-08-18 16:59 ` [PATCH 19/31] net/tcp: Add TCP-AO SNE support Dmitry Safonov
2022-08-23 14:50 ` Leonard Crestez
2022-08-23 22:40 ` Francesco Ruggeri
2022-08-18 16:59 ` [PATCH 20/31] net/tcp: Add tcp_hash_fail() ratelimited logs Dmitry Safonov
2022-08-18 16:59 ` [PATCH 21/31] net/tcp: Ignore specific ICMPs for TCP-AO connections Dmitry Safonov
2022-08-18 16:59 ` [PATCH 22/31] net/tcp: Add option for TCP-AO to (not) hash header Dmitry Safonov
2022-08-18 16:59 ` [PATCH 23/31] net/tcp: Add getsockopt(TCP_AO_GET) Dmitry Safonov
2022-08-23 14:45 ` Leonard Crestez
2022-08-18 16:59 ` [PATCH 24/31] net/tcp: Allow asynchronous delete for TCP-AO keys (MKTs) Dmitry Safonov
2022-08-18 16:59 ` [PATCH 25/31] selftests/net: Add TCP-AO library Dmitry Safonov
2022-08-23 15:47 ` Shuah Khan
2022-09-05 20:24 ` Dmitry Safonov
2022-09-06 16:34 ` Dmitry Safonov
2022-08-18 17:00 ` [PATCH 26/31] selftests/net: Verify that TCP-AO complies with ignoring ICMPs Dmitry Safonov
2022-08-18 17:00 ` [PATCH 27/31] selftest/net: Add TCP-AO ICMPs accept test Dmitry Safonov
2022-08-18 17:00 ` [PATCH 28/31] selftest/tcp-ao: Add a test for MKT matching Dmitry Safonov
2022-08-18 17:00 ` [PATCH 29/31] selftest/tcp-ao: Add test for TCP-AO add setsockopt() command Dmitry Safonov
2022-08-18 17:00 ` [PATCH 30/31] selftests/tcp-ao: Add TCP-AO + TCP-MD5 + no sign listen socket tests Dmitry Safonov
2022-08-18 17:00 ` [PATCH 31/31] selftests/aolib: Add test/benchmark for removing MKTs Dmitry Safonov
2022-08-21 20:34 ` [PATCH 00/31] net/tcp: Add TCP-AO support Leonard Crestez
2022-08-21 23:51 ` David Ahern
2022-08-22 20:35 ` Dmitry Safonov
2022-08-23 15:30 ` Leonard Crestez
2022-08-23 16:31 ` Dmitry Safonov
2022-08-24 12:46 ` Andrew Lunn
2022-08-24 17:55 ` Jakub Kicinski
2022-08-27 8:55 ` Leonard Crestez
2022-08-22 18:42 ` Salam Noureddine
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220818170005.747015-10-dima@arista.com \
--to=dima@arista.com \
--cc=0x7f454c46@gmail.com \
--cc=ardb@kernel.org \
--cc=cdleonard@gmail.com \
--cc=colona@arista.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=ebiggers@kernel.org \
--cc=edumazet@google.com \
--cc=fruggeri@arista.com \
--cc=gilligan@arista.com \
--cc=herbert@gondor.apana.org.au \
--cc=kuba@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=netdev@vger.kernel.org \
--cc=noureddine@arista.com \
--cc=pabeni@redhat.com \
--cc=shuah@kernel.org \
--cc=yoshfuji@linux-ipv6.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).