[Devel] [PATCH VZ9 1/2] fs/fuse: pcs: corrupted writes in encrypted journalless mode
Alexey Kuznetsov
kuznet at virtuozzo.com
Fri Apr 26 18:19:02 MSK 2024
It is a shame. The bug is stupid and effect is disasterous.
https://pmc.acronis.work/browse/VSTOR-84977
Signed-off-by: Alexey Kuznetsov <kuznet at 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
More information about the Devel
mailing list