Skip to content

Commit

Permalink
tls: strp: make sure the TCP skbs do not have overlapping data
Browse files Browse the repository at this point in the history
[ Upstream commit 0d87bbd ]

TLS tries to get away with using the TCP input queue directly.
This does not work if there is duplicated data (multiple skbs
holding bytes for the same seq number range due to retransmits).
Check for this condition and fall back to copy mode, it should
be rare.

Fixes: 84c61fe ("tls: rx: do not use the standard strparser")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
kuba-moo authored and gregkh committed Oct 29, 2022
1 parent 5f49959 commit 2277d7c
Showing 1 changed file with 28 additions and 4 deletions.
32 changes: 28 additions & 4 deletions net/tls/tls_strp.c
Expand Up @@ -273,7 +273,7 @@ static int tls_strp_read_copyin(struct tls_strparser *strp)
return desc.error;
}

static int tls_strp_read_short(struct tls_strparser *strp)
static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
{
struct skb_shared_info *shinfo;
struct page *page;
Expand All @@ -283,7 +283,7 @@ static int tls_strp_read_short(struct tls_strparser *strp)
* to read the data out. Otherwise the connection will stall.
* Without pressure threshold of INT_MAX will never be ready.
*/
if (likely(!tcp_epollin_ready(strp->sk, INT_MAX)))
if (likely(qshort && !tcp_epollin_ready(strp->sk, INT_MAX)))
return 0;

shinfo = skb_shinfo(strp->anchor);
Expand Down Expand Up @@ -315,6 +315,27 @@ static int tls_strp_read_short(struct tls_strparser *strp)
return 0;
}

static bool tls_strp_check_no_dup(struct tls_strparser *strp)
{
unsigned int len = strp->stm.offset + strp->stm.full_len;
struct sk_buff *skb;
u32 seq;

skb = skb_shinfo(strp->anchor)->frag_list;
seq = TCP_SKB_CB(skb)->seq;

while (skb->len < len) {
seq += skb->len;
len -= skb->len;
skb = skb->next;

if (TCP_SKB_CB(skb)->seq != seq)
return false;
}

return true;
}

static void tls_strp_load_anchor_with_queue(struct tls_strparser *strp, int len)
{
struct tcp_sock *tp = tcp_sk(strp->sk);
Expand Down Expand Up @@ -373,7 +394,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
return tls_strp_read_copyin(strp);

if (inq < strp->stm.full_len)
return tls_strp_read_short(strp);
return tls_strp_read_copy(strp, true);

if (!strp->stm.full_len) {
tls_strp_load_anchor_with_queue(strp, inq);
Expand All @@ -387,9 +408,12 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
strp->stm.full_len = sz;

if (!strp->stm.full_len || inq < strp->stm.full_len)
return tls_strp_read_short(strp);
return tls_strp_read_copy(strp, true);
}

if (!tls_strp_check_no_dup(strp))
return tls_strp_read_copy(strp, false);

strp->msg_ready = 1;
tls_rx_msg_ready(strp);

Expand Down

0 comments on commit 2277d7c

Please sign in to comment.