]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Check for errors from crypto_skcipher_encrypt()
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 19 Feb 2022 05:42:12 +0000 (00:42 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:24 +0000 (17:09 -0400)
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>
fs/bcachefs/btree_io.c
fs/bcachefs/btree_io.h
fs/bcachefs/checksum.c
fs/bcachefs/checksum.h
fs/bcachefs/io.c
fs/bcachefs/journal_io.c

index b6551db0396842788ae111a6db786ccbe1d71f4b..a0446df0d3dad1aaaa854b5b336a574346226363 100644 (file)
@@ -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 @@ do_write:
            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);
 
index 0f20224e2a77cec3070850226ea52cd45ebb3695..095ad505338d36e1bac1916d5ee9a3f606ed29bc 100644 (file)
@@ -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 *);
index a1d89923d361a976aeed0f7de3b7ebb0658df495..425582f60d7a8f8092ed30807d2465f1ca6e2515 100644 (file)
@@ -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,
index f5c1a609c5c42fe408a5896498c1aeed748679ff..c86c3c05d62054a66faffa4c5c2cde81ab5de1e8 100644 (file)
@@ -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 *);
index 914e22c5c24789421357d0606305b7500e8d6a50..4b9ff76dd19f268c97dc020c69644e7ab017ce57 100644 (file)
@@ -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 @@ decompression_err:
                                 "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)
index 03bc94b586f2324804e5a5097d34ecb53fb9aa89..231f2e4bd1b979ec8f10058ad8d14da712b32ea7 100644 (file)
@@ -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);