From 22d8a33d30d7a28d0dd972f36cc48b80f585d67b Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Fri, 22 May 2020 15:50:05 +0100 Subject: [PATCH] bcachefs: fix stack corruption When a bkey_on_stack is passed to bch_read_indirect_extent, there is no guarantee that it will be big enough to hold the bkey. And bch_read_indirect_extent is not aware of bkey_on_stack to call realloc on it. This cause a stack corruption. This commit makes bch_read_indirect_extent aware of bkey_on_stack so it can call realloc when appropriate. Tested-by: Yuxuan Shui Signed-off-by: Yuxuan Shui Signed-off-by: Kent Overstreet --- fs/bcachefs/fs-io.c | 2 +- fs/bcachefs/fs.c | 2 +- fs/bcachefs/io.c | 10 +++++----- fs/bcachefs/io.h | 7 ++++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 9644d4624f803..7ce6d71aca29c 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -788,7 +788,7 @@ retry: sectors = k.k->size - offset_into_extent; ret = bch2_read_indirect_extent(trans, - &offset_into_extent, sk.k); + &offset_into_extent, &sk); if (ret) break; diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 4458a98b78eed..6aff3203b4e10 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -918,7 +918,7 @@ retry: sectors = k.k->size - offset_into_extent; ret = bch2_read_indirect_extent(&trans, - &offset_into_extent, cur.k); + &offset_into_extent, &cur); if (ret) break; diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c index 7df2b6c3f1680..39a23c6570eb8 100644 --- a/fs/bcachefs/io.c +++ b/fs/bcachefs/io.c @@ -1642,7 +1642,7 @@ retry: sectors = k.k->size - offset_into_extent; ret = bch2_read_indirect_extent(&trans, - &offset_into_extent, sk.k); + &offset_into_extent, &sk); if (ret) break; @@ -1944,14 +1944,14 @@ static void bch2_read_endio(struct bio *bio) int __bch2_read_indirect_extent(struct btree_trans *trans, unsigned *offset_into_extent, - struct bkey_i *orig_k) + struct bkey_on_stack *orig_k) { struct btree_iter *iter; struct bkey_s_c k; u64 reflink_offset; int ret; - reflink_offset = le64_to_cpu(bkey_i_to_reflink_p(orig_k)->v.idx) + + reflink_offset = le64_to_cpu(bkey_i_to_reflink_p(orig_k->k)->v.idx) + *offset_into_extent; iter = bch2_trans_get_iter(trans, BTREE_ID_REFLINK, @@ -1974,7 +1974,7 @@ int __bch2_read_indirect_extent(struct btree_trans *trans, } *offset_into_extent = iter->pos.offset - bkey_start_offset(k.k); - bkey_reassemble(orig_k, k); + bkey_on_stack_reassemble(orig_k, trans->c, k); err: bch2_trans_iter_put(trans, iter); return ret; @@ -2281,7 +2281,7 @@ retry: k = bkey_i_to_s_c(sk.k); ret = bch2_read_indirect_extent(&trans, - &offset_into_extent, sk.k); + &offset_into_extent, &sk); if (ret) goto err; diff --git a/fs/bcachefs/io.h b/fs/bcachefs/io.h index 0a049cc14e42d..f0fe0bf906d3c 100644 --- a/fs/bcachefs/io.h +++ b/fs/bcachefs/io.h @@ -3,6 +3,7 @@ #define _BCACHEFS_IO_H #include "checksum.h" +#include "bkey_on_stack.h" #include "io_types.h" #define to_wbio(_bio) \ @@ -114,13 +115,13 @@ struct cache_promote_op; struct extent_ptr_decoded; int __bch2_read_indirect_extent(struct btree_trans *, unsigned *, - struct bkey_i *); + struct bkey_on_stack *); static inline int bch2_read_indirect_extent(struct btree_trans *trans, unsigned *offset_into_extent, - struct bkey_i *k) + struct bkey_on_stack *k) { - return k->k.type == KEY_TYPE_reflink_p + return k->k->k.type == KEY_TYPE_reflink_p ? __bch2_read_indirect_extent(trans, offset_into_extent, k) : 0; } -- 2.30.2