It is a shame. The bug is stupid and effect is disasterous.

https://pmc.acronis.work/browse/VSTOR-84977

Signed-off-by: Alexey Kuznetsov <kuz...@acronis.com>
---
 fs/fuse/kio/pcs/pcs_cs_accel.c | 43 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/fs/fuse/kio/pcs/pcs_cs_accel.c b/fs/fuse/kio/pcs/pcs_cs_accel.c
index a18069f..9be94a6 100644
--- a/fs/fuse/kio/pcs/pcs_cs_accel.c
+++ b/fs/fuse/kio/pcs/pcs_cs_accel.c
@@ -932,7 +932,8 @@ static int init_crypted_data(struct pcs_int_request * ireq, 
int idx)
        struct pcs_int_request *parent = ireq->completion_data.parent;
        struct pcs_fuse_req * r;
        struct bio_vec * bvec;
-       int n, nvec;
+       int n, nvec, first;
+       unsigned int off, start_off, end_off;
        u64 pos;
        u64 chunk_id;
        struct pcs_csa_context * csa_ctx;
@@ -951,14 +952,38 @@ static int init_crypted_data(struct pcs_int_request * 
ireq, int idx)
        if (!bvec)
                return -ENOMEM;
 
-       for (n = 0; n < nvec; n++) {
-               bvec[n] = r->exec.io.bvec[n];
-               if ((bvec[n].bv_offset|bvec[n].bv_len)&511)
+       off = 0;
+       start_off = ireq->iochunk.dio_offset;
+       end_off = start_off + ireq->iochunk.size;
+
+       for (first = 0; first < nvec; first++) {
+               struct bio_vec *v = r->exec.io.bvec + first;
+               unsigned int next = off + v->bv_len;
+
+               if (next > start_off)
+                       break;
+               off = next;
+       }
+
+       for (n = 0; n < nvec - first && off < end_off; n++) {
+               struct bio_vec *v = r->exec.io.bvec + first + n;
+               unsigned int next = off + v->bv_len;
+
+               bvec[n] = *v;
+               if (off < start_off) {
+                       bvec[n].bv_offset += start_off - off;
+                       bvec[n].bv_len -= start_off - off;
+               }
+               if (next > end_off)
+                       bvec[n].bv_len -= next - end_off;
+               if ((bvec[n].bv_offset | bvec[n].bv_len) & 511)
                        goto out;
                bvec[n].bv_page = alloc_page(GFP_NOIO);
                if (!bvec[n].bv_page)
                        goto out;
+               off = next;
        }
+       nvec = n;
 
        rcu_read_lock();
        csa_ctx = 
rcu_dereference(ireq->iochunk.csl->cs[idx].cslink.cs->csa_ctx);
@@ -969,17 +994,19 @@ static int init_crypted_data(struct pcs_int_request * 
ireq, int idx)
 
        pos = ireq->iochunk.offset;
        chunk_id = ireq->iochunk.map->id;
-       for (n = 0; n < nvec; n++) {
+       for (n = 0; n < nvec; n++, first++) {
                if (tfm->base.base.__crt_alg->cra_priority == 400)
-                       encrypt_page_ctr(tfm, bvec[n].bv_page, 
r->exec.io.bvec[n].bv_page, bvec[n].bv_offset, bvec[n].bv_len, pos, chunk_id);
+                       encrypt_page_ctr(tfm, bvec[n].bv_page, 
r->exec.io.bvec[first].bv_page,
+                                        bvec[n].bv_offset, bvec[n].bv_len, 
pos, chunk_id);
                else
-                       encrypt_page_xts(tfm, bvec[n].bv_page, 
r->exec.io.bvec[n].bv_page, bvec[n].bv_offset, bvec[n].bv_len, pos, chunk_id);
+                       encrypt_page_xts(tfm, bvec[n].bv_page, 
r->exec.io.bvec[first].bv_page,
+                                        bvec[n].bv_offset, bvec[n].bv_len, 
pos, chunk_id);
                pos += bvec[n].bv_len;
        }
        rcu_read_unlock();
 
        ireq->iochunk.acr.awr[idx].bvec_copy = bvec;
-       ireq->iochunk.acr.awr[idx].num_copy_bvecs = n;
+       ireq->iochunk.acr.awr[idx].num_copy_bvecs = nvec;
        return 0;
 
 out:
-- 
1.8.3.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to