The commit is pushed to "branch-rh9-5.14.0-362.8.1.vz9.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh9-5.14.0-362.8.1.vz9.35.17 ------> commit 678b95f5ab2c292376f3079425d47711375ef541 Author: Alexey Kuznetsov <kuz...@virtuozzo.com> Date: Fri Apr 26 23:19:02 2024 +0800
fs/fuse: pcs: corrupted writes in encrypted journalless mode It is a shame. The bug is stupid and effect is disasterous. khorenko@: Previously if we had a big write request and have to split it in 64Kb blocks, init_crypted_data() for every splitted block took FIRST 64K from the request and encrypted/wrote it. https://pmc.acronis.work/browse/VSTOR-84977 Fixes: 61973b1b2da3 ("fuse: cs acceleration for writes") Signed-off-by: Alexey Kuznetsov <kuz...@acronis.com> Feature: vStorage --- 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 a18069f22d85..9be94a610aaa 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: _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel