Skip to content

Commit

Permalink
net/tls: fix copy to fragments in reencrypt
Browse files Browse the repository at this point in the history
[ Upstream commit eb3d38d ]

Fragments may contain data from other records so we have to account
for that when we calculate the destination and max length of copy we
can perform.  Note that 'offset' is the offset within the message,
so it can't be passed as offset within the frag..

Here skb_store_bits() would have realised the call is wrong and
simply not copy data.

Fixes: 4799ac8 ("tls: Add rx inline crypto offload")
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: John Hurley <john.hurley@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jakub Kicinski authored and Greg Kroah-Hartman committed May 5, 2019
1 parent f7f4d4b commit a31a8f5
Showing 1 changed file with 22 additions and 7 deletions.
29 changes: 22 additions & 7 deletions net/tls/tls_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn)
static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
{
struct strp_msg *rxm = strp_msg(skb);
int err = 0, offset = rxm->offset, copy, nsg;
int err = 0, offset = rxm->offset, copy, nsg, data_len, pos;
struct sk_buff *skb_iter, *unused;
struct scatterlist sg[1];
char *orig_buf, *buf;
Expand Down Expand Up @@ -610,9 +610,10 @@ static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
else
err = 0;

data_len = rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE;

if (skb_pagelen(skb) > offset) {
copy = min_t(int, skb_pagelen(skb) - offset,
rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE);
copy = min_t(int, skb_pagelen(skb) - offset, data_len);

if (skb->decrypted)
skb_store_bits(skb, offset, buf, copy);
Expand All @@ -621,16 +622,30 @@ static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
buf += copy;
}

pos = skb_pagelen(skb);
skb_walk_frags(skb, skb_iter) {
copy = min_t(int, skb_iter->len,
rxm->full_len - offset + rxm->offset -
TLS_CIPHER_AES_GCM_128_TAG_SIZE);
int frag_pos;

/* Practically all frags must belong to msg if reencrypt
* is needed with current strparser and coalescing logic,
* but strparser may "get optimized", so let's be safe.
*/
if (pos + skb_iter->len <= offset)
goto done_with_frag;
if (pos >= data_len + rxm->offset)
break;

frag_pos = offset - pos;
copy = min_t(int, skb_iter->len - frag_pos,
data_len + rxm->offset - offset);

if (skb_iter->decrypted)
skb_store_bits(skb_iter, offset, buf, copy);
skb_store_bits(skb_iter, frag_pos, buf, copy);

offset += copy;
buf += copy;
done_with_frag:
pos += skb_iter->len;
}

free_buf:
Expand Down

0 comments on commit a31a8f5

Please sign in to comment.