Skip to content

Commit

Permalink
mptcp: handle consistently DSS corruption
Browse files Browse the repository at this point in the history
commit e32d262 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: 6771bfd ("mptcp: update mptcp ack sequence from work queue")
Cc: [email protected]
Signed-off-by: Paolo Abeni <[email protected]>
Reviewed-by: Matthieu Baerts (NGI0) <[email protected]>
Signed-off-by: Matthieu Baerts (NGI0) <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
[ Conflicts in mib.[ch], because commit 104125b ("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) <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Paolo Abeni authored and gregkh committed Oct 22, 2024
1 parent 6654efe commit 12c1676
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 4 deletions.
2 changes: 2 additions & 0 deletions net/mptcp/mib.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,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("DSSNoMatchTCP", MPTCP_MIB_DSSTCPMISMATCH),
SNMP_MIB_ITEM("DataCsumErr", MPTCP_MIB_DATACSUMERR),
Expand Down
2 changes: 2 additions & 0 deletions net/mptcp/mib.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,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_DSSTCPMISMATCH, /* DSS-mapping did not map with TCP's sequence numbers */
MPTCP_MIB_DATACSUMERR, /* The data checksum fail */
Expand Down
20 changes: 17 additions & 3 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,18 @@ static bool mptcp_check_data_fin(struct sock *sk)
return ret;
}

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)
Expand Down Expand Up @@ -626,10 +638,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;
}
Expand Down
2 changes: 1 addition & 1 deletion net/mptcp/subflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,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 -
Expand Down

0 comments on commit 12c1676

Please sign in to comment.