From: Greg Kroah-Hartman Date: Mon, 12 Jun 2023 10:06:03 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.14.318~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=425ebf0b9d4ec296341b7fd67a35ce5fc94d94c7;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: btrfs-check-return-value-of-btrfs_commit_transaction-in-relocation.patch btrfs-unset-reloc-control-if-transaction-commit-fails-in-prepare_to_relocate.patch mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch rbd-get-snapshot-context-after-exclusive-lock-is-ensured-to-be-held.patch --- diff --git a/queue-5.4/btrfs-check-return-value-of-btrfs_commit_transaction-in-relocation.patch b/queue-5.4/btrfs-check-return-value-of-btrfs_commit_transaction-in-relocation.patch new file mode 100644 index 00000000000..c658b04876b --- /dev/null +++ b/queue-5.4/btrfs-check-return-value-of-btrfs_commit_transaction-in-relocation.patch @@ -0,0 +1,56 @@ +From fb686c6824dd6294ca772b92424b8fba666e7d00 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 12 Mar 2021 15:25:34 -0500 +Subject: btrfs: check return value of btrfs_commit_transaction in relocation + +From: Josef Bacik + +commit fb686c6824dd6294ca772b92424b8fba666e7d00 upstream. + +There are a few places where we don't check the return value of +btrfs_commit_transaction in relocation.c. Thankfully all these places +have straightforward error handling, so simply change all of the sites +at once. + +Reviewed-by: Qu Wenruo +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Stefan Ghinea +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/relocation.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -2511,7 +2511,7 @@ again: + list_splice(&reloc_roots, &rc->reloc_roots); + + if (!err) +- btrfs_commit_transaction(trans); ++ err = btrfs_commit_transaction(trans); + else + btrfs_end_transaction(trans); + return err; +@@ -4102,8 +4102,7 @@ int prepare_to_relocate(struct reloc_con + */ + return PTR_ERR(trans); + } +- btrfs_commit_transaction(trans); +- return 0; ++ return btrfs_commit_transaction(trans); + } + + static noinline_for_stack int relocate_block_group(struct reloc_control *rc) +@@ -4263,7 +4262,9 @@ restart: + err = PTR_ERR(trans); + goto out_free; + } +- btrfs_commit_transaction(trans); ++ ret = btrfs_commit_transaction(trans); ++ if (ret && !err) ++ err = ret; + out_free: + ret = clean_dirty_subvols(rc); + if (ret < 0 && !err) diff --git a/queue-5.4/btrfs-unset-reloc-control-if-transaction-commit-fails-in-prepare_to_relocate.patch b/queue-5.4/btrfs-unset-reloc-control-if-transaction-commit-fails-in-prepare_to_relocate.patch new file mode 100644 index 00000000000..1433bf7ed56 --- /dev/null +++ b/queue-5.4/btrfs-unset-reloc-control-if-transaction-commit-fails-in-prepare_to_relocate.patch @@ -0,0 +1,103 @@ +From 85f02d6c856b9f3a0acf5219de6e32f58b9778eb Mon Sep 17 00:00:00 2001 +From: Zixuan Fu +Date: Thu, 21 Jul 2022 15:48:29 +0800 +Subject: btrfs: unset reloc control if transaction commit fails in prepare_to_relocate() + +From: Zixuan Fu + +commit 85f02d6c856b9f3a0acf5219de6e32f58b9778eb upstream. + +In btrfs_relocate_block_group(), the rc is allocated. Then +btrfs_relocate_block_group() calls + +relocate_block_group() + prepare_to_relocate() + set_reloc_control() + +that assigns rc to the variable fs_info->reloc_ctl. When +prepare_to_relocate() returns, it calls + +btrfs_commit_transaction() + btrfs_start_dirty_block_groups() + btrfs_alloc_path() + kmem_cache_zalloc() + +which may fail for example (or other errors could happen). When the +failure occurs, btrfs_relocate_block_group() detects the error and frees +rc and doesn't set fs_info->reloc_ctl to NULL. After that, in +btrfs_init_reloc_root(), rc is retrieved from fs_info->reloc_ctl and +then used, which may cause a use-after-free bug. + +This possible bug can be triggered by calling btrfs_ioctl_balance() +before calling btrfs_ioctl_defrag(). + +To fix this possible bug, in prepare_to_relocate(), check if +btrfs_commit_transaction() fails. If the failure occurs, +unset_reloc_control() is called to set fs_info->reloc_ctl to NULL. + +The error log in our fault-injection testing is shown as follows: + + [ 58.751070] BUG: KASAN: use-after-free in btrfs_init_reloc_root+0x7ca/0x920 [btrfs] + ... + [ 58.753577] Call Trace: + ... + [ 58.755800] kasan_report+0x45/0x60 + [ 58.756066] btrfs_init_reloc_root+0x7ca/0x920 [btrfs] + [ 58.757304] record_root_in_trans+0x792/0xa10 [btrfs] + [ 58.757748] btrfs_record_root_in_trans+0x463/0x4f0 [btrfs] + [ 58.758231] start_transaction+0x896/0x2950 [btrfs] + [ 58.758661] btrfs_defrag_root+0x250/0xc00 [btrfs] + [ 58.759083] btrfs_ioctl_defrag+0x467/0xa00 [btrfs] + [ 58.759513] btrfs_ioctl+0x3c95/0x114e0 [btrfs] + ... + [ 58.768510] Allocated by task 23683: + [ 58.768777] ____kasan_kmalloc+0xb5/0xf0 + [ 58.769069] __kmalloc+0x227/0x3d0 + [ 58.769325] alloc_reloc_control+0x10a/0x3d0 [btrfs] + [ 58.769755] btrfs_relocate_block_group+0x7aa/0x1e20 [btrfs] + [ 58.770228] btrfs_relocate_chunk+0xf1/0x760 [btrfs] + [ 58.770655] __btrfs_balance+0x1326/0x1f10 [btrfs] + [ 58.771071] btrfs_balance+0x3150/0x3d30 [btrfs] + [ 58.771472] btrfs_ioctl_balance+0xd84/0x1410 [btrfs] + [ 58.771902] btrfs_ioctl+0x4caa/0x114e0 [btrfs] + ... + [ 58.773337] Freed by task 23683: + ... + [ 58.774815] kfree+0xda/0x2b0 + [ 58.775038] free_reloc_control+0x1d6/0x220 [btrfs] + [ 58.775465] btrfs_relocate_block_group+0x115c/0x1e20 [btrfs] + [ 58.775944] btrfs_relocate_chunk+0xf1/0x760 [btrfs] + [ 58.776369] __btrfs_balance+0x1326/0x1f10 [btrfs] + [ 58.776784] btrfs_balance+0x3150/0x3d30 [btrfs] + [ 58.777185] btrfs_ioctl_balance+0xd84/0x1410 [btrfs] + [ 58.777621] btrfs_ioctl+0x4caa/0x114e0 [btrfs] + ... + +Reported-by: TOTE Robot +CC: stable@vger.kernel.org # 5.15+ +Reviewed-by: Sweet Tea Dorminy +Reviewed-by: Nikolay Borisov +Signed-off-by: Zixuan Fu +Signed-off-by: David Sterba +Signed-off-by: Stefan Ghinea +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/relocation.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -4102,7 +4102,12 @@ int prepare_to_relocate(struct reloc_con + */ + return PTR_ERR(trans); + } +- return btrfs_commit_transaction(trans); ++ ++ ret = btrfs_commit_transaction(trans); ++ if (ret) ++ unset_reloc_control(rc); ++ ++ return ret; + } + + static noinline_for_stack int relocate_block_group(struct reloc_control *rc) diff --git a/queue-5.4/mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch b/queue-5.4/mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch new file mode 100644 index 00000000000..13efcf69419 --- /dev/null +++ b/queue-5.4/mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch @@ -0,0 +1,50 @@ +From 5ece78de88739b4c68263e9f2582380c1fd8314f Mon Sep 17 00:00:00 2001 +From: YouChing Lin +Date: Thu, 5 Nov 2020 15:23:40 +0800 +Subject: mtd: spinand: macronix: Add support for MX35LFxGE4AD + +From: YouChing Lin + +commit 5ece78de88739b4c68263e9f2582380c1fd8314f upstream. + +The Macronix MX35LF2GE4AD / MX35LF4GE4AD are 3V, 2G / 4Gbit serial +SLC NAND flash device (with on-die ECC). + +Validated by read, erase, read back, write, read back and nandtest +on Xilinx Zynq PicoZed FPGA board which included Macronix SPI Host +(drivers/spi/spi-mxic.c). + +Signed-off-by: YouChing Lin +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/1604561020-13499-1-git-send-email-ycllin@mxic.com.tw +Signed-off-by: JaimeLiao +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/nand/spi/macronix.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/mtd/nand/spi/macronix.c ++++ b/drivers/mtd/nand/spi/macronix.c +@@ -116,6 +116,22 @@ static const struct spinand_info macroni + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), ++ SPINAND_INFO("MX35LF2GE4AD", 0x26, ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), ++ SPINAND_INFO("MX35LF4GE4AD", 0x37, ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), + }; + + static int macronix_spinand_detect(struct spinand_device *spinand) diff --git a/queue-5.4/rbd-get-snapshot-context-after-exclusive-lock-is-ensured-to-be-held.patch b/queue-5.4/rbd-get-snapshot-context-after-exclusive-lock-is-ensured-to-be-held.patch new file mode 100644 index 00000000000..24bc0c25d9e --- /dev/null +++ b/queue-5.4/rbd-get-snapshot-context-after-exclusive-lock-is-ensured-to-be-held.patch @@ -0,0 +1,176 @@ +From 870611e4877eff1e8413c3fb92a585e45d5291f6 Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Mon, 5 Jun 2023 16:33:35 +0200 +Subject: rbd: get snapshot context after exclusive lock is ensured to be held + +From: Ilya Dryomov + +commit 870611e4877eff1e8413c3fb92a585e45d5291f6 upstream. + +Move capturing the snapshot context into the image request state +machine, after exclusive lock is ensured to be held for the duration of +dealing with the image request. This is needed to ensure correctness +of fast-diff states (OBJECT_EXISTS vs OBJECT_EXISTS_CLEAN) and object +deltas computed based off of them. Otherwise the object map that is +forked for the snapshot isn't guaranteed to accurately reflect the +contents of the snapshot when the snapshot is taken under I/O. This +breaks differential backup and snapshot-based mirroring use cases with +fast-diff enabled: since some object deltas may be incomplete, the +destination image may get corrupted. + +Cc: stable@vger.kernel.org +Link: https://tracker.ceph.com/issues/61472 +Signed-off-by: Ilya Dryomov +Reviewed-by: Dongsheng Yang +[idryomov@gmail.com: backport to 5.4: no rbd_img_capture_header(), + img_request not embedded in blk-mq pdu] +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 41 ++++++++++++++++++++++++----------------- + 1 file changed, 24 insertions(+), 17 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -1495,6 +1495,8 @@ static bool rbd_obj_is_tail(struct rbd_o + */ + static void rbd_obj_set_copyup_enabled(struct rbd_obj_request *obj_req) + { ++ rbd_assert(obj_req->img_request->snapc); ++ + if (obj_req->img_request->op_type == OBJ_OP_DISCARD) { + dout("%s %p objno %llu discard\n", __func__, obj_req, + obj_req->ex.oe_objno); +@@ -1613,6 +1615,7 @@ __rbd_obj_add_osd_request(struct rbd_obj + static struct ceph_osd_request * + rbd_obj_add_osd_request(struct rbd_obj_request *obj_req, int num_ops) + { ++ rbd_assert(obj_req->img_request->snapc); + return __rbd_obj_add_osd_request(obj_req, obj_req->img_request->snapc, + num_ops); + } +@@ -1741,11 +1744,14 @@ static bool rbd_dev_parent_get(struct rb + * Caller is responsible for filling in the list of object requests + * that comprises the image request, and the Linux request pointer + * (if there is one). ++ * ++ * Only snap_id is captured here, for reads. For writes, snapshot ++ * context is captured in rbd_img_object_requests() after exclusive ++ * lock is ensured to be held. + */ + static struct rbd_img_request *rbd_img_request_create( + struct rbd_device *rbd_dev, +- enum obj_operation_type op_type, +- struct ceph_snap_context *snapc) ++ enum obj_operation_type op_type) + { + struct rbd_img_request *img_request; + +@@ -1757,8 +1763,6 @@ static struct rbd_img_request *rbd_img_r + img_request->op_type = op_type; + if (!rbd_img_is_write(img_request)) + img_request->snap_id = rbd_dev->spec->snap_id; +- else +- img_request->snapc = snapc; + + if (rbd_dev_parent_get(rbd_dev)) + img_request_layered_set(img_request); +@@ -2944,7 +2948,7 @@ static int rbd_obj_read_from_parent(stru + int ret; + + child_img_req = rbd_img_request_create(img_req->rbd_dev->parent, +- OBJ_OP_READ, NULL); ++ OBJ_OP_READ); + if (!child_img_req) + return -ENOMEM; + +@@ -3635,9 +3639,19 @@ static int rbd_img_exclusive_lock(struct + + static void rbd_img_object_requests(struct rbd_img_request *img_req) + { ++ struct rbd_device *rbd_dev = img_req->rbd_dev; + struct rbd_obj_request *obj_req; + + rbd_assert(!img_req->pending.result && !img_req->pending.num_pending); ++ rbd_assert(!need_exclusive_lock(img_req) || ++ __rbd_is_lock_owner(rbd_dev)); ++ ++ if (rbd_img_is_write(img_req)) { ++ rbd_assert(!img_req->snapc); ++ down_read(&rbd_dev->header_rwsem); ++ img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc); ++ up_read(&rbd_dev->header_rwsem); ++ } + + for_each_obj_request(img_req, obj_req) { + int result = 0; +@@ -3655,7 +3669,6 @@ static void rbd_img_object_requests(stru + + static bool rbd_img_advance(struct rbd_img_request *img_req, int *result) + { +- struct rbd_device *rbd_dev = img_req->rbd_dev; + int ret; + + again: +@@ -3676,9 +3689,6 @@ again: + if (*result) + return true; + +- rbd_assert(!need_exclusive_lock(img_req) || +- __rbd_is_lock_owner(rbd_dev)); +- + rbd_img_object_requests(img_req); + if (!img_req->pending.num_pending) { + *result = img_req->pending.result; +@@ -4140,6 +4150,10 @@ static int rbd_post_acquire_action(struc + { + int ret; + ++ ret = rbd_dev_refresh(rbd_dev); ++ if (ret) ++ return ret; ++ + if (rbd_dev->header.features & RBD_FEATURE_OBJECT_MAP) { + ret = rbd_object_map_open(rbd_dev); + if (ret) +@@ -4798,7 +4812,6 @@ static void rbd_queue_workfn(struct work + struct request *rq = blk_mq_rq_from_pdu(work); + struct rbd_device *rbd_dev = rq->q->queuedata; + struct rbd_img_request *img_request; +- struct ceph_snap_context *snapc = NULL; + u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT; + u64 length = blk_rq_bytes(rq); + enum obj_operation_type op_type; +@@ -4863,10 +4876,6 @@ static void rbd_queue_workfn(struct work + + down_read(&rbd_dev->header_rwsem); + mapping_size = rbd_dev->mapping.size; +- if (op_type != OBJ_OP_READ) { +- snapc = rbd_dev->header.snapc; +- ceph_get_snap_context(snapc); +- } + up_read(&rbd_dev->header_rwsem); + + if (offset + length > mapping_size) { +@@ -4876,13 +4885,12 @@ static void rbd_queue_workfn(struct work + goto err_rq; + } + +- img_request = rbd_img_request_create(rbd_dev, op_type, snapc); ++ img_request = rbd_img_request_create(rbd_dev, op_type); + if (!img_request) { + result = -ENOMEM; + goto err_rq; + } + img_request->rq = rq; +- snapc = NULL; /* img_request consumes a ref */ + + dout("%s rbd_dev %p img_req %p %s %llu~%llu\n", __func__, rbd_dev, + img_request, obj_op_name(op_type), offset, length); +@@ -4904,7 +4912,6 @@ err_rq: + if (result) + rbd_warn(rbd_dev, "%s %llx at %llx result %d", + obj_op_name(op_type), length, offset, result); +- ceph_put_snap_context(snapc); + err: + blk_mq_end_request(rq, errno_to_blk_status(result)); + } diff --git a/queue-5.4/series b/queue-5.4/series index dc93dda8b0d..15aa6be3042 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -38,3 +38,7 @@ ext4-only-check-dquot_initialize_needed-when-debugging.patch cifs-get-rid-of-unused-parameter-in-reconn_setup_dfs_targets.patch cifs-handle-empty-list-of-targets-in-cifs_reconnect.patch drm-atomic-don-t-pollute-crtc_state-mode_blob-with-error-pointers.patch +rbd-get-snapshot-context-after-exclusive-lock-is-ensured-to-be-held.patch +btrfs-check-return-value-of-btrfs_commit_transaction-in-relocation.patch +btrfs-unset-reloc-control-if-transaction-commit-fails-in-prepare_to_relocate.patch +mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch