diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-02-27 11:34:21 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2022-03-12 20:14:08 -0500 |
commit | 2bcbaac8813ba4f78d9b47bc554a4533ea1be92e (patch) | |
tree | f731bc31eedd8ac4e8616bd066c4e9f18520c645 | |
parent | 85b15f459c58576acbcd19ea813e20f26ed9b2d2 (diff) |
bcachefs: Fix a use after free
This fixes a regression from "bcachefs: Stash a copy of key being
overwritten in btree_insert_entry". In btree_key_can_insert_cached(), we
may reallocate the key cache key, invalidating pointers previously
returned by peek() - fix it by issuing a transaction restart.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 13 | ||||
-rw-r--r-- | include/trace/events/bcachefs.h | 8 |
2 files changed, 20 insertions, 1 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index b4b45540683c..ee978f33390e 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -381,7 +381,18 @@ btree_key_can_insert_cached(struct btree_trans *trans, ck->u64s = new_u64s; ck->k = new_k; - return BTREE_INSERT_OK; + /* + * Keys returned by peek() are no longer valid pointers, so we need a + * transaction restart: + */ + trace_trans_restart_key_cache_key_realloced(trans->fn, _RET_IP_, + path->btree_id, &path->pos); + /* + * Not using btree_trans_restart() because we can't unlock here, we have + * write locks held: + */ + trans->restarted = true; + return -EINTR; } static inline void do_btree_insert_one(struct btree_trans *trans, diff --git a/include/trace/events/bcachefs.h b/include/trace/events/bcachefs.h index 8cf6669e2830..0596887959d3 100644 --- a/include/trace/events/bcachefs.h +++ b/include/trace/events/bcachefs.h @@ -918,6 +918,14 @@ TRACE_EVENT(trans_restart_mem_realloced, __entry->bytes) ); +DEFINE_EVENT(transaction_restart_iter, trans_restart_key_cache_key_realloced, + TP_PROTO(const char *trans_fn, + unsigned long caller_ip, + enum btree_id btree_id, + struct bpos *pos), + TP_ARGS(trans_fn, caller_ip, btree_id, pos) +); + #endif /* _TRACE_BCACHE_H */ /* This part must be outside protection */ |