]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mptcp: handle consistently DSS corruption
authorPaolo Abeni <pabeni@redhat.com>
Sat, 19 Oct 2024 10:29:08 +0000 (12:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Oct 2024 13:39:29 +0000 (15:39 +0200)
commit e32d262c89e2b22cb0640223f953b548617ed8a6 upstream.

Bugged peer implementation can send corrupted DSS options, consistently
hitting a few warning in the data path. Use DEBUG_NET assertions, to
avoid the splat on some builds and handle consistently the error, dumping
related MIBs and performing fallback and/or reset according to the
subflow type.

Fixes: 6771bfd9ee24 ("mptcp: update mptcp ack sequence from work queue")
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20241008-net-mptcp-fallback-fixes-v1-1-c6fb8e93e551@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Conflicts in mib.[ch], because commit 104125b82e5c ("mptcp: add mib
  for infinite map sending") is linked to a new feature, not available
  in this version. Resolving the conflicts is easy, simply adding the
  new lines declaring the new "DSS corruptions" MIB entries.
  Also removed in protocol.c and subflow.c all DEBUG_NET_WARN_ON_ONCE
  because they are not defined in this version: enough with the MIB
  counters that have been added in this commit. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/mptcp/mib.c
net/mptcp/mib.h
net/mptcp/protocol.c
net/mptcp/subflow.c

index f4034e000f3ef6eed92475553933e218f9f24e0c..44d083958d8e59b423e2abd106c927e715a56d28 100644 (file)
@@ -23,6 +23,8 @@ static const struct snmp_mib mptcp_snmp_list[] = {
        SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX),
        SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC),
        SNMP_MIB_ITEM("DSSNotMatching", MPTCP_MIB_DSSNOMATCH),
+       SNMP_MIB_ITEM("DSSCorruptionFallback", MPTCP_MIB_DSSCORRUPTIONFALLBACK),
+       SNMP_MIB_ITEM("DSSCorruptionReset", MPTCP_MIB_DSSCORRUPTIONRESET),
        SNMP_MIB_ITEM("InfiniteMapRx", MPTCP_MIB_INFINITEMAPRX),
        SNMP_MIB_ITEM("OFOQueueTail", MPTCP_MIB_OFOQUEUETAIL),
        SNMP_MIB_ITEM("OFOQueue", MPTCP_MIB_OFOQUEUE),
index a9f43ff00b3c8d82b8da994dce7351e577feca89..0e17e1cebdbcfdc20c300cf4928cefd3a5e1c10c 100644 (file)
@@ -16,6 +16,8 @@ enum linux_mptcp_mib_field {
        MPTCP_MIB_JOINACKRX,            /* Received an ACK + MP_JOIN */
        MPTCP_MIB_JOINACKMAC,           /* HMAC was wrong on ACK + MP_JOIN */
        MPTCP_MIB_DSSNOMATCH,           /* Received a new mapping that did not match the previous one */
+       MPTCP_MIB_DSSCORRUPTIONFALLBACK,/* DSS corruption detected, fallback */
+       MPTCP_MIB_DSSCORRUPTIONRESET,   /* DSS corruption detected, MPJ subflow reset */
        MPTCP_MIB_INFINITEMAPRX,        /* Received an infinite mapping */
        MPTCP_MIB_OFOQUEUETAIL, /* Segments inserted into OoO queue tail */
        MPTCP_MIB_OFOQUEUE,             /* Segments inserted into OoO queue */
index 24a21ff0cb8a8aa25ee59ea9a24029e43a507c18..8558309a2d3fd3685d3968322199956a2e3de377 100644 (file)
@@ -457,6 +457,18 @@ static void mptcp_check_data_fin(struct sock *sk)
        }
 }
 
+static void mptcp_dss_corruption(struct mptcp_sock *msk, struct sock *ssk)
+{
+       if (READ_ONCE(msk->allow_infinite_fallback)) {
+               MPTCP_INC_STATS(sock_net(ssk),
+                               MPTCP_MIB_DSSCORRUPTIONFALLBACK);
+               mptcp_do_fallback(ssk);
+       } else {
+               MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSCORRUPTIONRESET);
+               mptcp_subflow_reset(ssk);
+       }
+}
+
 static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
                                           struct sock *ssk,
                                           unsigned int *bytes)
@@ -519,10 +531,12 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
                                moved += len;
                        seq += len;
 
-                       if (WARN_ON_ONCE(map_remaining < len))
-                               break;
+                       if (unlikely(map_remaining < len))
+                               mptcp_dss_corruption(msk, ssk);
                } else {
-                       WARN_ON_ONCE(!fin);
+                       if (unlikely(!fin))
+                               mptcp_dss_corruption(msk, ssk);
+
                        sk_eat_skb(ssk, skb);
                        done = true;
                }
index 0c020ca463f43f664f97de6d5469e9aa45cdec0d..c3434069fb0a53a22864fd14685944b6d16bb535 100644 (file)
@@ -702,7 +702,7 @@ static bool skb_is_fully_mapped(struct sock *ssk, struct sk_buff *skb)
        unsigned int skb_consumed;
 
        skb_consumed = tcp_sk(ssk)->copied_seq - TCP_SKB_CB(skb)->seq;
-       if (WARN_ON_ONCE(skb_consumed >= skb->len))
+       if (unlikely(skb_consumed >= skb->len))
                return true;
 
        return skb->len - skb_consumed <= subflow->map_data_len -