All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leonard Crestez <cdleonard@gmail.com>
To: David Ahern <dsahern@kernel.org>, Shuah Khan <shuah@kernel.org>,
	Dmitry Safonov <0x7f454c46@gmail.com>,
	Eric Dumazet <edumazet@google.com>
Cc: "David S. Miller" <davem@davemloft.net>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	Kuniyuki Iwashima <kuniyu@amazon.co.jp>,
	Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>,
	Jakub Kicinski <kuba@kernel.org>,
	Yuchung Cheng <ycheng@google.com>,
	Francesco Ruggeri <fruggeri@arista.com>,
	Mat Martineau <mathew.j.martineau@linux.intel.com>,
	Christoph Paasch <cpaasch@apple.com>,
	Ivan Delalande <colona@arista.com>,
	Priyaranjan Jha <priyarjha@google.com>,
	netdev@vger.kernel.org, linux-crypto@vger.kernel.org,
	linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 21/25] tcp: authopt: Add initial l3index support
Date: Mon,  1 Nov 2021 18:34:56 +0200	[thread overview]
Message-ID: <4e049d1ade4be3010b4ea63daf2ef3bed4e1892b.1635784253.git.cdleonard@gmail.com> (raw)
In-Reply-To: <cover.1635784253.git.cdleonard@gmail.com>

This is a parallel feature to tcp_md5sig.tcpm_ifindex support and allows
applications to server multiple VRFs with a single socket.

The ifindex argument must be the ifindex of a VRF device and must match
exactly, keys with ifindex == 0 (outside of VRF) will not match for
connections inside a VRF.

Keys without the TCP_AUTHOPT_KEY_IFINDEX will ignore ifindex and match
both inside and outside VRF.

Signed-off-by: Leonard Crestez <cdleonard@gmail.com>
---
 include/net/tcp_authopt.h |  2 ++
 include/uapi/linux/tcp.h  | 11 ++++++
 net/ipv4/tcp_authopt.c    | 76 +++++++++++++++++++++++++++++++++++----
 3 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/include/net/tcp_authopt.h b/include/net/tcp_authopt.h
index 9341e10ef542..072d5383f14b 100644
--- a/include/net/tcp_authopt.h
+++ b/include/net/tcp_authopt.h
@@ -39,10 +39,12 @@ struct tcp_authopt_key_info {
 	u8 alg_id;
 	/** @keylen: Same as &tcp_authopt_key.keylen */
 	u8 keylen;
 	/** @key: Same as &tcp_authopt_key.key */
 	u8 key[TCP_AUTHOPT_MAXKEYLEN];
+	/** @l3index: Same as &tcp_authopt_key.ifindex */
+	int l3index;
 	/** @addr: Same as &tcp_authopt_key.addr */
 	struct sockaddr_storage addr;
 	/** @alg: Algorithm implementation matching alg_id */
 	struct tcp_authopt_alg_imp *alg;
 };
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index e02176390519..a7f5f918ed5a 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -400,15 +400,17 @@ struct tcp_authopt {
  * enum tcp_authopt_key_flag - flags for `tcp_authopt.flags`
  *
  * @TCP_AUTHOPT_KEY_DEL: Delete the key and ignore non-id fields
  * @TCP_AUTHOPT_KEY_EXCLUDE_OPTS: Exclude TCP options from signature
  * @TCP_AUTHOPT_KEY_ADDR_BIND: Key only valid for `tcp_authopt.addr`
+ * @TCP_AUTHOPT_KEY_IFINDEX: Key only valid for `tcp_authopt.ifindex`
  */
 enum tcp_authopt_key_flag {
 	TCP_AUTHOPT_KEY_DEL = (1 << 0),
 	TCP_AUTHOPT_KEY_EXCLUDE_OPTS = (1 << 1),
 	TCP_AUTHOPT_KEY_ADDR_BIND = (1 << 2),
+	TCP_AUTHOPT_KEY_IFINDEX = (1 << 3),
 };
 
 /**
  * enum tcp_authopt_alg - Algorithms for TCP Authentication Option
  */
@@ -450,10 +452,19 @@ struct tcp_authopt_key {
 	 * @addr: Key is only valid for this address
 	 *
 	 * Ignored unless TCP_AUTHOPT_KEY_ADDR_BIND flag is set
 	 */
 	struct __kernel_sockaddr_storage addr;
+	/**
+	 * @ifindex: ifindex of vrf (l3mdev_master) interface
+	 *
+	 * If the TCP_AUTHOPT_KEY_IFINDEX flag is set then key only applies for
+	 * connections through this interface. Interface must be an vrf master.
+	 *
+	 * This is similar to `tcp_msg5sig.tcpm_ifindex`
+	 */
+	int	ifindex;
 };
 
 /* setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) */
 
 #define TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT 0x1
diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c
index a02fe0d14b63..f497537ce16c 100644
--- a/net/ipv4/tcp_authopt.c
+++ b/net/ipv4/tcp_authopt.c
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include "linux/net.h"
 #include <linux/kernel.h>
 #include <net/tcp.h>
 #include <net/tcp_authopt.h>
 #include <crypto/hash.h>
 
@@ -190,10 +191,14 @@ static bool tcp_authopt_key_match_exact(struct tcp_authopt_key_info *info,
 {
 	if (info->send_id != key->send_id)
 		return false;
 	if (info->recv_id != key->recv_id)
 		return false;
+	if ((info->flags & TCP_AUTHOPT_KEY_IFINDEX) != (key->flags & TCP_AUTHOPT_KEY_IFINDEX))
+		return false;
+	if ((info->flags & TCP_AUTHOPT_KEY_IFINDEX) && info->l3index != key->ifindex)
+		return false;
 	if ((info->flags & TCP_AUTHOPT_KEY_ADDR_BIND) != (key->flags & TCP_AUTHOPT_KEY_ADDR_BIND))
 		return false;
 	if (info->flags & TCP_AUTHOPT_KEY_ADDR_BIND)
 		if (!ipvx_addr_match(&info->addr, &key->addr))
 			return false;
@@ -257,26 +262,49 @@ static struct tcp_authopt_key_info *tcp_authopt_key_lookup_exact(const struct so
 			return key_info;
 
 	return NULL;
 }
 
+static bool better_key_match(struct tcp_authopt_key_info *old, struct tcp_authopt_key_info *new)
+{
+	if (!old)
+		return true;
+
+	/* l3index always overrides non-l3index */
+	if (old->l3index && new->l3index == 0)
+		return false;
+	if (old->l3index == 0 && new->l3index)
+		return true;
+
+	return false;
+}
+
 static struct tcp_authopt_key_info *tcp_authopt_lookup_send(struct tcp_authopt_info *info,
 							    const struct sock *addr_sk,
 							    int send_id)
 {
 	struct tcp_authopt_key_info *result = NULL;
 	struct tcp_authopt_key_info *key;
+	int l3index = -1;
 
 	hlist_for_each_entry_rcu(key, &info->head, node, 0) {
 		if (send_id >= 0 && key->send_id != send_id)
 			continue;
 		if (key->flags & TCP_AUTHOPT_KEY_ADDR_BIND)
 			if (!tcp_authopt_key_match_sk_addr(key, addr_sk))
 				continue;
-		if (result && net_ratelimit())
-			pr_warn("ambiguous tcp authentication keys configured for send\n");
-		result = key;
+		if (key->flags & TCP_AUTHOPT_KEY_IFINDEX) {
+			if (l3index < 0)
+				l3index = l3mdev_master_ifindex_by_index(sock_net(addr_sk),
+									 addr_sk->sk_bound_dev_if);
+			if (l3index != key->l3index)
+				continue;
+		}
+		if (better_key_match(result, key))
+			result = key;
+		else if (result)
+			net_warn_ratelimited("ambiguous tcp authentication keys configured for send\n");
 	}
 
 	return result;
 }
 
@@ -527,18 +555,20 @@ void tcp_authopt_clear(struct sock *sk)
 }
 
 #define TCP_AUTHOPT_KEY_KNOWN_FLAGS ( \
 	TCP_AUTHOPT_KEY_DEL | \
 	TCP_AUTHOPT_KEY_EXCLUDE_OPTS | \
-	TCP_AUTHOPT_KEY_ADDR_BIND)
+	TCP_AUTHOPT_KEY_ADDR_BIND | \
+	TCP_AUTHOPT_KEY_IFINDEX)
 
 int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen)
 {
 	struct tcp_authopt_key opt;
 	struct tcp_authopt_info *info;
 	struct tcp_authopt_key_info *key_info, *old_key_info;
 	struct tcp_authopt_alg_imp *alg;
+	int l3index = 0;
 	int err;
 
 	sock_owned_by_me(sk);
 	if (!sysctl_tcp_authopt)
 		return -EPERM;
@@ -584,10 +614,24 @@ int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen)
 		return -EINVAL;
 	err = tcp_authopt_alg_require(alg);
 	if (err)
 		return err;
 
+	/* check ifindex is valid (zero is always valid) */
+	if (opt.flags & TCP_AUTHOPT_KEY_IFINDEX && opt.ifindex) {
+		struct net_device *dev;
+
+		rcu_read_lock();
+		dev = dev_get_by_index_rcu(sock_net(sk), opt.ifindex);
+		if (dev && netif_is_l3_master(dev))
+			l3index = dev->ifindex;
+		rcu_read_unlock();
+
+		if (!l3index)
+			return -EINVAL;
+	}
+
 	key_info = sock_kmalloc(sk, sizeof(*key_info), GFP_KERNEL | __GFP_ZERO);
 	if (!key_info)
 		return -ENOMEM;
 	/* If an old key exists with exact ID then remove and replace.
 	 * RCU-protected readers might observe both and pick any.
@@ -601,10 +645,11 @@ int tcp_set_authopt_key(struct sock *sk, sockptr_t optval, unsigned int optlen)
 	key_info->alg_id = opt.alg;
 	key_info->alg = alg;
 	key_info->keylen = opt.keylen;
 	memcpy(key_info->key, opt.key, opt.keylen);
 	memcpy(&key_info->addr, &opt.addr, sizeof(key_info->addr));
+	key_info->l3index = l3index;
 	hlist_add_head_rcu(&key_info->node, &info->head);
 
 	return 0;
 }
 
@@ -1436,21 +1481,38 @@ static struct tcp_authopt_key_info *tcp_authopt_lookup_recv(struct sock *sk,
 							    struct tcp_authopt_info *info,
 							    int recv_id)
 {
 	struct tcp_authopt_key_info *result = NULL;
 	struct tcp_authopt_key_info *key;
+	int l3index = -1;
 
 	/* multiple matches will cause occasional failures */
 	hlist_for_each_entry_rcu(key, &info->head, node, 0) {
 		if (recv_id >= 0 && key->recv_id != recv_id)
 			continue;
 		if (key->flags & TCP_AUTHOPT_KEY_ADDR_BIND &&
 		    !tcp_authopt_key_match_skb_addr(key, skb))
 			continue;
-		if (result && net_ratelimit())
-			pr_warn("ambiguous tcp authentication keys configured for receive\n");
-		result = key;
+		if (key->flags & TCP_AUTHOPT_KEY_IFINDEX) {
+			if (l3index < 0) {
+				if (skb->protocol == htons(ETH_P_IP)) {
+					l3index = inet_sdif(skb) ? inet_iif(skb) : 0;
+				} else if (skb->protocol == htons(ETH_P_IPV6)) {
+					l3index = inet6_sdif(skb) ? inet6_iif(skb) : 0;
+				} else {
+					WARN_ONCE(1, "unexpected skb->protocol=%x", skb->protocol);
+					continue;
+				}
+			}
+
+			if (l3index != key->l3index)
+				continue;
+		}
+		if (better_key_match(result, key))
+			result = key;
+		else if (result)
+			net_warn_ratelimited("ambiguous tcp authentication keys configured for send\n");
 	}
 
 	return result;
 }
 
-- 
2.25.1


  parent reply	other threads:[~2021-11-01 16:37 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-01 16:34 [PATCH v2] tcp: Initial support for RFC5925 auth option Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 01/25] tcp: authopt: Initial support and key management Leonard Crestez
2021-11-03  2:29   ` David Ahern
2021-11-05 12:10     ` Leonard Crestez
2021-11-05  1:22   ` Dmitry Safonov
2021-11-05  7:04     ` Leonard Crestez
2021-11-05 14:50       ` Dmitry Safonov
2021-11-05 18:00         ` Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 02/25] docs: Add user documentation for tcp_authopt Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 03/25] selftests: Initial tcp_authopt test module Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 04/25] selftests: tcp_authopt: Initial sockopt manipulation Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 05/25] tcp: authopt: Add crypto initialization Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 06/25] tcp: authopt: Compute packet signatures Leonard Crestez
2021-11-05  1:53   ` Dmitry Safonov
2021-11-05  6:39     ` Leonard Crestez
2021-11-05  2:08   ` Dmitry Safonov
2021-11-05  6:09     ` Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 07/25] tcp: Use BIT() for OPTION_* constants Leonard Crestez
2021-11-03  2:31   ` David Ahern
2021-11-03 22:19     ` Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 08/25] tcp: authopt: Hook into tcp core Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 09/25] tcp: authopt: Disable via sysctl by default Leonard Crestez
2021-11-03  2:39   ` David Ahern
2021-11-05  8:50     ` Leonard Crestez
2021-11-05  1:46   ` Dmitry Safonov
2021-11-01 16:34 ` [PATCH v2 10/25] selftests: tcp_authopt: Test key address binding Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 11/25] tcp: authopt: Implement Sequence Number Extension Leonard Crestez
2021-11-01 19:22   ` Francesco Ruggeri
2021-11-02 10:03     ` Leonard Crestez
2021-11-02 19:21       ` Francesco Ruggeri
2021-11-03 22:01         ` Leonard Crestez
2021-11-01 20:54   ` Eric Dumazet
2021-11-02  9:50     ` Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 12/25] tcp: ipv6: Add AO signing for tcp_v6_send_response Leonard Crestez
2021-11-03  2:44   ` David Ahern
2021-11-03 22:09     ` Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 13/25] tcp: authopt: Add support for signing skb-less replies Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 14/25] tcp: ipv4: Add AO signing for " Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 15/25] selftests: tcp_authopt: Implement SNE in python Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 16/25] selftests: tcp_authopt: Add scapy-based packet signing code Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 17/25] selftests: tcp_authopt: Add packet-level tests Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 18/25] selftests: tcp_authopt: Initial sne test Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 19/25] tcp: authopt: Add key selection controls Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 20/25] selftests: tcp_authopt: Add tests for rollover Leonard Crestez
2021-11-01 16:34 ` Leonard Crestez [this message]
2021-11-03  3:06   ` [PATCH v2 21/25] tcp: authopt: Add initial l3index support David Ahern
2021-11-05 12:26     ` Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 22/25] selftests: tcp_authopt: Initial tests for l3mdev handling Leonard Crestez
2021-11-01 16:34 ` [PATCH v2 23/25] selftests: nettest: Rename md5_prefix to key_addr_prefix Leonard Crestez
2021-11-03  3:08   ` David Ahern
2021-11-01 16:34 ` [PATCH v2 24/25] selftests: nettest: Initial tcp_authopt support Leonard Crestez
2021-11-03  3:09   ` David Ahern
2021-11-01 16:35 ` [PATCH v2 25/25] selftests: net/fcnal: " Leonard Crestez
2021-11-03  3:18 ` [PATCH v2] tcp: Initial support for RFC5925 auth option David Ahern
2021-11-03 22:22   ` Leonard Crestez

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=4e049d1ade4be3010b4ea63daf2ef3bed4e1892b.1635784253.git.cdleonard@gmail.com \
    --to=cdleonard@gmail.com \
    --cc=0x7f454c46@gmail.com \
    --cc=colona@arista.com \
    --cc=cpaasch@apple.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=fruggeri@arista.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=kuba@kernel.org \
    --cc=kuniyu@amazon.co.jp \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mathew.j.martineau@linux.intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=priyarjha@google.com \
    --cc=shuah@kernel.org \
    --cc=ycheng@google.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.