From 017512a07e15b66472946cf5e6f4b4511e7cf898 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Mon, 5 Oct 2020 12:01:06 +0200 Subject: [PATCH] mptcp: more DATA FIN fixes Currently data fin on data packet are not handled properly: the 'rcv_data_fin_seq' field is interpreted as the last sequence number carrying a valid data, but for data fin packet with valid maps we currently store map_seq + map_len, that is, the next value. The 'write_seq' fields carries instead the value subseguent to the last valid byte, so in mptcp_write_data_fin() we never detect correctly the last DSS map. Fixes: 7279da6145bb ("mptcp: Use MPTCP-level flag for sending DATA_FIN") Fixes: 1a49b2c2a501 ("mptcp: Handle incoming 32-bit DATA_FIN values") Reviewed-by: Mat Martineau Signed-off-by: Paolo Abeni Signed-off-by: David S. Miller --- net/mptcp/options.c | 10 +++++----- net/mptcp/subflow.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/mptcp/options.c b/net/mptcp/options.c index afa486912f5a..888bbbbb3e8a 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -451,7 +451,10 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb, static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow, struct sk_buff *skb, struct mptcp_ext *ext) { - u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq); + /* The write_seq value has already been incremented, so the actual + * sequence number for the DATA_FIN is one less. + */ + u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq) - 1; if (!ext->use_map || !skb->len) { /* RFC6824 requires a DSS mapping with specific values @@ -460,10 +463,7 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow, ext->data_fin = 1; ext->use_map = 1; ext->dsn64 = 1; - /* The write_seq value has already been incremented, so - * the actual sequence number for the DATA_FIN is one less. - */ - ext->data_seq = data_fin_tx_seq - 1; + ext->data_seq = data_fin_tx_seq; ext->subflow_seq = 0; ext->data_len = 1; } else if (ext->data_seq + ext->data_len == data_fin_tx_seq) { diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 5f2fa935022d..6f035af1c9d2 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -749,7 +749,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk, return MAPPING_DATA_FIN; } } else { - u64 data_fin_seq = mpext->data_seq + data_len; + u64 data_fin_seq = mpext->data_seq + data_len - 1; /* If mpext->data_seq is a 32-bit value, data_fin_seq * must also be limited to 32 bits.