Commit 636d4eef authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Fix memory corruption in encryption path

When do_encrypt() was passed a vmalloc address and the buffer spanned
more than a single page, we were encrypting/decrypting completely
different pages than the ones intended.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
parent 0fbf71f8
......@@ -114,15 +114,41 @@ static inline int do_encrypt(struct crypto_sync_skcipher *tfm,
struct nonce nonce,
void *buf, size_t len)
{
struct scatterlist sg;
sg_init_table(&sg, 1);
sg_set_page(&sg,
is_vmalloc_addr(buf)
? vmalloc_to_page(buf)
: virt_to_page(buf),
len, offset_in_page(buf));
return do_encrypt_sg(tfm, nonce, &sg, len);
if (!is_vmalloc_addr(buf)) {
struct scatterlist sg;
sg_init_table(&sg, 1);
sg_set_page(&sg,
is_vmalloc_addr(buf)
? vmalloc_to_page(buf)
: virt_to_page(buf),
len, offset_in_page(buf));
return do_encrypt_sg(tfm, nonce, &sg, len);
} else {
unsigned pages = buf_pages(buf, len);
struct scatterlist *sg;
size_t orig_len = len;
int ret, i;
sg = kmalloc_array(sizeof(*sg), pages, GFP_KERNEL);
if (!sg)
return -ENOMEM;
sg_init_table(sg, pages);
for (i = 0; i < pages; i++) {
unsigned offset = offset_in_page(buf);
unsigned pg_len = min(len, PAGE_SIZE - offset);
sg_set_page(sg + i, vmalloc_to_page(buf), pg_len, offset);
buf += pg_len;
len -= pg_len;
}
ret = do_encrypt_sg(tfm, nonce, sg, orig_len);
kfree(sg);
return ret;
}
}
int bch2_chacha_encrypt_key(struct bch_key *key, struct nonce nonce,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment