diff options
Diffstat (limited to 'net/tls/tls_device.c')
-rw-r--r-- | net/tls/tls_device.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index 26f26e71ef3f..e225c81e6b35 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c | |||
@@ -580,7 +580,7 @@ void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn) | |||
580 | static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb) | 580 | static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb) |
581 | { | 581 | { |
582 | struct strp_msg *rxm = strp_msg(skb); | 582 | struct strp_msg *rxm = strp_msg(skb); |
583 | int err = 0, offset = rxm->offset, copy, nsg; | 583 | int err = 0, offset = rxm->offset, copy, nsg, data_len, pos; |
584 | struct sk_buff *skb_iter, *unused; | 584 | struct sk_buff *skb_iter, *unused; |
585 | struct scatterlist sg[1]; | 585 | struct scatterlist sg[1]; |
586 | char *orig_buf, *buf; | 586 | char *orig_buf, *buf; |
@@ -611,25 +611,42 @@ static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb) | |||
611 | else | 611 | else |
612 | err = 0; | 612 | err = 0; |
613 | 613 | ||
614 | copy = min_t(int, skb_pagelen(skb) - offset, | 614 | data_len = rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE; |
615 | rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE); | ||
616 | 615 | ||
617 | if (skb->decrypted) | 616 | if (skb_pagelen(skb) > offset) { |
618 | skb_store_bits(skb, offset, buf, copy); | 617 | copy = min_t(int, skb_pagelen(skb) - offset, data_len); |
619 | 618 | ||
620 | offset += copy; | 619 | if (skb->decrypted) |
621 | buf += copy; | 620 | skb_store_bits(skb, offset, buf, copy); |
622 | 621 | ||
622 | offset += copy; | ||
623 | buf += copy; | ||
624 | } | ||
625 | |||
626 | pos = skb_pagelen(skb); | ||
623 | skb_walk_frags(skb, skb_iter) { | 627 | skb_walk_frags(skb, skb_iter) { |
624 | copy = min_t(int, skb_iter->len, | 628 | int frag_pos; |
625 | rxm->full_len - offset + rxm->offset - | 629 | |
626 | TLS_CIPHER_AES_GCM_128_TAG_SIZE); | 630 | /* Practically all frags must belong to msg if reencrypt |
631 | * is needed with current strparser and coalescing logic, | ||
632 | * but strparser may "get optimized", so let's be safe. | ||
633 | */ | ||
634 | if (pos + skb_iter->len <= offset) | ||
635 | goto done_with_frag; | ||
636 | if (pos >= data_len + rxm->offset) | ||
637 | break; | ||
638 | |||
639 | frag_pos = offset - pos; | ||
640 | copy = min_t(int, skb_iter->len - frag_pos, | ||
641 | data_len + rxm->offset - offset); | ||
627 | 642 | ||
628 | if (skb_iter->decrypted) | 643 | if (skb_iter->decrypted) |
629 | skb_store_bits(skb_iter, offset, buf, copy); | 644 | skb_store_bits(skb_iter, frag_pos, buf, copy); |
630 | 645 | ||
631 | offset += copy; | 646 | offset += copy; |
632 | buf += copy; | 647 | buf += copy; |
648 | done_with_frag: | ||
649 | pos += skb_iter->len; | ||
633 | } | 650 | } |
634 | 651 | ||
635 | free_buf: | 652 | free_buf: |