lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v5 20/20] tcp: authopt: Try to respect rnextkeyid from SYN on SYNACK
Date
According to the RFC we should use the key that the peer suggests via
rnextkeyid.

This is currently done by storing recv_rnextkeyid in tcp_authopt_info
but this does not work for the SYNACK case because the tcp_request_sock
does not hold an info pointer for reasons of memory usage.

Handle this by storing recv_rnextkeyid inside tcp_request_sock. This
doesn't increase the memory usage because there are unused bytes at the
end.

Signed-off-by: Leonard Crestez <cdleonard@gmail.com>
---
include/linux/tcp.h | 6 ++++++
net/ipv4/tcp_authopt.c | 26 ++++++++++++++++++++------
net/ipv4/tcp_input.c | 12 ++++++++++++
3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 497604176119..0c346c2c2145 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -95,10 +95,13 @@ struct tcp_options_received {
u8 saw_unknown:1, /* Received unknown option */
unused:7;
u8 num_sacks; /* Number of SACK blocks */
u16 user_mss; /* mss requested by user in ioctl */
u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
+#if IS_ENABLED(CONFIG_TCP_AUTHOPT)
+ u8 rnextkeyid;
+#endif
};

static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
{
rx_opt->tstamp_ok = rx_opt->sack_ok = 0;
@@ -133,10 +136,13 @@ struct tcp_request_sock {
u32 rcv_nxt; /* the ack # by SYNACK. For
* FastOpen it's the seq#
* after data-in-SYN.
*/
u8 syn_tos;
+#if IS_ENABLED(CONFIG_TCP_AUTHOPT)
+ u8 recv_rnextkeyid;
+#endif
};

static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
{
return (struct tcp_request_sock *)req;
diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c
index 5ea93eb495f1..4b316488c805 100644
--- a/net/ipv4/tcp_authopt.c
+++ b/net/ipv4/tcp_authopt.c
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later

+#include "linux/tcp.h"
+#include "net/tcp_states.h"
#include <net/tcp_authopt.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/tcp.h>
#include <linux/kref.h>
@@ -424,21 +426,33 @@ struct tcp_authopt_key_info *__tcp_authopt_select_key(const struct sock *sk,
{
struct tcp_authopt_key_info *key, *new_key = NULL;
struct netns_tcp_authopt *net = sock_net_tcp_authopt(sk);

/* Listen sockets don't refer to any specific connection so we don't try
- * to keep using the same key and ignore any received keyids.
+ * to keep using the same key.
+ * The rnextkeyid is stored in tcp_request_sock
*/
if (sk->sk_state == TCP_LISTEN) {
- int send_keyid = -1;
-
+ int send_id = -1;
+ struct tcp_request_sock *rsk;
+
+ if (WARN_ONCE(addr_sk->sk_state != TCP_NEW_SYN_RECV, "bad socket state"))
+ return NULL;
+ rsk = tcp_rsk((struct request_sock *)addr_sk);
+ /* Forcing a specific send_keyid on a listen socket forces it for
+ * all clients so is unlikely to be useful.
+ */
if (info->flags & TCP_AUTHOPT_FLAG_LOCK_KEYID)
- send_keyid = info->send_keyid;
- key = tcp_authopt_lookup_send(net, addr_sk, send_keyid);
+ send_id = info->send_keyid;
+ else
+ send_id = rsk->recv_rnextkeyid;
+ key = tcp_authopt_lookup_send(net, addr_sk, send_id);
+ /* If no key found with specific send_id try anything else. */
+ if (!key)
+ key = tcp_authopt_lookup_send(net, addr_sk, -1);
if (key)
*rnextkeyid = key->recv_id;
-
return key;
}

if (locked) {
sock_owned_by_me(sk);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 91f1b04c1933..667da79df4ae 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4094,10 +4094,18 @@ void tcp_parse_options(const struct net *net,
/*
* The MD5 Hash has already been
* checked (see tcp_v{4,6}_do_rcv()).
*/
break;
+#endif
+#ifdef CONFIG_TCP_AUTHOPT
+ case TCPOPT_AUTHOPT:
+ /* Hash has already been checked.
+ * We parse rnextkeyid here so we can match it on synack
+ */
+ opt_rx->rnextkeyid = ptr[1];
+ break;
#endif
case TCPOPT_FASTOPEN:
tcp_parse_fastopen_option(
opsize - TCPOLEN_FASTOPEN_BASE,
ptr, th->syn, foc, false);
@@ -6891,10 +6899,14 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
tcp_clear_options(&tmp_opt);

if (IS_ENABLED(CONFIG_SMC) && want_cookie)
tmp_opt.smc_ok = 0;

+#if IS_ENABLED(CONFIG_TCP_AUTHOPT)
+ tcp_rsk(req)->recv_rnextkeyid = tmp_opt.rnextkeyid;
+#endif
+
tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
tcp_openreq_init(req, &tmp_opt, skb, sk);
inet_rsk(req)->no_srccheck = inet_sk(sk)->transparent;

/* Note: tcp_v6_init_req() might override ir_iif for link locals */
--
2.25.1
\
 
 \ /
  Last update: 2022-01-24 13:17    [W:0.109 / U:0.084 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site