]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jun 2023 07:49:20 +0000 (09:49 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jun 2023 07:49:20 +0000 (09:49 +0200)
added patches:
mmc-block-ensure-error-propagation-for-non-blk.patch
nilfs2-reject-devices-with-insufficient-block-count.patch

queue-5.15/mmc-block-ensure-error-propagation-for-non-blk.patch [new file with mode: 0644]
queue-5.15/nilfs2-reject-devices-with-insufficient-block-count.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/mmc-block-ensure-error-propagation-for-non-blk.patch b/queue-5.15/mmc-block-ensure-error-propagation-for-non-blk.patch
new file mode 100644 (file)
index 0000000..ceddb18
--- /dev/null
@@ -0,0 +1,81 @@
+From 003fb0a51162d940f25fc35e70b0996a12c9e08a Mon Sep 17 00:00:00 2001
+From: Christian Loehle <CLoehle@hyperstone.com>
+Date: Wed, 26 Apr 2023 16:59:39 +0000
+Subject: mmc: block: ensure error propagation for non-blk
+
+From: Christian Loehle <CLoehle@hyperstone.com>
+
+commit 003fb0a51162d940f25fc35e70b0996a12c9e08a upstream.
+
+Requests to the mmc layer usually come through a block device IO.
+The exceptions are the ioctl interface, RPMB chardev ioctl
+and debugfs, which issue their own blk_mq requests through
+blk_execute_rq and do not query the BLK_STS error but the
+mmcblk-internal drv_op_result. This patch ensures that drv_op_result
+defaults to an error and has to be overwritten by the operation
+to be considered successful.
+
+The behavior leads to a bug where the request never propagates
+the error, e.g. by directly erroring out at mmc_blk_mq_issue_rq if
+mmc_blk_part_switch fails. The ioctl caller of the rpmb chardev then
+can never see an error (BLK_STS_IOERR, but drv_op_result is unchanged)
+and thus may assume that their call executed successfully when it did not.
+
+While always checking the blk_execute_rq return value would be
+advised, let's eliminate the error by always setting
+drv_op_result as -EIO to be overwritten on success (or other error)
+
+Fixes: 614f0388f580 ("mmc: block: move single ioctl() commands to block requests")
+Signed-off-by: Christian Loehle <cloehle@hyperstone.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/59c17ada35664b818b7bd83752119b2d@hyperstone.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Christian Loehle <cloehle@hyperstone.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/block.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -265,6 +265,7 @@ static ssize_t power_ro_lock_store(struc
+               goto out_put;
+       }
+       req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
++      req_to_mmc_queue_req(req)->drv_op_result = -EIO;
+       blk_execute_rq(NULL, req, 0);
+       ret = req_to_mmc_queue_req(req)->drv_op_result;
+       blk_put_request(req);
+@@ -656,6 +657,7 @@ static int mmc_blk_ioctl_cmd(struct mmc_
+       idatas[0] = idata;
+       req_to_mmc_queue_req(req)->drv_op =
+               rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
++      req_to_mmc_queue_req(req)->drv_op_result = -EIO;
+       req_to_mmc_queue_req(req)->drv_op_data = idatas;
+       req_to_mmc_queue_req(req)->ioc_count = 1;
+       blk_execute_rq(NULL, req, 0);
+@@ -725,6 +727,7 @@ static int mmc_blk_ioctl_multi_cmd(struc
+       }
+       req_to_mmc_queue_req(req)->drv_op =
+               rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
++      req_to_mmc_queue_req(req)->drv_op_result = -EIO;
+       req_to_mmc_queue_req(req)->drv_op_data = idata;
+       req_to_mmc_queue_req(req)->ioc_count = num_of_cmds;
+       blk_execute_rq(NULL, req, 0);
+@@ -2784,6 +2787,7 @@ static int mmc_dbg_card_status_get(void
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+       req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
++      req_to_mmc_queue_req(req)->drv_op_result = -EIO;
+       blk_execute_rq(NULL, req, 0);
+       ret = req_to_mmc_queue_req(req)->drv_op_result;
+       if (ret >= 0) {
+@@ -2822,6 +2826,7 @@ static int mmc_ext_csd_open(struct inode
+               goto out_free;
+       }
+       req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
++      req_to_mmc_queue_req(req)->drv_op_result = -EIO;
+       req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
+       blk_execute_rq(NULL, req, 0);
+       err = req_to_mmc_queue_req(req)->drv_op_result;
diff --git a/queue-5.15/nilfs2-reject-devices-with-insufficient-block-count.patch b/queue-5.15/nilfs2-reject-devices-with-insufficient-block-count.patch
new file mode 100644 (file)
index 0000000..018fde5
--- /dev/null
@@ -0,0 +1,105 @@
+From 92c5d1b860e9581d64baca76779576c0ab0d943d Mon Sep 17 00:00:00 2001
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Fri, 26 May 2023 11:13:32 +0900
+Subject: nilfs2: reject devices with insufficient block count
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+commit 92c5d1b860e9581d64baca76779576c0ab0d943d upstream.
+
+The current sanity check for nilfs2 geometry information lacks checks for
+the number of segments stored in superblocks, so even for device images
+that have been destructively truncated or have an unusually high number of
+segments, the mount operation may succeed.
+
+This causes out-of-bounds block I/O on file system block reads or log
+writes to the segments, the latter in particular causing
+"a_ops->writepages" to repeatedly fail, resulting in sync_inodes_sb() to
+hang.
+
+Fix this issue by checking the number of segments stored in the superblock
+and avoiding mounting devices that can cause out-of-bounds accesses.  To
+eliminate the possibility of overflow when calculating the number of
+blocks required for the device from the number of segments, this also adds
+a helper function to calculate the upper bound on the number of segments
+and inserts a check using it.
+
+Link: https://lkml.kernel.org/r/20230526021332.3431-1-konishi.ryusuke@gmail.com
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Reported-by: syzbot+7d50f1e54a12ba3aeae2@syzkaller.appspotmail.com
+  Link: https://syzkaller.appspot.com/bug?extid=7d50f1e54a12ba3aeae2
+Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/the_nilfs.c |   44 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 43 insertions(+), 1 deletion(-)
+
+--- a/fs/nilfs2/the_nilfs.c
++++ b/fs/nilfs2/the_nilfs.c
+@@ -405,6 +405,18 @@ unsigned long nilfs_nrsvsegs(struct the_
+                                 100));
+ }
++/**
++ * nilfs_max_segment_count - calculate the maximum number of segments
++ * @nilfs: nilfs object
++ */
++static u64 nilfs_max_segment_count(struct the_nilfs *nilfs)
++{
++      u64 max_count = U64_MAX;
++
++      do_div(max_count, nilfs->ns_blocks_per_segment);
++      return min_t(u64, max_count, ULONG_MAX);
++}
++
+ void nilfs_set_nsegments(struct the_nilfs *nilfs, unsigned long nsegs)
+ {
+       nilfs->ns_nsegments = nsegs;
+@@ -414,6 +426,8 @@ void nilfs_set_nsegments(struct the_nilf
+ static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
+                                  struct nilfs_super_block *sbp)
+ {
++      u64 nsegments, nblocks;
++
+       if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) {
+               nilfs_err(nilfs->ns_sb,
+                         "unsupported revision (superblock rev.=%d.%d, current rev.=%d.%d). Please check the version of mkfs.nilfs(2).",
+@@ -457,7 +471,35 @@ static int nilfs_store_disk_layout(struc
+               return -EINVAL;
+       }
+-      nilfs_set_nsegments(nilfs, le64_to_cpu(sbp->s_nsegments));
++      nsegments = le64_to_cpu(sbp->s_nsegments);
++      if (nsegments > nilfs_max_segment_count(nilfs)) {
++              nilfs_err(nilfs->ns_sb,
++                        "segment count %llu exceeds upper limit (%llu segments)",
++                        (unsigned long long)nsegments,
++                        (unsigned long long)nilfs_max_segment_count(nilfs));
++              return -EINVAL;
++      }
++
++      nblocks = (u64)i_size_read(nilfs->ns_sb->s_bdev->bd_inode) >>
++              nilfs->ns_sb->s_blocksize_bits;
++      if (nblocks) {
++              u64 min_block_count = nsegments * nilfs->ns_blocks_per_segment;
++              /*
++               * To avoid failing to mount early device images without a
++               * second superblock, exclude that block count from the
++               * "min_block_count" calculation.
++               */
++
++              if (nblocks < min_block_count) {
++                      nilfs_err(nilfs->ns_sb,
++                                "total number of segment blocks %llu exceeds device size (%llu blocks)",
++                                (unsigned long long)min_block_count,
++                                (unsigned long long)nblocks);
++                      return -EINVAL;
++              }
++      }
++
++      nilfs_set_nsegments(nilfs, nsegments);
+       nilfs->ns_crc_seed = le32_to_cpu(sbp->s_crc_seed);
+       return 0;
+ }
index b8d08e3cfce32534bc1e0ce2ba8ffcdd01e0ff9b..a6a9740dc6d31a9909dc83ac8ef88ae80050424d 100644 (file)
@@ -104,3 +104,5 @@ net-remove-unused-inline-function-dst_hold_and_use.patch
 net-remove-decnet-leftovers-from-flow.h.patch
 neighbour-delete-neigh_lookup_nodev-as-not-used.patch
 of-overlay-add-entry-to-of_overlay_action_name.patch
+mmc-block-ensure-error-propagation-for-non-blk.patch
+nilfs2-reject-devices-with-insufficient-block-count.patch