lkml.org 
[lkml]   [2023]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v8 15/23] net/tcp: Add tcp_hash_fail() ratelimited logs
    Date
    Add a helper for logging connection-detailed messages for failed TCP
    hash verification (both MD5 and AO).

    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 | 14 ++++++++++++--
    include/net/tcp_ao.h | 29 +++++++++++++++++++++++++++++
    net/ipv4/tcp.c | 23 +++++++++++++----------
    net/ipv4/tcp_ao.c | 7 +++++++
    4 files changed, 61 insertions(+), 12 deletions(-)

    diff --git a/include/net/tcp.h b/include/net/tcp.h
    index 646aebc682f8..61dd9a8afaf1 100644
    --- a/include/net/tcp.h
    +++ b/include/net/tcp.h
    @@ -2610,12 +2610,18 @@ tcp_inbound_hash(struct sock *sk, const struct request_sock *req,
    int l3index;

    /* Invalid option or two times meet any of auth options */
    - if (tcp_parse_auth_options(th, &md5_location, &aoh))
    + if (tcp_parse_auth_options(th, &md5_location, &aoh)) {
    + tcp_hash_fail("TCP segment has incorrect auth options set",
    + family, skb, "");
    return SKB_DROP_REASON_TCP_AUTH_HDR;
    + }

    if (req) {
    if (tcp_rsk_used_ao(req) != !!aoh) {
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD);
    + tcp_hash_fail("TCP connection can't start/end using TCP-AO",
    + family, skb, "%s",
    + !aoh ? "missing AO" : "AO signed");
    return SKB_DROP_REASON_TCP_AOFAILURE;
    }
    }
    @@ -2632,10 +2638,14 @@ tcp_inbound_hash(struct sock *sk, const struct request_sock *req,
    * the last key is impossible to remove, so there's
    * always at least one current_key.
    */
    - if (tcp_ao_required(sk, saddr, family, true))
    + if (tcp_ao_required(sk, saddr, family, true)) {
    + tcp_hash_fail("AO hash is required, but not found",
    + family, skb, "L3 index %d", l3index);
    return SKB_DROP_REASON_TCP_AONOTFOUND;
    + }
    if (unlikely(tcp_md5_do_lookup(sk, l3index, saddr, family))) {
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
    + tcp_hash_fail("MD5 Hash not found", family, skb, "");
    return SKB_DROP_REASON_TCP_MD5NOTFOUND;
    }
    return SKB_NOT_DROPPED_YET;
    diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h
    index fc5674763730..801dca405df7 100644
    --- a/include/net/tcp_ao.h
    +++ b/include/net/tcp_ao.h
    @@ -119,6 +119,35 @@ struct tcp_ao_info {
    struct rcu_head rcu;
    };

    +#define tcp_hash_fail(msg, family, skb, fmt, ...) \
    +do { \
    + const struct tcphdr *th = tcp_hdr(skb); \
    + char hdr_flags[5] = {}; \
    + char *f = hdr_flags; \
    + \
    + if (th->fin) \
    + *f++ = 'F'; \
    + if (th->syn) \
    + *f++ = 'S'; \
    + if (th->rst) \
    + *f++ = 'R'; \
    + if (th->ack) \
    + *f++ = 'A'; \
    + if (f != hdr_flags) \
    + *f = ' '; \
    + if (family == AF_INET) { \
    + net_info_ratelimited("%s for (%pI4, %d)->(%pI4, %d) %s" fmt "\n", \
    + msg, &ip_hdr(skb)->saddr, ntohs(th->source), \
    + &ip_hdr(skb)->daddr, ntohs(th->dest), \
    + hdr_flags, ##__VA_ARGS__); \
    + } else { \
    + net_info_ratelimited("%s for [%pI6c]:%u->[%pI6c]:%u %s" fmt "\n", \
    + msg, &ipv6_hdr(skb)->saddr, ntohs(th->source), \
    + &ipv6_hdr(skb)->daddr, ntohs(th->dest), \
    + hdr_flags, ##__VA_ARGS__); \
    + } \
    +} while (0)
    +
    #ifdef CONFIG_TCP_AO
    /* TCP-AO structures and functions */

    diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
    index fcedec0ae08e..096c2f0949d3 100644
    --- a/net/ipv4/tcp.c
    +++ b/net/ipv4/tcp.c
    @@ -4376,7 +4376,6 @@ tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb,
    * o MD5 hash and we're not expecting one.
    * o MD5 hash and its wrong.
    */
    - const struct tcphdr *th = tcp_hdr(skb);
    const struct tcp_sock *tp = tcp_sk(sk);
    struct tcp_md5sig_key *key;
    int genhash;
    @@ -4386,6 +4385,7 @@ tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb,

    if (!key && hash_location) {
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
    + tcp_hash_fail("Unexpected MD5 Hash found", family, skb, "");
    return SKB_DROP_REASON_TCP_MD5UNEXPECTED;
    }

    @@ -4401,16 +4401,19 @@ tcp_inbound_md5_hash(const struct sock *sk, const struct sk_buff *skb,
    if (genhash || memcmp(hash_location, newhash, 16) != 0) {
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE);
    if (family == AF_INET) {
    - net_info_ratelimited("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s L3 index %d\n",
    - saddr, ntohs(th->source),
    - daddr, ntohs(th->dest),
    - genhash ? " tcp_v4_calc_md5_hash failed"
    - : "", l3index);
    + tcp_hash_fail("MD5 Hash failed", AF_INET, skb, "%s L3 index %d",
    + genhash ? "tcp_v4_calc_md5_hash failed"
    + : "", l3index);
    } else {
    - net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u L3 index %d\n",
    - genhash ? "failed" : "mismatch",
    - saddr, ntohs(th->source),
    - daddr, ntohs(th->dest), l3index);
    + if (genhash) {
    + tcp_hash_fail("MD5 Hash failed",
    + AF_INET6, skb, "L3 index %d",
    + l3index);
    + } else {
    + tcp_hash_fail("MD5 Hash mismatch",
    + AF_INET6, skb, "L3 index %d",
    + l3index);
    + }
    }
    return SKB_DROP_REASON_TCP_MD5FAILURE;
    }
    diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c
    index 5ebbfadfbfd0..9ee7fc9f6a76 100644
    --- a/net/ipv4/tcp_ao.c
    +++ b/net/ipv4/tcp_ao.c
    @@ -772,6 +772,8 @@ tcp_ao_verify_hash(const struct sock *sk, const struct sk_buff *skb,
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD);
    atomic64_inc(&info->counters.pkt_bad);
    atomic64_inc(&key->pkt_bad);
    + tcp_hash_fail("AO hash wrong length", family, skb,
    + "%u != %d", maclen, tcp_ao_maclen(key));
    return SKB_DROP_REASON_TCP_AOFAILURE;
    }

    @@ -786,6 +788,7 @@ tcp_ao_verify_hash(const struct sock *sk, const struct sk_buff *skb,
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOBAD);
    atomic64_inc(&info->counters.pkt_bad);
    atomic64_inc(&key->pkt_bad);
    + tcp_hash_fail("AO hash mismatch", family, skb, "");
    kfree(hash_buf);
    return SKB_DROP_REASON_TCP_AOFAILURE;
    }
    @@ -813,6 +816,8 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,
    info = rcu_dereference(tcp_sk(sk)->ao_info);
    if (!info) {
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOKEYNOTFOUND);
    + tcp_hash_fail("AO key not found", family, skb,
    + "keyid: %u", aoh->keyid);
    return SKB_DROP_REASON_TCP_AOUNEXPECTED;
    }

    @@ -915,6 +920,8 @@ tcp_inbound_ao_hash(struct sock *sk, const struct sk_buff *skb,
    key_not_found:
    NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAOKEYNOTFOUND);
    atomic64_inc(&info->counters.key_not_found);
    + tcp_hash_fail("Requested by the peer AO key id not found",
    + family, skb, "");
    return SKB_DROP_REASON_TCP_AOKEYNOTFOUND;
    }

    --
    2.41.0
    \
     
     \ /
      Last update: 2023-07-19 22:30    [W:6.929 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site