From 427ba555036e85ed0805f45ca3896b68602e0a80 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 12:23:51 -0400 Subject: [PATCH 01/18] bcachefs: Fix rcu splat in check_fix_ptrs() Signed-off-by: Kent Overstreet --- fs/bcachefs/buckets.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index e28d28ac2a13..02bb02b70981 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -479,9 +479,8 @@ int bch2_check_fix_ptrs(struct btree_trans *trans, percpu_down_read(&c->mark_lock); - rcu_read_lock(); bkey_for_each_ptr_decode(k.k, ptrs_c, p, entry_c) { - struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev); + struct bch_dev *ca = bch2_dev_tryget(c, p.ptr.dev); if (!ca) { if (fsck_err(c, ptr_to_invalid_device, "pointer to missing device %u\n" @@ -558,7 +557,7 @@ int bch2_check_fix_ptrs(struct btree_trans *trans, do_update = true; if (data_type != BCH_DATA_btree && p.ptr.gen != g->gen) - continue; + goto next; if (fsck_err_on(bucket_data_type_mismatch(g->data_type, data_type), c, ptr_bucket_data_type_mismatch, @@ -601,8 +600,9 @@ int bch2_check_fix_ptrs(struct btree_trans *trans, bch2_bkey_val_to_text(&buf, c, k), buf.buf))) do_update = true; } +next: + bch2_dev_put(ca); } - rcu_read_unlock(); if (do_update) { if (flags & BTREE_TRIGGER_is_root) { @@ -638,9 +638,10 @@ int bch2_check_fix_ptrs(struct btree_trans *trans, } else { struct bkey_ptrs ptrs; union bch_extent_entry *entry; + + rcu_read_lock(); restart_drop_ptrs: ptrs = bch2_bkey_ptrs(bkey_i_to_s(new)); - rcu_read_lock(); bkey_for_each_ptr_decode(bkey_i_to_s(new).k, ptrs, p, entry) { struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev); struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr); From 54429c902af909448371f40af59d4437a57949c7 Mon Sep 17 00:00:00 2001 From: Youling Tang Date: Fri, 10 May 2024 14:10:58 +0800 Subject: [PATCH 02/18] bcachefs: set FMODE_CAN_ODIRECT instead of a dummy direct_IO method Since commit a2ad63daa88b ("VFS: add FMODE_CAN_ODIRECT file flag") file systems can just set the FMODE_CAN_ODIRECT flag at open time instead of wiring up a dummy direct_IO method to indicate support for direct I/O. Do that for bcachefs so that noop_direct_IO can eventually be removed. Similar to commit b29434999371 ("xfs: set FMODE_CAN_ODIRECT instead of a dummy direct_IO method"). Signed-off-by: Youling Tang Signed-off-by: Kent Overstreet --- fs/bcachefs/fs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index fd851f10d11c..9b41c6e9deef 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -1145,6 +1145,8 @@ static int bch2_open(struct inode *vinode, struct file *file) return ret; } + file->f_mode |= FMODE_CAN_ODIRECT; + return generic_file_open(vinode, file); } @@ -1237,7 +1239,6 @@ static const struct address_space_operations bch_address_space_operations = { .write_end = bch2_write_end, .invalidate_folio = bch2_invalidate_folio, .release_folio = bch2_release_folio, - .direct_IO = noop_direct_IO, #ifdef CONFIG_MIGRATION .migrate_folio = filemap_migrate_folio, #endif From 9667214b30ef19c1cbead7893257619bca4d0d4d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 17:07:32 -0400 Subject: [PATCH 03/18] bcachefs: Fix ref in trans_mark_dev_sbs() error path Reported-by: syzbot+5c7f715a7107a608a544@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/buckets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 02bb02b70981..b469586517a8 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -1465,7 +1465,7 @@ int bch2_trans_mark_dev_sbs_flags(struct bch_fs *c, for_each_online_member(c, ca) { int ret = bch2_trans_mark_dev_sb(c, ca, flags); if (ret) { - bch2_dev_put(ca); + percpu_ref_put(&ca->io_ref); return ret; } } From f108ddd467b5cad84a6d93cdd0a251ba47ceaccb Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 17:08:15 -0400 Subject: [PATCH 04/18] bcachefs: Fix shift overflow in btree_lost_data() Reported-by: syzbot+29f65db1a5fe427b5c56@syzkaller.appspotmail.com Fixes: 55936afe1107 ("bcachefs: Flag btrees with missing data") Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs_format.h | 6 ++++++ fs/bcachefs/recovery.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 1bebba881d89..d801e19cb489 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1555,6 +1555,12 @@ enum btree_id { BTREE_ID_NR }; +/* + * Maximum number of btrees that we will _ever_ have under the current scheme, + * where we refer to them with bitfields + */ +#define BTREE_ID_NR_MAX 64 + static inline bool btree_id_is_alloc(enum btree_id id) { switch (id) { diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 1266916ac03f..63f990f5c63a 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -35,6 +35,9 @@ void bch2_btree_lost_data(struct bch_fs *c, enum btree_id btree) { + if (btree >= BTREE_ID_NR_MAX) + return; + u64 b = BIT_ULL(btree); if (!(c->sb.btrees_lost_data & b)) { From bcfbaea8e547881cd2cab6e05c3cd75449128590 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 17:28:44 -0400 Subject: [PATCH 05/18] bcachefs: Fix shift overflows in replicas.c We can't disallow unknown data_types in verify() - we have to preserve them unchanged for backwards compat; that means we have to add a few more guards. Reported-by: syzbot+249018ea545364f78d04@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/replicas.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c index bd1d5d085e23..d45b10bc531c 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -524,13 +524,16 @@ int bch2_replicas_gc_start(struct bch_fs *c, unsigned typemask) c->replicas_gc.nr = 0; c->replicas_gc.entry_size = 0; - for_each_cpu_replicas_entry(&c->replicas, e) - if (!((1 << e->data_type) & typemask)) { + for_each_cpu_replicas_entry(&c->replicas, e) { + /* Preserve unknown data types */ + if (e->data_type >= BCH_DATA_NR || + !((1 << e->data_type) & typemask)) { c->replicas_gc.nr++; c->replicas_gc.entry_size = max_t(unsigned, c->replicas_gc.entry_size, replicas_entry_bytes(e)); } + } c->replicas_gc.entries = kcalloc(c->replicas_gc.nr, c->replicas_gc.entry_size, @@ -542,7 +545,8 @@ int bch2_replicas_gc_start(struct bch_fs *c, unsigned typemask) } for_each_cpu_replicas_entry(&c->replicas, e) - if (!((1 << e->data_type) & typemask)) + if (e->data_type >= BCH_DATA_NR || + !((1 << e->data_type) & typemask)) memcpy(cpu_replicas_entry(&c->replicas_gc, i++), e, c->replicas_gc.entry_size); @@ -998,7 +1002,7 @@ unsigned bch2_sb_dev_has_data(struct bch_sb *sb, unsigned dev) { struct bch_sb_field_replicas *replicas; struct bch_sb_field_replicas_v0 *replicas_v0; - unsigned i, data_has = 0; + unsigned data_has = 0; replicas = bch2_sb_field_get(sb, replicas); replicas_v0 = bch2_sb_field_get(sb, replicas_v0); @@ -1006,17 +1010,26 @@ unsigned bch2_sb_dev_has_data(struct bch_sb *sb, unsigned dev) if (replicas) { struct bch_replicas_entry_v1 *r; - for_each_replicas_entry(replicas, r) - for (i = 0; i < r->nr_devs; i++) + for_each_replicas_entry(replicas, r) { + if (r->data_type >= sizeof(data_has) * 8) + continue; + + for (unsigned i = 0; i < r->nr_devs; i++) if (r->devs[i] == dev) data_has |= 1 << r->data_type; + } + } else if (replicas_v0) { struct bch_replicas_entry_v0 *r; - for_each_replicas_entry_v0(replicas_v0, r) - for (i = 0; i < r->nr_devs; i++) + for_each_replicas_entry_v0(replicas_v0, r) { + if (r->data_type >= sizeof(data_has) * 8) + continue; + + for (unsigned i = 0; i < r->nr_devs; i++) if (r->devs[i] == dev) data_has |= 1 << r->data_type; + } } From 25989f4a9bf5f9bee7ba541de68f34cf406dff38 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 17:52:12 -0400 Subject: [PATCH 06/18] bcachefs: Improve bch2_assert_pos_locked() Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_iter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 5bf98cb8b15d..d3bcb4e4e230 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -332,6 +332,8 @@ static int bch2_btree_iter_verify_ret(struct btree_iter *iter, struct bkey_s_c k void bch2_assert_pos_locked(struct btree_trans *trans, enum btree_id id, struct bpos pos, bool key_cache) { + bch2_trans_verify_not_unlocked(trans); + struct btree_path *path; struct trans_for_each_path_inorder_iter iter; struct printbuf buf = PRINTBUF; From 6ce26ad376bdc65c2bc6d4ef7b8a939bf1bd19dc Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 17:55:02 -0400 Subject: [PATCH 07/18] bcachefs: Fix missing parens in drop_locks_do() Reported-by: syzbot+95db43b0a06f157ee865@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_iter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index eab2a25bdc7a..798eb1c47966 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -838,7 +838,7 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans, #define drop_locks_do(_trans, _do) \ ({ \ bch2_trans_unlock(_trans); \ - _do ?: bch2_trans_relock(_trans); \ + (_do) ?: bch2_trans_relock(_trans); \ }) #define allocate_dropping_locks_errcode(_trans, _do) \ From 6d48e61364aedd774d688f28b5a6c9b5f7f0018c Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 19:16:22 -0400 Subject: [PATCH 08/18] bcachefs: Add missing guard in bch2_snapshot_has_children() We additionally need to be going inconsistent if passed an invalid snapshot ID; that patch will need more thorough testing. Reported-by: syzbot+1c9fca23fe478633b305@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/snapshot.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/bcachefs/snapshot.h b/fs/bcachefs/snapshot.h index bd5d74269d15..ab13d8f4b41e 100644 --- a/fs/bcachefs/snapshot.h +++ b/fs/bcachefs/snapshot.h @@ -176,12 +176,9 @@ static inline bool bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ances static inline bool bch2_snapshot_has_children(struct bch_fs *c, u32 id) { - const struct snapshot_t *t; - bool ret; - rcu_read_lock(); - t = snapshot_t(c, id); - ret = (t->children[0]|t->children[1]) != 0; + const struct snapshot_t *t = snapshot_t(c, id); + bool ret = t && (t->children[0]|t->children[1]) != 0; rcu_read_unlock(); return ret; From c06a8b75679d73473c0c382bcc676ee4b7657bee Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 19:58:44 -0400 Subject: [PATCH 09/18] bcachefs: Fix bch2_alloc_ciphers() Don't put error pointers in bch_fs, that's gross. This fixes (?) the check in bch2_checksum_type_valid() - depending on our error paths, or depending on what our error paths are doing it at least makes the code saner. Reported-by: syzbot+2e3cb81b5d1fe18a374b@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/checksum.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/fs/bcachefs/checksum.c b/fs/bcachefs/checksum.c index 85198f391e9c..fc9a2b2a916f 100644 --- a/fs/bcachefs/checksum.c +++ b/fs/bcachefs/checksum.c @@ -648,26 +648,26 @@ int bch2_decrypt_sb_key(struct bch_fs *c, static int bch2_alloc_ciphers(struct bch_fs *c) { - int ret; - - if (!c->chacha20) - c->chacha20 = crypto_alloc_sync_skcipher("chacha20", 0, 0); - ret = PTR_ERR_OR_ZERO(c->chacha20); + if (c->chacha20) + return 0; + struct crypto_sync_skcipher *chacha20 = crypto_alloc_sync_skcipher("chacha20", 0, 0); + int ret = PTR_ERR_OR_ZERO(chacha20); if (ret) { bch_err(c, "error requesting chacha20 module: %s", bch2_err_str(ret)); return ret; } - if (!c->poly1305) - c->poly1305 = crypto_alloc_shash("poly1305", 0, 0); - ret = PTR_ERR_OR_ZERO(c->poly1305); - + struct crypto_shash *poly1305 = crypto_alloc_shash("poly1305", 0, 0); + ret = PTR_ERR_OR_ZERO(poly1305); if (ret) { bch_err(c, "error requesting poly1305 module: %s", bch2_err_str(ret)); + crypto_free_sync_skcipher(chacha20); return ret; } + c->chacha20 = chacha20; + c->poly1305 = poly1305; return 0; } @@ -762,11 +762,11 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed) void bch2_fs_encryption_exit(struct bch_fs *c) { - if (!IS_ERR_OR_NULL(c->poly1305)) + if (c->poly1305) crypto_free_shash(c->poly1305); - if (!IS_ERR_OR_NULL(c->chacha20)) + if (c->chacha20) crypto_free_sync_skcipher(c->chacha20); - if (!IS_ERR_OR_NULL(c->sha256)) + if (c->sha256) crypto_free_shash(c->sha256); } @@ -779,6 +779,7 @@ int bch2_fs_encryption_init(struct bch_fs *c) c->sha256 = crypto_alloc_shash("sha256", 0, 0); ret = PTR_ERR_OR_ZERO(c->sha256); if (ret) { + c->sha256 = NULL; bch_err(c, "error requesting sha256 module: %s", bch2_err_str(ret)); goto out; } From 6b74fdcc8e25323cd256a573186f9c6c6c2410c0 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 19 May 2024 20:09:35 -0400 Subject: [PATCH 10/18] bcachefs: bch2_checksum() returns 0 for unknown checksum type This fixes missing guards on trying to calculate a checksum with an invalid/unknown checksum type; moving the guards up to e.g. btree_io.c might be "more correct", but doesn't buy us anything - an unknown checksum type will always be flagged as at least a checksum error so we aren't losing any safety doing it this way and it makes it less likely to accidentally pop an assert we don't want. Reported-by: syzbot+e951ad5349f3a34a715a@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/checksum.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/bcachefs/checksum.c b/fs/bcachefs/checksum.c index fc9a2b2a916f..4b3d6f0137f6 100644 --- a/fs/bcachefs/checksum.c +++ b/fs/bcachefs/checksum.c @@ -233,7 +233,7 @@ struct bch_csum bch2_checksum(struct bch_fs *c, unsigned type, return ret; } default: - BUG(); + return (struct bch_csum) {}; } } @@ -307,7 +307,7 @@ static struct bch_csum __bch2_checksum_bio(struct bch_fs *c, unsigned type, return ret; } default: - BUG(); + return (struct bch_csum) {}; } } From 765b8cb8acabdff9261a11b80c87496717f67824 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 20 May 2024 01:11:20 -0400 Subject: [PATCH 11/18] bcachefs: Check for subvolues with bogus snapshot/inode fields This fixes an assertion pop in btree_iter.c that checks for forgetting to pass a snapshot ID when iterating over snapshots btrees. Reported-by: syzbot+0dfe05235e38653e2aee@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/sb-errors_types.h | 4 +++- fs/bcachefs/subvolume.c | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/sb-errors_types.h b/fs/bcachefs/sb-errors_types.h index 87324747351a..666599d3fb9d 100644 --- a/fs/bcachefs/sb-errors_types.h +++ b/fs/bcachefs/sb-errors_types.h @@ -273,7 +273,9 @@ x(dup_backpointer_to_bad_csum_extent, 265) \ x(btree_bitmap_not_marked, 266) \ x(sb_clean_entry_overrun, 267) \ - x(btree_ptr_v2_written_0, 268) + x(btree_ptr_v2_written_0, 268) \ + x(subvol_snapshot_bad, 269) \ + x(subvol_inode_bad, 270) enum bch_sb_error_id { #define x(t, n) BCH_FSCK_ERR_##t = n, diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c index 132213761ef6..dfc9cf305756 100644 --- a/fs/bcachefs/subvolume.c +++ b/fs/bcachefs/subvolume.c @@ -210,12 +210,21 @@ int bch2_check_subvol_children(struct bch_fs *c) int bch2_subvolume_invalid(struct bch_fs *c, struct bkey_s_c k, enum bch_validate_flags flags, struct printbuf *err) { + struct bkey_s_c_subvolume subvol = bkey_s_c_to_subvolume(k); int ret = 0; bkey_fsck_err_on(bkey_lt(k.k->p, SUBVOL_POS_MIN) || bkey_gt(k.k->p, SUBVOL_POS_MAX), c, err, subvol_pos_bad, "invalid pos"); + + bkey_fsck_err_on(!subvol.v->snapshot, c, err, + subvol_snapshot_bad, + "invalid snapshot"); + + bkey_fsck_err_on(!subvol.v->inode, c, err, + subvol_inode_bad, + "invalid inode"); fsck_err: return ret; } From 5fa421448d1f51b8991dd550a4b6347229116cc7 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 20 May 2024 00:58:04 -0400 Subject: [PATCH 12/18] bcachefs: Fix bogus verify_replicas_entry() assert verify_replicas_entry() is only for newly created replicas entries - existing entries on disk may have unknown data types, and we have real verifiers for them. Reported-by: syzbot+73414091bd382684ee2b@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/replicas.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c index d45b10bc531c..57a1f09cca09 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -23,14 +23,12 @@ static int bch2_memcmp(const void *l, const void *r, const void *priv) static void verify_replicas_entry(struct bch_replicas_entry_v1 *e) { #ifdef CONFIG_BCACHEFS_DEBUG - unsigned i; - BUG_ON(e->data_type >= BCH_DATA_NR); BUG_ON(!e->nr_devs); BUG_ON(e->nr_required > 1 && e->nr_required >= e->nr_devs); - for (i = 0; i + 1 < e->nr_devs; i++) + for (unsigned i = 0; i + 1 < e->nr_devs; i++) BUG_ON(e->devs[i] >= e->devs[i + 1]); #endif } @@ -192,24 +190,17 @@ cpu_replicas_add_entry(struct bch_fs *c, struct bch_replicas_cpu *old, struct bch_replicas_entry_v1 *new_entry) { - unsigned i; struct bch_replicas_cpu new = { .nr = old->nr + 1, .entry_size = max_t(unsigned, old->entry_size, replicas_entry_bytes(new_entry)), }; - for (i = 0; i < new_entry->nr_devs; i++) - BUG_ON(!bch2_dev_exists(c, new_entry->devs[i])); - - BUG_ON(!new_entry->data_type); - verify_replicas_entry(new_entry); - new.entries = kcalloc(new.nr, new.entry_size, GFP_KERNEL); if (!new.entries) return new; - for (i = 0; i < old->nr; i++) + for (unsigned i = 0; i < old->nr; i++) memcpy(cpu_replicas_entry(&new, i), cpu_replicas_entry(old, i), old->entry_size); @@ -230,8 +221,6 @@ static inline int __replicas_entry_idx(struct bch_replicas_cpu *r, if (unlikely(entry_size > r->entry_size)) return -1; - verify_replicas_entry(search); - #define entry_cmp(_l, _r) memcmp(_l, _r, entry_size) idx = eytzinger0_find(r->entries, r->nr, r->entry_size, entry_cmp, search); From 70dd062e27e679247cd8828c23c0e12728de5465 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 20 May 2024 03:03:29 -0400 Subject: [PATCH 13/18] bcachefs: Fix btree_trans leak in bch2_readahead() Reported-by: syzbot+d797fe78808e968d6c84@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/fs-io-buffered.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c index b0a33fabadf8..6b69e5cd68dd 100644 --- a/fs/bcachefs/fs-io-buffered.c +++ b/fs/bcachefs/fs-io-buffered.c @@ -257,7 +257,6 @@ void bch2_readahead(struct readahead_control *ractl) struct bch_inode_info *inode = to_bch_ei(ractl->mapping->host); struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_io_opts opts; - struct btree_trans *trans = bch2_trans_get(c); struct folio *folio; struct readpages_iter readpages_iter; @@ -269,6 +268,7 @@ void bch2_readahead(struct readahead_control *ractl) bch2_pagecache_add_get(inode); + struct btree_trans *trans = bch2_trans_get(c); while ((folio = readpage_iter_peek(&readpages_iter))) { unsigned n = min_t(unsigned, readpages_iter.folios.nr - @@ -289,10 +289,10 @@ void bch2_readahead(struct readahead_control *ractl) &readpages_iter); bch2_trans_unlock(trans); } + bch2_trans_put(trans); bch2_pagecache_add_put(inode); - bch2_trans_put(trans); darray_exit(&readpages_iter.folios); } From 2ba24864d2f61b52210ba645ee5af1d0422a7ea9 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 20 May 2024 03:13:57 -0400 Subject: [PATCH 14/18] bcachefs: Fix stack oob in __bch2_encrypt_bio() Reported-by: syzbot+fff6b0fb00259873576a@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/checksum.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/bcachefs/checksum.c b/fs/bcachefs/checksum.c index 4b3d6f0137f6..3bd3aba90d8f 100644 --- a/fs/bcachefs/checksum.c +++ b/fs/bcachefs/checksum.c @@ -352,8 +352,12 @@ int __bch2_encrypt_bio(struct bch_fs *c, unsigned type, bytes += bv.bv_len; } - sg_mark_end(sg - 1); - return do_encrypt_sg(c->chacha20, nonce, sgl, bytes); + if (sg != sgl) { + sg_mark_end(sg - 1); + return do_encrypt_sg(c->chacha20, nonce, sgl, bytes); + } + + return ret; } struct bch_csum bch2_checksum_merge(unsigned type, struct bch_csum a, From 2195b755ebd23992c5758d2d02a8080eac2baeca Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 22 May 2024 19:14:08 -0400 Subject: [PATCH 15/18] bcachefs: Fix unsafety in bch2_dirent_name_bytes() Reported-by: syzbot+84fa6fb8c7f98b93cdea@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/dirent.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c index 6bbf9a7d9e4d..c67460d8205d 100644 --- a/fs/bcachefs/dirent.c +++ b/fs/bcachefs/dirent.c @@ -15,6 +15,9 @@ static unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d) { + if (bkey_val_bytes(d.k) < offsetof(struct bch_dirent, d_name)) + return 0; + unsigned bkey_u64s = bkey_val_u64s(d.k); unsigned bkey_bytes = bkey_u64s * sizeof(u64); u64 last_u64 = ((u64*)d.v)[bkey_u64s - 1]; From d293ece108104967ec3465f253834c0511170f04 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 22 May 2024 19:53:03 -0400 Subject: [PATCH 16/18] bcachefs: Fix shutdown ordering the btree key cache uses the srcu struct created/destroyed by btree_iter.c; btree_iter needs to be exited last. Reported-by: syzbot+3af9daea347788b15213@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/printbuf.c | 7 +++++++ fs/bcachefs/super.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/printbuf.c b/fs/bcachefs/printbuf.c index 8b0369185f5c..9f529e4c1b16 100644 --- a/fs/bcachefs/printbuf.c +++ b/fs/bcachefs/printbuf.c @@ -45,6 +45,13 @@ int bch2_printbuf_make_room(struct printbuf *out, unsigned extra) unsigned new_size = roundup_pow_of_two(out->size + extra); + /* Sanity check... */ + if (new_size > PAGE_SIZE << MAX_PAGE_ORDER) { + out->allocation_failure = true; + out->overflow = true; + return -ENOMEM; + } + /* * Note: output buffer must be freeable with kfree(), it's not required * that the user use printbuf_exit(). diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 294a9d35a9f2..2206a8dee693 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -551,9 +551,9 @@ static void __bch2_fs_free(struct bch_fs *c) bch2_fs_io_read_exit(c); bch2_fs_buckets_waiting_for_journal_exit(c); bch2_fs_btree_interior_update_exit(c); - bch2_fs_btree_iter_exit(c); bch2_fs_btree_key_cache_exit(&c->btree_key_cache); bch2_fs_btree_cache_exit(c); + bch2_fs_btree_iter_exit(c); bch2_fs_replicas_exit(c); bch2_fs_journal_exit(&c->journal); bch2_io_clock_exit(&c->io_clock[WRITE]); From cd3b31f9d4174cccafd8da615d73f40c1ce48939 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 22 May 2024 20:17:05 -0400 Subject: [PATCH 17/18] bcachefs: Ensure we're RW before journalling Reported-by: syzbot+c60cd352aedb109528bf@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/recovery.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 63f990f5c63a..cf513fc79ce4 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -811,9 +811,11 @@ int bch2_fs_recovery(struct bch_fs *c) clear_bit(BCH_FS_fsck_running, &c->flags); /* fsync if we fixed errors */ - if (test_bit(BCH_FS_errors_fixed, &c->flags)) { + if (test_bit(BCH_FS_errors_fixed, &c->flags) && + bch2_write_ref_tryget(c, BCH_WRITE_REF_fsync)) { bch2_journal_flush_all_pins(&c->journal); bch2_journal_meta(&c->journal); + bch2_write_ref_put(c, BCH_WRITE_REF_fsync); } /* If we fixed errors, verify that fs is actually clean now: */ From d93ff5fa40b9db5f505d508336bc171f54db862e Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 22 May 2024 20:36:42 -0400 Subject: [PATCH 18/18] bcachefs: Fix race path in bch2_inode_insert() __destroy_new_inode() is appropriate when we have _just_allocated the inode, but not when it's been fully initialized and on i_sb_list. Reported-by: syzbot+a0ddc9873c280a4cb18f@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet --- fs/bcachefs/fs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 9b41c6e9deef..96040a95cf46 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -188,8 +188,7 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino BUG_ON(!old); if (unlikely(old != inode)) { - __destroy_inode(&inode->v); - kmem_cache_free(bch2_inode_cache, inode); + discard_new_inode(&inode->v); inode = old; } else { mutex_lock(&c->vfs_inodes_lock);