diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-02-22 17:57:59 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:54 -0400 |
commit | 64784ade4fd75cdd47d7ddfbfcbed3506fe10523 (patch) | |
tree | f0ef0f061a485560cd36a27725eb6c99300a8383 | |
parent | 43b0e8787ecb92760202c0682172141ed4b22c62 (diff) | |
download | linux-stable-64784ade4fd75cdd47d7ddfbfcbed3506fe10523.tar.gz linux-stable-64784ade4fd75cdd47d7ddfbfcbed3506fe10523.tar.bz2 linux-stable-64784ade4fd75cdd47d7ddfbfcbed3506fe10523.zip |
bcachefs: Fix buffer overrun in ec_stripe_update_extent()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/ec.c | 35 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 12 | ||||
-rw-r--r-- | fs/bcachefs/extents.h | 12 |
3 files changed, 26 insertions, 33 deletions
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 924494868102..4b054f7c4d4e 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -865,25 +865,6 @@ err: return ret; } -static void extent_stripe_ptr_add(struct bkey_s_extent e, - struct ec_stripe_buf *s, - struct bch_extent_ptr *ptr, - unsigned block) -{ - struct bch_extent_stripe_ptr *dst = (void *) ptr; - union bch_extent_entry *end = extent_entry_last(e); - - memmove_u64s_up(dst + 1, dst, (u64 *) end - (u64 *) dst); - e.k->u64s += sizeof(*dst) / sizeof(u64); - - *dst = (struct bch_extent_stripe_ptr) { - .type = 1 << BCH_EXTENT_ENTRY_stripe_ptr, - .block = block, - .redundancy = s->key.v.nr_redundant, - .idx = s->key.k.p.offset, - }; -} - static int ec_stripe_update_extent(struct btree_trans *trans, struct bpos bucket, u8 gen, struct ec_stripe_buf *s, @@ -895,6 +876,7 @@ static int ec_stripe_update_extent(struct btree_trans *trans, struct bkey_s_c k; const struct bch_extent_ptr *ptr_c; struct bch_extent_ptr *ptr, *ec_ptr = NULL; + struct bch_extent_stripe_ptr stripe_ptr; struct bkey_i *n; int ret, dev, block; @@ -933,16 +915,27 @@ static int ec_stripe_update_extent(struct btree_trans *trans, dev = s->key.v.ptrs[block].dev; - n = bch2_bkey_make_mut(trans, k); + n = bch2_trans_kmalloc(trans, bkey_bytes(k.k) + sizeof(stripe_ptr)); ret = PTR_ERR_OR_ZERO(n); if (ret) goto out; + bkey_reassemble(n, k); + bch2_bkey_drop_ptrs(bkey_i_to_s(n), ptr, ptr->dev != dev); ec_ptr = (void *) bch2_bkey_has_device(bkey_i_to_s_c(n), dev); BUG_ON(!ec_ptr); - extent_stripe_ptr_add(bkey_i_to_s_extent(n), s, ec_ptr, block); + stripe_ptr = (struct bch_extent_stripe_ptr) { + .type = 1 << BCH_EXTENT_ENTRY_stripe_ptr, + .block = block, + .redundancy = s->key.v.nr_redundant, + .idx = s->key.k.p.offset, + }; + + __extent_entry_insert(n, + (union bch_extent_entry *) ec_ptr, + (union bch_extent_entry *) &stripe_ptr); ret = bch2_trans_update(trans, &iter, n, 0); out: diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index a55e0ed75548..38be9bf91264 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -705,18 +705,6 @@ void bch2_bkey_extent_entry_drop(struct bkey_i *k, union bch_extent_entry *entry k->k.u64s -= extent_entry_u64s(entry); } -static inline void __extent_entry_insert(struct bkey_i *k, - union bch_extent_entry *dst, - union bch_extent_entry *new) -{ - union bch_extent_entry *end = bkey_val_end(bkey_i_to_s(k)); - - memmove_u64s_up_small((u64 *) dst + extent_entry_u64s(new), - dst, (u64 *) end - (u64 *) dst); - k->k.u64s += extent_entry_u64s(new); - memcpy_u64s_small(dst, new, extent_entry_u64s(new)); -} - void bch2_extent_ptr_decoded_append(struct bkey_i *k, struct extent_ptr_decoded *p) { diff --git a/fs/bcachefs/extents.h b/fs/bcachefs/extents.h index c52a09832857..2e37543a6229 100644 --- a/fs/bcachefs/extents.h +++ b/fs/bcachefs/extents.h @@ -76,6 +76,18 @@ static inline size_t extent_entry_u64s(const union bch_extent_entry *entry) return extent_entry_bytes(entry) / sizeof(u64); } +static inline void __extent_entry_insert(struct bkey_i *k, + union bch_extent_entry *dst, + union bch_extent_entry *new) +{ + union bch_extent_entry *end = bkey_val_end(bkey_i_to_s(k)); + + memmove_u64s_up_small((u64 *) dst + extent_entry_u64s(new), + dst, (u64 *) end - (u64 *) dst); + k->k.u64s += extent_entry_u64s(new); + memcpy_u64s_small(dst, new, extent_entry_u64s(new)); +} + static inline bool extent_entry_is_ptr(const union bch_extent_entry *e) { return extent_entry_type(e) == BCH_EXTENT_ENTRY_ptr; |