diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-11-14 10:22:30 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:09:46 +0300 |
commit | 061f7999a6322c639dd6616dc6d3785957de2bc3 (patch) | |
tree | febba2966132f8a61e387bbded3a04441037848d /fs/bcachefs/btree_key_cache.c | |
parent | 961cbdef3c270266e17aa831cf22eb14b900af65 (diff) | |
download | linux-061f7999a6322c639dd6616dc6d3785957de2bc3.tar.xz |
bcachefs: Fix a use after free
This fixes a regression from percpu freedlists in the btree key cache
code: in a rare error path, we were immediately freeing a bkey_cached
that had been used before and should've waited for an SRCU barrier.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/btree_key_cache.c')
-rw-r--r-- | fs/bcachefs/btree_key_cache.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index 179669dbd688..1ac91221cc95 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -190,7 +190,8 @@ static void bkey_cached_free_fast(struct btree_key_cache *bc, } static struct bkey_cached * -bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path) +bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path, + bool *was_new) { struct bch_fs *c = trans->c; struct btree_key_cache *bc = &c->btree_key_cache; @@ -275,6 +276,7 @@ bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path) ck->c.cached = true; BUG_ON(!six_trylock_intent(&ck->c.lock)); BUG_ON(!six_trylock_write(&ck->c.lock)); + *was_new = true; return ck; } @@ -313,9 +315,9 @@ btree_key_cache_create(struct btree_trans *trans, struct btree_path *path) struct bch_fs *c = trans->c; struct btree_key_cache *bc = &c->btree_key_cache; struct bkey_cached *ck; - bool was_new = true; + bool was_new = false; - ck = bkey_cached_alloc(trans, path); + ck = bkey_cached_alloc(trans, path, &was_new); if (IS_ERR(ck)) return ck; @@ -328,7 +330,6 @@ btree_key_cache_create(struct btree_trans *trans, struct btree_path *path) } mark_btree_node_locked(trans, path, 0, SIX_LOCK_intent); - was_new = false; } else { if (path->btree_id == BTREE_ID_subvolumes) six_lock_pcpu_alloc(&ck->c.lock); |