summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-02-27 11:34:21 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2022-03-12 20:14:08 -0500
commit2bcbaac8813ba4f78d9b47bc554a4533ea1be92e (patch)
treef731bc31eedd8ac4e8616bd066c4e9f18520c645
parent85b15f459c58576acbcd19ea813e20f26ed9b2d2 (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.c13
-rw-r--r--include/trace/events/bcachefs.h8
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 */