]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Fix null ptr deref in btree_path_lock_root()
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 27 Nov 2024 03:59:27 +0000 (22:59 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:20 +0000 (01:36 -0500)
Historically, we required that all btree node roots point to a valid
(possibly fake) node, but we're improving our ability to continue in the
presence of errors.

Reported-by: syzbot+e22007d6acb9c87c2362@syzkaller.appspotmail.com
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.c

index 89f9665ce70d9419784651fdc438dbac32666ede..80c3b55ce7637f23a7c8fbbe82e2881ede726d01 100644 (file)
@@ -722,7 +722,7 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
                                       unsigned long trace_ip)
 {
        struct bch_fs *c = trans->c;
-       struct btree *b, **rootp = &bch2_btree_id_root(c, path->btree_id)->b;
+       struct btree_root *r = bch2_btree_id_root(c, path->btree_id);
        enum six_lock_type lock_type;
        unsigned i;
        int ret;
@@ -730,7 +730,12 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
        EBUG_ON(path->nodes_locked);
 
        while (1) {
-               b = READ_ONCE(*rootp);
+               struct btree *b = READ_ONCE(r->b);
+               if (unlikely(!b)) {
+                       BUG_ON(!r->error);
+                       return r->error;
+               }
+
                path->level = READ_ONCE(b->c.level);
 
                if (unlikely(path->level < depth_want)) {
@@ -755,7 +760,7 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
                        BUG();
                }
 
-               if (likely(b == READ_ONCE(*rootp) &&
+               if (likely(b == READ_ONCE(r->b) &&
                           b->c.level == path->level &&
                           !race_fault())) {
                        for (i = 0; i < path->level; i++)