Messages in this thread Patch in this message | | | From | Dmitry Safonov <> | Subject | [RFC 4/5] net/tcp-md5: Don't send RST if key (dis)appeared | Date | Tue, 9 May 2023 23:16:07 +0100 |
| |
Seems cheap at this place as both key and hash_location were looked up until now.
Signed-off-by: Dmitry Safonov <dima@arista.com> --- net/ipv4/tcp_ipv4.c | 10 ++++++++++ net/ipv6/tcp_ipv6.c | 8 ++++++++ 2 files changed, 18 insertions(+)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f5b870943dcb..d94cd5e70d58 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -686,6 +686,16 @@ static bool tcp_v4_md5_sign_reset(struct net *net, const struct sock *sk, l3index = tcp_v4_sdif(skb) ? inet_iif(skb) : 0; addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr; key = tcp_md5_do_lookup(sk, l3index, addr, AF_INET); + /* This segment should have been already verified by + * tcp_inbound_md5_hash(). But that might raced with userspace + * adding or deleting keys. So, follow the logic of + * tcp_inbound_md5_hash() and avoid replying with TCP-MD5 sign + * on non-signed segments and vice-versa. + */ + if (unlikely(!!key != !!hash_location)) { + rcu_read_unlock(); + return true; + } } else if (hash_location) { const union tcp_md5_addr *addr; int sdif = tcp_v4_sdif(skb); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3756a43367a3..498dfa194b8b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -993,6 +993,14 @@ static int tcp_v6_md5_lookup_reset_key(struct net *net, const struct sock *sk, */ l3index = tcp_v6_sdif(skb) ? tcp_v6_iif_l3_slave(skb) : 0; *key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr, l3index); + /* This segment should have been already verified by + * tcp_inbound_md5_hash(). But that might raced with userspace + * adding or deleting keys. So, follow the logic of + * tcp_inbound_md5_hash() and avoid replying with TCP-MD5 sign + * on non-signed segments and vice-versa. + */ + if (unlikely(!!*key != !!hash_location)) + return -ENOKEY; } else if (hash_location) { int dif = tcp_v6_iif_l3_slave(skb); int sdif = tcp_v6_sdif(skb); -- 2.40.0
| |