From ddf11d8c60b0d46dd25520d388243b508d6e9016 Mon Sep 17 00:00:00 2001 From: Kent Overstreet <kent.overstreet@gmail.com> Date: Sun, 27 Feb 2022 11:34:21 -0500 Subject: [PATCH] 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> --- fs/bcachefs/btree_update_leaf.c | 13 ++++++++++++- fs/bcachefs/trace.h | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index dc4dfcda8f21..42ee54cf390d 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -382,7 +382,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/fs/bcachefs/trace.h b/fs/bcachefs/trace.h index b35022dc66c2..af3785254c71 100644 --- a/fs/bcachefs/trace.h +++ b/fs/bcachefs/trace.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_BCACHEFS_H */ /* This part must be outside protection */ -- 2.30.9