Merge branch ‘tls-data-copies’ [Linux 5.1]

Merge branch ‘tls-data-copies’ [Linux 5.1]

This Linux kernel change "Merge branch ‘tls-data-copies’" is included in the Linux 5.1 release. This change is authored by David S. Miller <davem [at] davemloft.net> on Sat Apr 27 20:17:20 2019 -0400. The commit for this change in Linux stable tree is fbef947 (patch). Other info about this change: Merge: b2a20fd eb3d38d

Merge branch 'tls-data-copies'

Jakub Kicinski says:

====================
net/tls: fix data copies in tls_device_reencrypt()

This series fixes the tls_device_reencrypt() which is broken
if record starts in the frags of the message skb.
====================

Signed-off-by: David S. Miller <[email protected]>

There is no are 0 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 net/tls/tls_device.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 9635706..14dedb2 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -597,7 +597,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;
@@ -628,9 +628,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);
@@ -639,16 +640,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:

Leave a Reply

Your email address will not be published. Required fields are marked *