mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-26 04:16:39 +00:00
bcachefs: Check for errors from crypto_skcipher_encrypt()
Apparently it actually is possible for crypto_skcipher_encrypt() to return an error - not sure why that would be - but we need to replace our assertion with actual error handling. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
parent
8f9ad91a02
commit
a9de137bf6
6 changed files with 85 additions and 38 deletions
|
@ -917,7 +917,10 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
|
|||
BTREE_ERR_WANT_RETRY, c, ca, b, i,
|
||||
"invalid checksum");
|
||||
|
||||
bset_encrypt(c, i, b->written << 9);
|
||||
ret = bset_encrypt(c, i, b->written << 9);
|
||||
if (bch2_fs_fatal_err_on(ret, c,
|
||||
"error decrypting btree node: %i", ret))
|
||||
goto fsck_err;
|
||||
|
||||
btree_err_on(btree_node_is_extents(b) &&
|
||||
!BTREE_NODE_NEW_EXTENT_OVERWRITE(b->data),
|
||||
|
@ -944,7 +947,10 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
|
|||
BTREE_ERR_WANT_RETRY, c, ca, b, i,
|
||||
"invalid checksum");
|
||||
|
||||
bset_encrypt(c, i, b->written << 9);
|
||||
ret = bset_encrypt(c, i, b->written << 9);
|
||||
if (bch2_fs_fatal_err_on(ret, c,
|
||||
"error decrypting btree node: %i\n", ret))
|
||||
goto fsck_err;
|
||||
|
||||
sectors = vstruct_sectors(bne, c->block_bits);
|
||||
}
|
||||
|
@ -1753,6 +1759,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, bool already_sta
|
|||
unsigned long old, new;
|
||||
bool validate_before_checksum = false;
|
||||
void *data;
|
||||
int ret;
|
||||
|
||||
if (already_started)
|
||||
goto do_write;
|
||||
|
@ -1893,7 +1900,10 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, bool already_sta
|
|||
validate_bset_for_write(c, b, i, sectors_to_write))
|
||||
goto err;
|
||||
|
||||
bset_encrypt(c, i, b->written << 9);
|
||||
ret = bset_encrypt(c, i, b->written << 9);
|
||||
if (bch2_fs_fatal_err_on(ret, c,
|
||||
"error encrypting btree node: %i\n", ret))
|
||||
goto err;
|
||||
|
||||
nonce = btree_nonce(i, b->written << 9);
|
||||
|
||||
|
|
|
@ -111,22 +111,25 @@ static inline struct nonce btree_nonce(struct bset *i, unsigned offset)
|
|||
}};
|
||||
}
|
||||
|
||||
static inline void bset_encrypt(struct bch_fs *c, struct bset *i, unsigned offset)
|
||||
static inline int bset_encrypt(struct bch_fs *c, struct bset *i, unsigned offset)
|
||||
{
|
||||
struct nonce nonce = btree_nonce(i, offset);
|
||||
int ret;
|
||||
|
||||
if (!offset) {
|
||||
struct btree_node *bn = container_of(i, struct btree_node, keys);
|
||||
unsigned bytes = (void *) &bn->keys - (void *) &bn->flags;
|
||||
|
||||
bch2_encrypt(c, BSET_CSUM_TYPE(i), nonce, &bn->flags,
|
||||
bytes);
|
||||
ret = bch2_encrypt(c, BSET_CSUM_TYPE(i), nonce,
|
||||
&bn->flags, bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nonce = nonce_add(nonce, round_up(bytes, CHACHA_BLOCK_SIZE));
|
||||
}
|
||||
|
||||
bch2_encrypt(c, BSET_CSUM_TYPE(i), nonce, i->_data,
|
||||
vstruct_end(i) - (void *) i->_data);
|
||||
return bch2_encrypt(c, BSET_CSUM_TYPE(i), nonce, i->_data,
|
||||
vstruct_end(i) - (void *) i->_data);
|
||||
}
|
||||
|
||||
void bch2_btree_sort_into(struct bch_fs *, struct btree *, struct btree *);
|
||||
|
|
|
@ -93,9 +93,9 @@ static void bch2_checksum_update(struct bch2_checksum_state *state, const void *
|
|||
}
|
||||
}
|
||||
|
||||
static inline void do_encrypt_sg(struct crypto_sync_skcipher *tfm,
|
||||
struct nonce nonce,
|
||||
struct scatterlist *sg, size_t len)
|
||||
static inline int do_encrypt_sg(struct crypto_sync_skcipher *tfm,
|
||||
struct nonce nonce,
|
||||
struct scatterlist *sg, size_t len)
|
||||
{
|
||||
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
|
||||
int ret;
|
||||
|
@ -104,17 +104,20 @@ static inline void do_encrypt_sg(struct crypto_sync_skcipher *tfm,
|
|||
skcipher_request_set_crypt(req, sg, sg, len, nonce.d);
|
||||
|
||||
ret = crypto_skcipher_encrypt(req);
|
||||
BUG_ON(ret);
|
||||
if (ret)
|
||||
pr_err("got error %i from crypto_skcipher_encrypt()", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void do_encrypt(struct crypto_sync_skcipher *tfm,
|
||||
static inline int do_encrypt(struct crypto_sync_skcipher *tfm,
|
||||
struct nonce nonce,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_one(&sg, buf, len);
|
||||
do_encrypt_sg(tfm, nonce, &sg, len);
|
||||
return do_encrypt_sg(tfm, nonce, &sg, len);
|
||||
}
|
||||
|
||||
int bch2_chacha_encrypt_key(struct bch_key *key, struct nonce nonce,
|
||||
|
@ -136,25 +139,29 @@ int bch2_chacha_encrypt_key(struct bch_key *key, struct nonce nonce,
|
|||
goto err;
|
||||
}
|
||||
|
||||
do_encrypt(chacha20, nonce, buf, len);
|
||||
ret = do_encrypt(chacha20, nonce, buf, len);
|
||||
err:
|
||||
crypto_free_sync_skcipher(chacha20);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gen_poly_key(struct bch_fs *c, struct shash_desc *desc,
|
||||
struct nonce nonce)
|
||||
static int gen_poly_key(struct bch_fs *c, struct shash_desc *desc,
|
||||
struct nonce nonce)
|
||||
{
|
||||
u8 key[POLY1305_KEY_SIZE];
|
||||
int ret;
|
||||
|
||||
nonce.d[3] ^= BCH_NONCE_POLY;
|
||||
|
||||
memset(key, 0, sizeof(key));
|
||||
do_encrypt(c->chacha20, nonce, key, sizeof(key));
|
||||
ret = do_encrypt(c->chacha20, nonce, key, sizeof(key));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
desc->tfm = c->poly1305;
|
||||
crypto_shash_init(desc);
|
||||
crypto_shash_update(desc, key, sizeof(key));
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bch_csum bch2_checksum(struct bch_fs *c, unsigned type,
|
||||
|
@ -196,13 +203,13 @@ struct bch_csum bch2_checksum(struct bch_fs *c, unsigned type,
|
|||
}
|
||||
}
|
||||
|
||||
void bch2_encrypt(struct bch_fs *c, unsigned type,
|
||||
int bch2_encrypt(struct bch_fs *c, unsigned type,
|
||||
struct nonce nonce, void *data, size_t len)
|
||||
{
|
||||
if (!bch2_csum_type_is_encryption(type))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
do_encrypt(c->chacha20, nonce, data, len);
|
||||
return do_encrypt(c->chacha20, nonce, data, len);
|
||||
}
|
||||
|
||||
static struct bch_csum __bch2_checksum_bio(struct bch_fs *c, unsigned type,
|
||||
|
@ -277,23 +284,27 @@ struct bch_csum bch2_checksum_bio(struct bch_fs *c, unsigned type,
|
|||
return __bch2_checksum_bio(c, type, nonce, bio, &iter);
|
||||
}
|
||||
|
||||
void bch2_encrypt_bio(struct bch_fs *c, unsigned type,
|
||||
struct nonce nonce, struct bio *bio)
|
||||
int bch2_encrypt_bio(struct bch_fs *c, unsigned type,
|
||||
struct nonce nonce, struct bio *bio)
|
||||
{
|
||||
struct bio_vec bv;
|
||||
struct bvec_iter iter;
|
||||
struct scatterlist sgl[16], *sg = sgl;
|
||||
size_t bytes = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!bch2_csum_type_is_encryption(type))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
sg_init_table(sgl, ARRAY_SIZE(sgl));
|
||||
|
||||
bio_for_each_segment(bv, bio, iter) {
|
||||
if (sg == sgl + ARRAY_SIZE(sgl)) {
|
||||
sg_mark_end(sg - 1);
|
||||
do_encrypt_sg(c->chacha20, nonce, sgl, bytes);
|
||||
|
||||
ret = do_encrypt_sg(c->chacha20, nonce, sgl, bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nonce = nonce_add(nonce, bytes);
|
||||
bytes = 0;
|
||||
|
@ -307,7 +318,7 @@ void bch2_encrypt_bio(struct bch_fs *c, unsigned type,
|
|||
}
|
||||
|
||||
sg_mark_end(sg - 1);
|
||||
do_encrypt_sg(c->chacha20, nonce, sgl, bytes);
|
||||
return do_encrypt_sg(c->chacha20, nonce, sgl, bytes);
|
||||
}
|
||||
|
||||
struct bch_csum bch2_checksum_merge(unsigned type, struct bch_csum a,
|
||||
|
|
|
@ -49,7 +49,7 @@ struct bch_csum bch2_checksum(struct bch_fs *, unsigned, struct nonce,
|
|||
int bch2_chacha_encrypt_key(struct bch_key *, struct nonce, void *, size_t);
|
||||
int bch2_request_key(struct bch_sb *, struct bch_key *);
|
||||
|
||||
void bch2_encrypt(struct bch_fs *, unsigned, struct nonce,
|
||||
int bch2_encrypt(struct bch_fs *, unsigned, struct nonce,
|
||||
void *data, size_t);
|
||||
|
||||
struct bch_csum bch2_checksum_bio(struct bch_fs *, unsigned,
|
||||
|
@ -61,8 +61,8 @@ int bch2_rechecksum_bio(struct bch_fs *, struct bio *, struct bversion,
|
|||
struct bch_extent_crc_unpacked *,
|
||||
unsigned, unsigned, unsigned);
|
||||
|
||||
void bch2_encrypt_bio(struct bch_fs *, unsigned,
|
||||
struct nonce, struct bio *);
|
||||
int bch2_encrypt_bio(struct bch_fs *, unsigned,
|
||||
struct nonce, struct bio *);
|
||||
|
||||
int bch2_decrypt_sb_key(struct bch_fs *, struct bch_sb_field_crypt *,
|
||||
struct bch_key *);
|
||||
|
|
|
@ -846,6 +846,7 @@ static int bch2_write_decrypt(struct bch_write_op *op)
|
|||
struct bch_fs *c = op->c;
|
||||
struct nonce nonce = extent_nonce(op->version, op->crc);
|
||||
struct bch_csum csum;
|
||||
int ret;
|
||||
|
||||
if (!bch2_csum_type_is_encryption(op->crc.csum_type))
|
||||
return 0;
|
||||
|
@ -860,10 +861,10 @@ static int bch2_write_decrypt(struct bch_write_op *op)
|
|||
if (bch2_crc_cmp(op->crc.csum, csum))
|
||||
return -EIO;
|
||||
|
||||
bch2_encrypt_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
|
||||
ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
|
||||
op->crc.csum_type = 0;
|
||||
op->crc.csum = (struct bch_csum) { 0, 0 };
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum prep_encoded_ret {
|
||||
|
@ -1078,8 +1079,11 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
|
|||
crc.live_size = src_len >> 9;
|
||||
|
||||
swap(dst->bi_iter.bi_size, dst_len);
|
||||
bch2_encrypt_bio(c, op->csum_type,
|
||||
extent_nonce(version, crc), dst);
|
||||
ret = bch2_encrypt_bio(c, op->csum_type,
|
||||
extent_nonce(version, crc), dst);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
crc.csum = bch2_checksum_bio(c, op->csum_type,
|
||||
extent_nonce(version, crc), dst);
|
||||
crc.csum_type = op->csum_type;
|
||||
|
@ -1851,6 +1855,7 @@ static void __bch2_read_endio(struct work_struct *work)
|
|||
struct nonce nonce = extent_nonce(rbio->version, crc);
|
||||
unsigned nofs_flags;
|
||||
struct bch_csum csum;
|
||||
int ret;
|
||||
|
||||
nofs_flags = memalloc_nofs_save();
|
||||
|
||||
|
@ -1885,7 +1890,10 @@ static void __bch2_read_endio(struct work_struct *work)
|
|||
crc.live_size = bvec_iter_sectors(rbio->bvec_iter);
|
||||
|
||||
if (crc_is_compressed(crc)) {
|
||||
bch2_encrypt_bio(c, crc.csum_type, nonce, src);
|
||||
ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src);
|
||||
if (ret)
|
||||
goto decrypt_err;
|
||||
|
||||
if (bch2_bio_uncompress(c, src, dst, dst_iter, crc))
|
||||
goto decompression_err;
|
||||
} else {
|
||||
|
@ -1896,7 +1904,9 @@ static void __bch2_read_endio(struct work_struct *work)
|
|||
BUG_ON(src->bi_iter.bi_size < dst_iter.bi_size);
|
||||
src->bi_iter.bi_size = dst_iter.bi_size;
|
||||
|
||||
bch2_encrypt_bio(c, crc.csum_type, nonce, src);
|
||||
ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src);
|
||||
if (ret)
|
||||
goto decrypt_err;
|
||||
|
||||
if (rbio->bounce) {
|
||||
struct bvec_iter src_iter = src->bi_iter;
|
||||
|
@ -1909,7 +1919,10 @@ static void __bch2_read_endio(struct work_struct *work)
|
|||
* Re encrypt data we decrypted, so it's consistent with
|
||||
* rbio->crc:
|
||||
*/
|
||||
bch2_encrypt_bio(c, crc.csum_type, nonce, src);
|
||||
ret = bch2_encrypt_bio(c, crc.csum_type, nonce, src);
|
||||
if (ret)
|
||||
goto decrypt_err;
|
||||
|
||||
promote_start(rbio->promote, rbio);
|
||||
rbio->promote = NULL;
|
||||
}
|
||||
|
@ -1944,6 +1957,11 @@ static void __bch2_read_endio(struct work_struct *work)
|
|||
"decompression error");
|
||||
bch2_rbio_error(rbio, READ_ERR, BLK_STS_IOERR);
|
||||
goto out;
|
||||
decrypt_err:
|
||||
bch_err_inum_ratelimited(c, rbio->read_pos.inode,
|
||||
"decrypt error");
|
||||
bch2_rbio_error(rbio, READ_ERR, BLK_STS_IOERR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void bch2_read_endio(struct bio *bio)
|
||||
|
|
|
@ -724,9 +724,11 @@ static int jset_validate(struct bch_fs *c,
|
|||
sector, le64_to_cpu(jset->seq)))
|
||||
ret = JOURNAL_ENTRY_BAD;
|
||||
|
||||
bch2_encrypt(c, JSET_CSUM_TYPE(jset), journal_nonce(jset),
|
||||
ret = bch2_encrypt(c, JSET_CSUM_TYPE(jset), journal_nonce(jset),
|
||||
jset->encrypted_start,
|
||||
vstruct_end(jset) - (void *) jset->encrypted_start);
|
||||
bch2_fs_fatal_err_on(ret, c,
|
||||
"error decrypting journal entry: %i", ret);
|
||||
csum_done:
|
||||
/* last_seq is ignored when JSET_NO_FLUSH is true */
|
||||
if (journal_entry_err_on(!JSET_NO_FLUSH(jset) &&
|
||||
|
@ -1594,9 +1596,12 @@ void bch2_journal_write(struct closure *cl)
|
|||
jset_validate_for_write(c, jset))
|
||||
goto err;
|
||||
|
||||
bch2_encrypt(c, JSET_CSUM_TYPE(jset), journal_nonce(jset),
|
||||
ret = bch2_encrypt(c, JSET_CSUM_TYPE(jset), journal_nonce(jset),
|
||||
jset->encrypted_start,
|
||||
vstruct_end(jset) - (void *) jset->encrypted_start);
|
||||
if (bch2_fs_fatal_err_on(ret, c,
|
||||
"error decrypting journal entry: %i", ret))
|
||||
goto err;
|
||||
|
||||
jset->csum = csum_vstruct(c, JSET_CSUM_TYPE(jset),
|
||||
journal_nonce(jset), jset);
|
||||
|
|
Loading…
Reference in a new issue