From: Greg Kroah-Hartman Date: Fri, 17 Oct 2025 08:05:07 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v5.15.195~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0460a8e900b9d8940ed6406f5b377f1c4cee4cea;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: arm64-dts-qcom-sdm845-fix-slimbam-num-channels-ees.patch asoc-codecs-wcd934x-simplify-with-dev_err_probe.patch asoc-wcd934x-fix-error-handling-in-wcd934x_codec_parse_data.patch btrfs-fix-the-incorrect-max_bytes-value-for-find_lock_delalloc_range.patch dm-fix-null-pointer-dereference-in-__dm_suspend.patch fscontext-do-not-consume-log-entries-when-returning-emsgsize.patch ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch kvm-x86-don-t-re-check-l1-intercepts-when-completing-userspace-i-o.patch locking-introduce-__cleanup-based-infrastructure.patch media-mc-clear-minor-number-before-put-device.patch mfd-intel_soc_pmic_chtdc_ti-drop-unneeded-assignment-for-cache_type.patch mfd-intel_soc_pmic_chtdc_ti-fix-invalid-regmap-config-max_register-value.patch mfd-intel_soc_pmic_chtdc_ti-set-use_single_read-regmap_config-flag.patch minmax-avoid-overly-complicated-constant-expressions-in-vm-code.patch minmax-deduplicate-__unconst_integer_typeof.patch minmax-fix-indentation-of-__cmp_once-and-__clamp_once.patch minmax-introduce-min-max-_array.patch net-usb-asix-hold-pm-usage-ref-to-avoid-pm-mdio-rtnl-deadlock.patch squashfs-add-additional-inode-sanity-checking.patch squashfs-reject-negative-file-sizes-in-squashfs_read_inode.patch tracing-fix-race-condition-in-kprobe-initialization-causing-null-pointer-dereference.patch --- diff --git a/queue-5.15/arm64-dts-qcom-sdm845-fix-slimbam-num-channels-ees.patch b/queue-5.15/arm64-dts-qcom-sdm845-fix-slimbam-num-channels-ees.patch new file mode 100644 index 0000000000..8f8ce328cf --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sdm845-fix-slimbam-num-channels-ees.patch @@ -0,0 +1,49 @@ +From stable+bounces-186217-greg=kroah.com@vger.kernel.org Fri Oct 17 01:01:14 2025 +From: Sasha Levin +Date: Thu, 16 Oct 2025 19:01:06 -0400 +Subject: arm64: dts: qcom: sdm845: Fix slimbam num-channels/ees +To: stable@vger.kernel.org +Cc: Stephan Gerhold , Dmitry Baryshkov , Bjorn Andersson , Sasha Levin +Message-ID: <20251016230106.3454355-1-sashal@kernel.org> + +From: Stephan Gerhold + +[ Upstream commit 316294bb6695a43a9181973ecd4e6fb3e576a9f7 ] + +Reading the hardware registers of the &slimbam on RB3 reveals that the BAM +supports only 23 pipes (channels) and supports 4 EEs instead of 2. This +hasn't caused problems so far since nothing is using the extra channels, +but attempting to use them would lead to crashes. + +The bam_dma driver might warn in the future if the num-channels in the DT +are wrong, so correct the properties in the DT to avoid future regressions. + +Cc: stable@vger.kernel.org +Fixes: 27ca1de07dc3 ("arm64: dts: qcom: sdm845: add slimbus nodes") +Signed-off-by: Stephan Gerhold +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20250821-sdm845-slimbam-channels-v1-1-498f7d46b9ee@linaro.org +Signed-off-by: Bjorn Andersson +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/boot/dts/qcom/sdm845.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi +@@ -4839,11 +4839,11 @@ + compatible = "qcom,bam-v1.7.0"; + qcom,controlled-remotely; + reg = <0 0x17184000 0 0x2a000>; +- num-channels = <31>; ++ num-channels = <23>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <1>; +- qcom,num-ees = <2>; ++ qcom,num-ees = <4>; + iommus = <&apps_smmu 0x1806 0x0>; + }; + diff --git a/queue-5.15/asoc-codecs-wcd934x-simplify-with-dev_err_probe.patch b/queue-5.15/asoc-codecs-wcd934x-simplify-with-dev_err_probe.patch new file mode 100644 index 0000000000..eb33b222f1 --- /dev/null +++ b/queue-5.15/asoc-codecs-wcd934x-simplify-with-dev_err_probe.patch @@ -0,0 +1,66 @@ +From stable+bounces-185498-greg=kroah.com@vger.kernel.org Mon Oct 13 21:28:35 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 15:28:28 -0400 +Subject: ASoC: codecs: wcd934x: Simplify with dev_err_probe +To: stable@vger.kernel.org +Cc: Krzysztof Kozlowski , Mark Brown , Sasha Levin +Message-ID: <20251013192829.3566355-1-sashal@kernel.org> + +From: Krzysztof Kozlowski + +[ Upstream commit fa92f4294283cc7d1f29151420be9e9336182518 ] + +Replace dev_err() in probe() path with dev_err_probe() to: +1. Make code a bit simpler and easier to read, +2. Do not print messages on deferred probe. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20230418074630.8681-2-krzysztof.kozlowski@linaro.org +Signed-off-by: Mark Brown +Stable-dep-of: 4e65bda8273c ("ASoC: wcd934x: fix error handling in wcd934x_codec_parse_data()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/codecs/wcd934x.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +--- a/sound/soc/codecs/wcd934x.c ++++ b/sound/soc/codecs/wcd934x.c +@@ -5885,10 +5885,9 @@ static int wcd934x_codec_parse_data(stru + slim_get_logical_addr(wcd->sidev); + wcd->if_regmap = regmap_init_slimbus(wcd->sidev, + &wcd934x_ifc_regmap_config); +- if (IS_ERR(wcd->if_regmap)) { +- dev_err(dev, "Failed to allocate ifc register map\n"); +- return PTR_ERR(wcd->if_regmap); +- } ++ if (IS_ERR(wcd->if_regmap)) ++ return dev_err_probe(dev, PTR_ERR(wcd->if_regmap), ++ "Failed to allocate ifc register map\n"); + + of_property_read_u32(dev->parent->of_node, "qcom,dmic-sample-rate", + &wcd->dmic_sample_rate); +@@ -5940,19 +5939,15 @@ static int wcd934x_codec_probe(struct pl + memcpy(wcd->tx_chs, wcd934x_tx_chs, sizeof(wcd934x_tx_chs)); + + irq = regmap_irq_get_virq(data->irq_data, WCD934X_IRQ_SLIMBUS); +- if (irq < 0) { +- dev_err(wcd->dev, "Failed to get SLIM IRQ\n"); +- return irq; +- } ++ if (irq < 0) ++ return dev_err_probe(wcd->dev, irq, "Failed to get SLIM IRQ\n"); + + ret = devm_request_threaded_irq(dev, irq, NULL, + wcd934x_slim_irq_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "slim", wcd); +- if (ret) { +- dev_err(dev, "Failed to request slimbus irq\n"); +- return ret; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to request slimbus irq\n"); + + wcd934x_register_mclk_output(wcd); + platform_set_drvdata(pdev, wcd); diff --git a/queue-5.15/asoc-wcd934x-fix-error-handling-in-wcd934x_codec_parse_data.patch b/queue-5.15/asoc-wcd934x-fix-error-handling-in-wcd934x_codec_parse_data.patch new file mode 100644 index 0000000000..3c8da5ce89 --- /dev/null +++ b/queue-5.15/asoc-wcd934x-fix-error-handling-in-wcd934x_codec_parse_data.patch @@ -0,0 +1,85 @@ +From stable+bounces-185499-greg=kroah.com@vger.kernel.org Mon Oct 13 21:28:37 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 15:28:29 -0400 +Subject: ASoC: wcd934x: fix error handling in wcd934x_codec_parse_data() +To: stable@vger.kernel.org +Cc: Ma Ke , Dmitry Baryshkov , Mark Brown , Sasha Levin +Message-ID: <20251013192829.3566355-2-sashal@kernel.org> + +From: Ma Ke + +[ Upstream commit 4e65bda8273c938039403144730923e77916a3d7 ] + +wcd934x_codec_parse_data() contains a device reference count leak in +of_slim_get_device() where device_find_child() increases the reference +count of the device but this reference is not properly decreased in +the success path. Add put_device() in wcd934x_codec_parse_data() and +add devm_add_action_or_reset() in the probe function, which ensures +that the reference count of the device is correctly managed. + +Memory leak in regmap_init_slimbus() as the allocated regmap is not +released when the device is removed. Using devm_regmap_init_slimbus() +instead of regmap_init_slimbus() to ensure automatic regmap cleanup on +device removal. + +Calling path: of_slim_get_device() -> of_find_slim_device() -> +device_find_child(). As comment of device_find_child() says, 'NOTE: +you will need to drop the reference with put_device() after use.'. + +Found by code review. + +Cc: stable@vger.kernel.org +Fixes: a61f3b4f476e ("ASoC: wcd934x: add support to wcd9340/wcd9341 codec") +Signed-off-by: Ma Ke +Reviewed-by: Dmitry Baryshkov +Link: https://patch.msgid.link/20250923065212.26660-1-make24@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/codecs/wcd934x.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +--- a/sound/soc/codecs/wcd934x.c ++++ b/sound/soc/codecs/wcd934x.c +@@ -5863,6 +5863,13 @@ static const struct snd_soc_component_dr + .set_jack = wcd934x_codec_set_jack, + }; + ++static void wcd934x_put_device_action(void *data) ++{ ++ struct device *dev = data; ++ ++ put_device(dev); ++} ++ + static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd) + { + struct device *dev = &wcd->sdev->dev; +@@ -5883,11 +5890,13 @@ static int wcd934x_codec_parse_data(stru + } + + slim_get_logical_addr(wcd->sidev); +- wcd->if_regmap = regmap_init_slimbus(wcd->sidev, ++ wcd->if_regmap = devm_regmap_init_slimbus(wcd->sidev, + &wcd934x_ifc_regmap_config); +- if (IS_ERR(wcd->if_regmap)) ++ if (IS_ERR(wcd->if_regmap)) { ++ put_device(&wcd->sidev->dev); + return dev_err_probe(dev, PTR_ERR(wcd->if_regmap), + "Failed to allocate ifc register map\n"); ++ } + + of_property_read_u32(dev->parent->of_node, "qcom,dmic-sample-rate", + &wcd->dmic_sample_rate); +@@ -5931,6 +5940,10 @@ static int wcd934x_codec_probe(struct pl + return ret; + } + ++ ret = devm_add_action_or_reset(dev, wcd934x_put_device_action, &wcd->sidev->dev); ++ if (ret) ++ return ret; ++ + /* set default rate 9P6MHz */ + regmap_update_bits(wcd->regmap, WCD934X_CODEC_RPM_CLK_MCLK_CFG, + WCD934X_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK, diff --git a/queue-5.15/btrfs-fix-the-incorrect-max_bytes-value-for-find_lock_delalloc_range.patch b/queue-5.15/btrfs-fix-the-incorrect-max_bytes-value-for-find_lock_delalloc_range.patch new file mode 100644 index 0000000000..ddf4c7ae70 --- /dev/null +++ b/queue-5.15/btrfs-fix-the-incorrect-max_bytes-value-for-find_lock_delalloc_range.patch @@ -0,0 +1,147 @@ +From stable+bounces-185837-greg=kroah.com@vger.kernel.org Wed Oct 15 17:38:39 2025 +From: Sasha Levin +Date: Wed, 15 Oct 2025 11:37:12 -0400 +Subject: btrfs: fix the incorrect max_bytes value for find_lock_delalloc_range() +To: stable@vger.kernel.org +Cc: Qu Wenruo , David Sterba , Sasha Levin +Message-ID: <20251015153712.1461199-1-sashal@kernel.org> + +From: Qu Wenruo + +[ Upstream commit 7b26da407420e5054e3f06c5d13271697add9423 ] + +[BUG] +With my local branch to enable bs > ps support for btrfs, sometimes I +hit the following ASSERT() inside submit_one_sector(): + + ASSERT(block_start != EXTENT_MAP_HOLE); + +Please note that it's not yet possible to hit this ASSERT() in the wild +yet, as it requires btrfs bs > ps support, which is not even in the +development branch. + +But on the other hand, there is also a very low chance to hit above +ASSERT() with bs < ps cases, so this is an existing bug affect not only +the incoming bs > ps support but also the existing bs < ps support. + +[CAUSE] +Firstly that ASSERT() means we're trying to submit a dirty block but +without a real extent map nor ordered extent map backing it. + +Furthermore with extra debugging, the folio triggering such ASSERT() is +always larger than the fs block size in my bs > ps case. +(8K block size, 4K page size) + +After some more debugging, the ASSERT() is trigger by the following +sequence: + + extent_writepage() + | We got a 32K folio (4 fs blocks) at file offset 0, and the fs block + | size is 8K, page size is 4K. + | And there is another 8K folio at file offset 32K, which is also + | dirty. + | So the filemap layout looks like the following: + | + | "||" is the filio boundary in the filemap. + | "//| is the dirty range. + | + | 0 8K 16K 24K 32K 40K + | |////////| |//////////////////////||////////| + | + |- writepage_delalloc() + | |- find_lock_delalloc_range() for [0, 8K) + | | Now range [0, 8K) is properly locked. + | | + | |- find_lock_delalloc_range() for [16K, 40K) + | | |- btrfs_find_delalloc_range() returned range [16K, 40K) + | | |- lock_delalloc_folios() locked folio 0 successfully + | | | + | | | The filemap range [32K, 40K) got dropped from filemap. + | | | + | | |- lock_delalloc_folios() failed with -EAGAIN on folio 32K + | | | As the folio at 32K is dropped. + | | | + | | |- loops = 1; + | | |- max_bytes = PAGE_SIZE; + | | |- goto again; + | | | This will re-do the lookup for dirty delalloc ranges. + | | | + | | |- btrfs_find_delalloc_range() called with @max_bytes == 4K + | | | This is smaller than block size, so + | | | btrfs_find_delalloc_range() is unable to return any range. + | | \- return false; + | | + | \- Now only range [0, 8K) has an OE for it, but for dirty range + | [16K, 32K) it's dirty without an OE. + | This breaks the assumption that writepage_delalloc() will find + | and lock all dirty ranges inside the folio. + | + |- extent_writepage_io() + |- submit_one_sector() for [0, 8K) + | Succeeded + | + |- submit_one_sector() for [16K, 24K) + Triggering the ASSERT(), as there is no OE, and the original + extent map is a hole. + +Please note that, this also exposed the same problem for bs < ps +support. E.g. with 64K page size and 4K block size. + +If we failed to lock a folio, and falls back into the "loops = 1;" +branch, we will re-do the search using 64K as max_bytes. +Which may fail again to lock the next folio, and exit early without +handling all dirty blocks inside the folio. + +[FIX] +Instead of using the fixed size PAGE_SIZE as @max_bytes, use +@sectorsize, so that we are ensured to find and lock any remaining +blocks inside the folio. + +And since we're here, add an extra ASSERT() to +before calling btrfs_find_delalloc_range() to make sure the @max_bytes is +at least no smaller than a block to avoid false negative. + +Cc: stable@vger.kernel.org # 5.15+ +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +[ adapted folio terminology and API calls to page-based equivalents ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/extent_io.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2000,6 +2000,13 @@ again: + /* step one, find a bunch of delalloc bytes starting at start */ + delalloc_start = *start; + delalloc_end = 0; ++ ++ /* ++ * If @max_bytes is smaller than a block, btrfs_find_delalloc_range() can ++ * return early without handling any dirty ranges. ++ */ ++ ASSERT(max_bytes >= fs_info->sectorsize); ++ + found = btrfs_find_delalloc_range(tree, &delalloc_start, &delalloc_end, + max_bytes, &cached_state); + if (!found || delalloc_end <= *start) { +@@ -2028,13 +2035,14 @@ again: + delalloc_start, delalloc_end); + ASSERT(!ret || ret == -EAGAIN); + if (ret == -EAGAIN) { +- /* some of the pages are gone, lets avoid looping by +- * shortening the size of the delalloc range we're searching ++ /* ++ * Some of the pages are gone, lets avoid looping by ++ * shortening the size of the delalloc range we're searching. + */ + free_extent_state(cached_state); + cached_state = NULL; + if (!loops) { +- max_bytes = PAGE_SIZE; ++ max_bytes = fs_info->sectorsize; + loops = 1; + goto again; + } else { diff --git a/queue-5.15/dm-fix-null-pointer-dereference-in-__dm_suspend.patch b/queue-5.15/dm-fix-null-pointer-dereference-in-__dm_suspend.patch new file mode 100644 index 0000000000..2613f65967 --- /dev/null +++ b/queue-5.15/dm-fix-null-pointer-dereference-in-__dm_suspend.patch @@ -0,0 +1,98 @@ +From stable+bounces-185564-greg=kroah.com@vger.kernel.org Tue Oct 14 04:16:19 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 22:16:10 -0400 +Subject: dm: fix NULL pointer dereference in __dm_suspend() +To: stable@vger.kernel.org +Cc: Zheng Qixing , Mikulas Patocka , Sasha Levin +Message-ID: <20251014021610.3835566-1-sashal@kernel.org> + +From: Zheng Qixing + +[ Upstream commit 8d33a030c566e1f105cd5bf27f37940b6367f3be ] + +There is a race condition between dm device suspend and table load that +can lead to null pointer dereference. The issue occurs when suspend is +invoked before table load completes: + +BUG: kernel NULL pointer dereference, address: 0000000000000054 +Oops: 0000 [#1] PREEMPT SMP PTI +CPU: 6 PID: 6798 Comm: dmsetup Not tainted 6.6.0-g7e52f5f0ca9b #62 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014 +RIP: 0010:blk_mq_wait_quiesce_done+0x0/0x50 +Call Trace: + + blk_mq_quiesce_queue+0x2c/0x50 + dm_stop_queue+0xd/0x20 + __dm_suspend+0x130/0x330 + dm_suspend+0x11a/0x180 + dev_suspend+0x27e/0x560 + ctl_ioctl+0x4cf/0x850 + dm_ctl_ioctl+0xd/0x20 + vfs_ioctl+0x1d/0x50 + __se_sys_ioctl+0x9b/0xc0 + __x64_sys_ioctl+0x19/0x30 + x64_sys_call+0x2c4a/0x4620 + do_syscall_64+0x9e/0x1b0 + +The issue can be triggered as below: + +T1 T2 +dm_suspend table_load +__dm_suspend dm_setup_md_queue + dm_mq_init_request_queue + blk_mq_init_allocated_queue + => q->mq_ops = set->ops; (1) +dm_stop_queue / dm_wait_for_completion +=> q->tag_set NULL pointer! (2) + => q->tag_set = set; (3) + +Fix this by checking if a valid table (map) exists before performing +request-based suspend and waiting for target I/O. When map is NULL, +skip these table-dependent suspend steps. + +Even when map is NULL, no I/O can reach any target because there is +no table loaded; I/O submitted in this state will fail early in the +DM layer. Skipping the table-dependent suspend logic in this case +is safe and avoids NULL pointer dereferences. + +Fixes: c4576aed8d85 ("dm: fix request-based dm's use of dm_wait_for_completion") +Cc: stable@vger.kernel.org +Signed-off-by: Zheng Qixing +Signed-off-by: Mikulas Patocka +[ omitted DMF_QUEUE_STOPPED flag setting and braces absent in 5.15 ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2406,7 +2406,7 @@ static int __dm_suspend(struct mapped_de + { + bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG; + bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG; +- int r; ++ int r = 0; + + lockdep_assert_held(&md->suspend_lock); + +@@ -2458,7 +2458,7 @@ static int __dm_suspend(struct mapped_de + * Stop md->queue before flushing md->wq in case request-based + * dm defers requests to md->wq from md->queue. + */ +- if (dm_request_based(md)) ++ if (map && dm_request_based(md)) + dm_stop_queue(md->queue); + + flush_workqueue(md->wq); +@@ -2468,7 +2468,8 @@ static int __dm_suspend(struct mapped_de + * We call dm_wait_for_completion to wait for all existing requests + * to finish. + */ +- r = dm_wait_for_completion(md, task_state); ++ if (map) ++ r = dm_wait_for_completion(md, task_state); + if (!r) + set_bit(dmf_suspended_flag, &md->flags); + diff --git a/queue-5.15/fscontext-do-not-consume-log-entries-when-returning-emsgsize.patch b/queue-5.15/fscontext-do-not-consume-log-entries-when-returning-emsgsize.patch new file mode 100644 index 0000000000..f0462a0a8c --- /dev/null +++ b/queue-5.15/fscontext-do-not-consume-log-entries-when-returning-emsgsize.patch @@ -0,0 +1,125 @@ +From stable+bounces-185832-greg=kroah.com@vger.kernel.org Wed Oct 15 17:06:26 2025 +From: Sasha Levin +Date: Wed, 15 Oct 2025 11:05:55 -0400 +Subject: fscontext: do not consume log entries when returning -EMSGSIZE +To: stable@vger.kernel.org +Cc: Aleksa Sarai , David Howells , Christian Brauner , Sasha Levin +Message-ID: <20251015150555.1437678-2-sashal@kernel.org> + +From: Aleksa Sarai + +[ Upstream commit 72d271a7baa7062cb27e774ac37c5459c6d20e22 ] + +Userspace generally expects APIs that return -EMSGSIZE to allow for them +to adjust their buffer size and retry the operation. However, the +fscontext log would previously clear the message even in the -EMSGSIZE +case. + +Given that it is very cheap for us to check whether the buffer is too +small before we remove the message from the ring buffer, let's just do +that instead. While we're at it, refactor some fscontext_read() into a +separate helper to make the ring buffer logic a bit easier to read. + +Fixes: 007ec26cdc9f ("vfs: Implement logging through fs_context") +Cc: David Howells +Cc: stable@vger.kernel.org # v5.2+ +Signed-off-by: Aleksa Sarai +Link: https://lore.kernel.org/20250807-fscontext-log-cleanups-v3-1-8d91d6242dc3@cyphar.com +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/fsopen.c | 70 ++++++++++++++++++++++++++++++++---------------------------- + 1 file changed, 38 insertions(+), 32 deletions(-) + +--- a/fs/fsopen.c ++++ b/fs/fsopen.c +@@ -18,50 +18,56 @@ + #include "internal.h" + #include "mount.h" + ++static inline const char *fetch_message_locked(struct fc_log *log, size_t len, ++ bool *need_free) ++{ ++ const char *p; ++ int index; ++ ++ if (unlikely(log->head == log->tail)) ++ return ERR_PTR(-ENODATA); ++ ++ index = log->tail & (ARRAY_SIZE(log->buffer) - 1); ++ p = log->buffer[index]; ++ if (unlikely(strlen(p) > len)) ++ return ERR_PTR(-EMSGSIZE); ++ ++ log->buffer[index] = NULL; ++ *need_free = log->need_free & (1 << index); ++ log->need_free &= ~(1 << index); ++ log->tail++; ++ ++ return p; ++} ++ + /* + * Allow the user to read back any error, warning or informational messages. ++ * Only one message is returned for each read(2) call. + */ + static ssize_t fscontext_read(struct file *file, + char __user *_buf, size_t len, loff_t *pos) + { + struct fs_context *fc = file->private_data; +- struct fc_log *log = fc->log.log; +- unsigned int logsize = ARRAY_SIZE(log->buffer); +- ssize_t ret; +- char *p; ++ ssize_t err; ++ const char *p __free(kfree) = NULL, *message; + bool need_free; +- int index, n; +- +- ret = mutex_lock_interruptible(&fc->uapi_mutex); +- if (ret < 0) +- return ret; +- +- if (log->head == log->tail) { +- mutex_unlock(&fc->uapi_mutex); +- return -ENODATA; +- } ++ int n; + +- index = log->tail & (logsize - 1); +- p = log->buffer[index]; +- need_free = log->need_free & (1 << index); +- log->buffer[index] = NULL; +- log->need_free &= ~(1 << index); +- log->tail++; ++ err = mutex_lock_interruptible(&fc->uapi_mutex); ++ if (err < 0) ++ return err; ++ message = fetch_message_locked(fc->log.log, len, &need_free); + mutex_unlock(&fc->uapi_mutex); ++ if (IS_ERR(message)) ++ return PTR_ERR(message); + +- ret = -EMSGSIZE; +- n = strlen(p); +- if (n > len) +- goto err_free; +- ret = -EFAULT; +- if (copy_to_user(_buf, p, n) != 0) +- goto err_free; +- ret = n; +- +-err_free: + if (need_free) +- kfree(p); +- return ret; ++ p = message; ++ ++ n = strlen(message); ++ if (copy_to_user(_buf, message, n)) ++ return -EFAULT; ++ return n; + } + + static int fscontext_release(struct inode *inode, struct file *file) diff --git a/queue-5.15/ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch b/queue-5.15/ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch new file mode 100644 index 0000000000..9f4db45f92 --- /dev/null +++ b/queue-5.15/ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch @@ -0,0 +1,43 @@ +From stable+bounces-185651-greg=kroah.com@vger.kernel.org Tue Oct 14 14:47:38 2025 +From: Sasha Levin +Date: Tue, 14 Oct 2025 08:45:50 -0400 +Subject: ksmbd: fix error code overwriting in smb2_get_info_filesystem() +To: stable@vger.kernel.org +Cc: Matvey Kovalev , Namjae Jeon , Steve French , Sasha Levin +Message-ID: <20251014124550.2777-1-sashal@kernel.org> + +From: Matvey Kovalev + +[ Upstream commit 88daf2f448aad05a2e6df738d66fe8b0cf85cee0 ] + +If client doesn't negotiate with SMB3.1.1 POSIX Extensions, +then proper error code won't be returned due to overwriting. + +Return error immediately. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: e2f34481b24db ("cifsd: add server-side procedures for SMB3") +Cc: stable@vger.kernel.org +Signed-off-by: Matvey Kovalev +Acked-by: Namjae Jeon +Signed-off-by: Steve French +[ adjusted file path from fs/smb/server/smb2pdu.c to fs/ksmbd/smb2pdu.c ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2pdu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -5204,7 +5204,8 @@ static int smb2_get_info_filesystem(stru + + if (!work->tcon->posix_extensions) { + pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n"); +- rc = -EOPNOTSUPP; ++ path_put(&path); ++ return -EOPNOTSUPP; + } else { + info = (struct filesystem_posix_info *)(rsp->Buffer); + info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize); diff --git a/queue-5.15/kvm-x86-don-t-re-check-l1-intercepts-when-completing-userspace-i-o.patch b/queue-5.15/kvm-x86-don-t-re-check-l1-intercepts-when-completing-userspace-i-o.patch new file mode 100644 index 0000000000..7eb4646a02 --- /dev/null +++ b/queue-5.15/kvm-x86-don-t-re-check-l1-intercepts-when-completing-userspace-i-o.patch @@ -0,0 +1,145 @@ +From stable+bounces-185487-greg=kroah.com@vger.kernel.org Mon Oct 13 19:39:32 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 13:36:41 -0400 +Subject: KVM: x86: Don't (re)check L1 intercepts when completing userspace I/O +To: stable@vger.kernel.org +Cc: Sean Christopherson , syzbot+cc2032ba16cc2018ca25@syzkaller.appspotmail.com, Jim Mattson , Sasha Levin +Message-ID: <20251013173641.3404405-1-sashal@kernel.org> + +From: Sean Christopherson + +[ Upstream commit e750f85391286a4c8100275516973324b621a269 ] + +When completing emulation of instruction that generated a userspace exit +for I/O, don't recheck L1 intercepts as KVM has already finished that +phase of instruction execution, i.e. has already committed to allowing L2 +to perform I/O. If L1 (or host userspace) modifies the I/O permission +bitmaps during the exit to userspace, KVM will treat the access as being +intercepted despite already having emulated the I/O access. + +Pivot on EMULTYPE_NO_DECODE to detect that KVM is completing emulation. +Of the three users of EMULTYPE_NO_DECODE, only complete_emulated_io() (the +intended "recipient") can reach the code in question. gp_interception()'s +use is mutually exclusive with is_guest_mode(), and +complete_emulated_insn_gp() unconditionally pairs EMULTYPE_NO_DECODE with +EMULTYPE_SKIP. + +The bad behavior was detected by a syzkaller program that toggles port I/O +interception during the userspace I/O exit, ultimately resulting in a WARN +on vcpu->arch.pio.count being non-zero due to KVM no completing emulation +of the I/O instruction. + + WARNING: CPU: 23 PID: 1083 at arch/x86/kvm/x86.c:8039 emulator_pio_in_out+0x154/0x170 [kvm] + Modules linked in: kvm_intel kvm irqbypass + CPU: 23 UID: 1000 PID: 1083 Comm: repro Not tainted 6.16.0-rc5-c1610d2d66b1-next-vm #74 NONE + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 + RIP: 0010:emulator_pio_in_out+0x154/0x170 [kvm] + PKRU: 55555554 + Call Trace: + + kvm_fast_pio+0xd6/0x1d0 [kvm] + vmx_handle_exit+0x149/0x610 [kvm_intel] + kvm_arch_vcpu_ioctl_run+0xda8/0x1ac0 [kvm] + kvm_vcpu_ioctl+0x244/0x8c0 [kvm] + __x64_sys_ioctl+0x8a/0xd0 + do_syscall_64+0x5d/0xc60 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + + +Reported-by: syzbot+cc2032ba16cc2018ca25@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/68790db4.a00a0220.3af5df.0020.GAE@google.com +Fixes: 8a76d7f25f8f ("KVM: x86: Add x86 callback for intercept check") +Cc: stable@vger.kernel.org +Cc: Jim Mattson +Link: https://lore.kernel.org/r/20250715190638.1899116-1-seanjc@google.com +Signed-off-by: Sean Christopherson +[ is_guest_mode() was open coded ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/emulate.c | 11 ++++------- + arch/x86/kvm/kvm_emulate.h | 2 +- + arch/x86/kvm/x86.c | 9 ++++++++- + 3 files changed, 13 insertions(+), 9 deletions(-) + +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -5452,12 +5452,11 @@ void init_decode_cache(struct x86_emulat + ctxt->mem_read.end = 0; + } + +-int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) ++int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts) + { + const struct x86_emulate_ops *ops = ctxt->ops; + int rc = X86EMUL_CONTINUE; + int saved_dst_type = ctxt->dst.type; +- unsigned emul_flags; + + ctxt->mem_read.pos = 0; + +@@ -5471,8 +5470,6 @@ int x86_emulate_insn(struct x86_emulate_ + rc = emulate_ud(ctxt); + goto done; + } +- +- emul_flags = ctxt->ops->get_hflags(ctxt); + if (unlikely(ctxt->d & + (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) { + if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) || +@@ -5506,7 +5503,7 @@ int x86_emulate_insn(struct x86_emulate_ + fetch_possible_mmx_operand(&ctxt->dst); + } + +- if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) { ++ if (unlikely(check_intercepts) && ctxt->intercept) { + rc = emulator_check_intercept(ctxt, ctxt->intercept, + X86_ICPT_PRE_EXCEPT); + if (rc != X86EMUL_CONTINUE) +@@ -5535,7 +5532,7 @@ int x86_emulate_insn(struct x86_emulate_ + goto done; + } + +- if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { ++ if (unlikely(check_intercepts) && (ctxt->d & Intercept)) { + rc = emulator_check_intercept(ctxt, ctxt->intercept, + X86_ICPT_POST_EXCEPT); + if (rc != X86EMUL_CONTINUE) +@@ -5589,7 +5586,7 @@ int x86_emulate_insn(struct x86_emulate_ + + special_insn: + +- if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { ++ if (unlikely(check_intercepts) && (ctxt->d & Intercept)) { + rc = emulator_check_intercept(ctxt, ctxt->intercept, + X86_ICPT_POST_MEMACCESS); + if (rc != X86EMUL_CONTINUE) +--- a/arch/x86/kvm/kvm_emulate.h ++++ b/arch/x86/kvm/kvm_emulate.h +@@ -496,7 +496,7 @@ bool x86_page_table_writing_insn(struct + #define EMULATION_RESTART 1 + #define EMULATION_INTERCEPTED 2 + void init_decode_cache(struct x86_emulate_ctxt *ctxt); +-int x86_emulate_insn(struct x86_emulate_ctxt *ctxt); ++int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts); + int emulator_task_switch(struct x86_emulate_ctxt *ctxt, + u16 tss_selector, int idt_index, int reason, + bool has_error_code, u32 error_code); +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -8209,7 +8209,14 @@ restart: + ctxt->exception.address = 0; + } + +- r = x86_emulate_insn(ctxt); ++ /* ++ * Check L1's instruction intercepts when emulating instructions for ++ * L2, unless KVM is re-emulating a previously decoded instruction, ++ * e.g. to complete userspace I/O, in which case KVM has already ++ * checked the intercepts. ++ */ ++ r = x86_emulate_insn(ctxt, is_guest_mode(vcpu) && ++ !(emulation_type & EMULTYPE_NO_DECODE)); + + if (r == EMULATION_INTERCEPTED) + return 1; diff --git a/queue-5.15/locking-introduce-__cleanup-based-infrastructure.patch b/queue-5.15/locking-introduce-__cleanup-based-infrastructure.patch new file mode 100644 index 0000000000..24bee52d92 --- /dev/null +++ b/queue-5.15/locking-introduce-__cleanup-based-infrastructure.patch @@ -0,0 +1,624 @@ +From stable+bounces-185831-greg=kroah.com@vger.kernel.org Wed Oct 15 17:08:52 2025 +From: Sasha Levin +Date: Wed, 15 Oct 2025 11:05:54 -0400 +Subject: locking: Introduce __cleanup() based infrastructure +To: stable@vger.kernel.org +Cc: Peter Zijlstra , Sasha Levin +Message-ID: <20251015150555.1437678-1-sashal@kernel.org> + +From: Peter Zijlstra + +[ Upstream commit 54da6a0924311c7cf5015533991e44fb8eb12773 ] + +Use __attribute__((__cleanup__(func))) to build: + + - simple auto-release pointers using __free() + + - 'classes' with constructor and destructor semantics for + scope-based resource management. + + - lock guards based on the above classes. + +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20230612093537.614161713%40infradead.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/ioat/dma.c | 12 +- + include/linux/cleanup.h | 171 ++++++++++++++++++++++++++++++++++++ + include/linux/compiler-clang.h | 9 + + include/linux/compiler_attributes.h | 6 + + include/linux/device.h | 7 + + include/linux/file.h | 6 + + include/linux/irqflags.h | 7 + + include/linux/mutex.h | 4 + include/linux/percpu.h | 4 + include/linux/preempt.h | 47 +++++++++ + include/linux/rcupdate.h | 3 + include/linux/rwsem.h | 8 + + include/linux/sched/task.h | 2 + include/linux/slab.h | 3 + include/linux/spinlock.h | 32 ++++++ + include/linux/srcu.h | 5 + + scripts/checkpatch.pl | 2 + 17 files changed, 321 insertions(+), 7 deletions(-) + create mode 100644 include/linux/cleanup.h + +--- a/drivers/dma/ioat/dma.c ++++ b/drivers/dma/ioat/dma.c +@@ -584,11 +584,11 @@ desc_get_errstat(struct ioatdma_chan *io + } + + /** +- * __cleanup - reclaim used descriptors ++ * __ioat_cleanup - reclaim used descriptors + * @ioat_chan: channel (ring) to clean + * @phys_complete: zeroed (or not) completion address (from status) + */ +-static void __cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete) ++static void __ioat_cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete) + { + struct ioatdma_device *ioat_dma = ioat_chan->ioat_dma; + struct ioat_ring_ent *desc; +@@ -675,7 +675,7 @@ static void ioat_cleanup(struct ioatdma_ + spin_lock_bh(&ioat_chan->cleanup_lock); + + if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) +- __cleanup(ioat_chan, phys_complete); ++ __ioat_cleanup(ioat_chan, phys_complete); + + if (is_ioat_halted(*ioat_chan->completion)) { + u32 chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); +@@ -712,7 +712,7 @@ static void ioat_restart_channel(struct + + ioat_quiesce(ioat_chan, 0); + if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) +- __cleanup(ioat_chan, phys_complete); ++ __ioat_cleanup(ioat_chan, phys_complete); + + __ioat_restart_chan(ioat_chan); + } +@@ -786,7 +786,7 @@ static void ioat_eh(struct ioatdma_chan + + /* cleanup so tail points to descriptor that caused the error */ + if (ioat_cleanup_preamble(ioat_chan, &phys_complete)) +- __cleanup(ioat_chan, phys_complete); ++ __ioat_cleanup(ioat_chan, phys_complete); + + chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET); + pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr_int); +@@ -943,7 +943,7 @@ void ioat_timer_event(struct timer_list + /* timer restarted in ioat_cleanup_preamble + * and IOAT_COMPLETION_ACK cleared + */ +- __cleanup(ioat_chan, phys_complete); ++ __ioat_cleanup(ioat_chan, phys_complete); + goto unlock_out; + } + +--- /dev/null ++++ b/include/linux/cleanup.h +@@ -0,0 +1,171 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __LINUX_GUARDS_H ++#define __LINUX_GUARDS_H ++ ++#include ++ ++/* ++ * DEFINE_FREE(name, type, free): ++ * simple helper macro that defines the required wrapper for a __free() ++ * based cleanup function. @free is an expression using '_T' to access ++ * the variable. ++ * ++ * __free(name): ++ * variable attribute to add a scoped based cleanup to the variable. ++ * ++ * no_free_ptr(var): ++ * like a non-atomic xchg(var, NULL), such that the cleanup function will ++ * be inhibited -- provided it sanely deals with a NULL value. ++ * ++ * return_ptr(p): ++ * returns p while inhibiting the __free(). ++ * ++ * Ex. ++ * ++ * DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) ++ * ++ * struct obj *p __free(kfree) = kmalloc(...); ++ * if (!p) ++ * return NULL; ++ * ++ * if (!init_obj(p)) ++ * return NULL; ++ * ++ * return_ptr(p); ++ */ ++ ++#define DEFINE_FREE(_name, _type, _free) \ ++ static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; } ++ ++#define __free(_name) __cleanup(__free_##_name) ++ ++#define no_free_ptr(p) \ ++ ({ __auto_type __ptr = (p); (p) = NULL; __ptr; }) ++ ++#define return_ptr(p) return no_free_ptr(p) ++ ++ ++/* ++ * DEFINE_CLASS(name, type, exit, init, init_args...): ++ * helper to define the destructor and constructor for a type. ++ * @exit is an expression using '_T' -- similar to FREE above. ++ * @init is an expression in @init_args resulting in @type ++ * ++ * EXTEND_CLASS(name, ext, init, init_args...): ++ * extends class @name to @name@ext with the new constructor ++ * ++ * CLASS(name, var)(args...): ++ * declare the variable @var as an instance of the named class ++ * ++ * Ex. ++ * ++ * DEFINE_CLASS(fdget, struct fd, fdput(_T), fdget(fd), int fd) ++ * ++ * CLASS(fdget, f)(fd); ++ * if (!f.file) ++ * return -EBADF; ++ * ++ * // use 'f' without concern ++ */ ++ ++#define DEFINE_CLASS(_name, _type, _exit, _init, _init_args...) \ ++typedef _type class_##_name##_t; \ ++static inline void class_##_name##_destructor(_type *p) \ ++{ _type _T = *p; _exit; } \ ++static inline _type class_##_name##_constructor(_init_args) \ ++{ _type t = _init; return t; } ++ ++#define EXTEND_CLASS(_name, ext, _init, _init_args...) \ ++typedef class_##_name##_t class_##_name##ext##_t; \ ++static inline void class_##_name##ext##_destructor(class_##_name##_t *p)\ ++{ class_##_name##_destructor(p); } \ ++static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ ++{ class_##_name##_t t = _init; return t; } ++ ++#define CLASS(_name, var) \ ++ class_##_name##_t var __cleanup(class_##_name##_destructor) = \ ++ class_##_name##_constructor ++ ++ ++/* ++ * DEFINE_GUARD(name, type, lock, unlock): ++ * trivial wrapper around DEFINE_CLASS() above specifically ++ * for locks. ++ * ++ * guard(name): ++ * an anonymous instance of the (guard) class ++ * ++ * scoped_guard (name, args...) { }: ++ * similar to CLASS(name, scope)(args), except the variable (with the ++ * explicit name 'scope') is declard in a for-loop such that its scope is ++ * bound to the next (compound) statement. ++ * ++ */ ++ ++#define DEFINE_GUARD(_name, _type, _lock, _unlock) \ ++ DEFINE_CLASS(_name, _type, _unlock, ({ _lock; _T; }), _type _T) ++ ++#define guard(_name) \ ++ CLASS(_name, __UNIQUE_ID(guard)) ++ ++#define scoped_guard(_name, args...) \ ++ for (CLASS(_name, scope)(args), \ ++ *done = NULL; !done; done = (void *)1) ++ ++/* ++ * Additional helper macros for generating lock guards with types, either for ++ * locks that don't have a native type (eg. RCU, preempt) or those that need a ++ * 'fat' pointer (eg. spin_lock_irqsave). ++ * ++ * DEFINE_LOCK_GUARD_0(name, lock, unlock, ...) ++ * DEFINE_LOCK_GUARD_1(name, type, lock, unlock, ...) ++ * ++ * will result in the following type: ++ * ++ * typedef struct { ++ * type *lock; // 'type := void' for the _0 variant ++ * __VA_ARGS__; ++ * } class_##name##_t; ++ * ++ * As above, both _lock and _unlock are statements, except this time '_T' will ++ * be a pointer to the above struct. ++ */ ++ ++#define __DEFINE_UNLOCK_GUARD(_name, _type, _unlock, ...) \ ++typedef struct { \ ++ _type *lock; \ ++ __VA_ARGS__; \ ++} class_##_name##_t; \ ++ \ ++static inline void class_##_name##_destructor(class_##_name##_t *_T) \ ++{ \ ++ if (_T->lock) { _unlock; } \ ++} ++ ++ ++#define __DEFINE_LOCK_GUARD_1(_name, _type, _lock) \ ++static inline class_##_name##_t class_##_name##_constructor(_type *l) \ ++{ \ ++ class_##_name##_t _t = { .lock = l }, *_T = &_t; \ ++ _lock; \ ++ return _t; \ ++} ++ ++#define __DEFINE_LOCK_GUARD_0(_name, _lock) \ ++static inline class_##_name##_t class_##_name##_constructor(void) \ ++{ \ ++ class_##_name##_t _t = { .lock = (void*)1 }, \ ++ *_T __maybe_unused = &_t; \ ++ _lock; \ ++ return _t; \ ++} ++ ++#define DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, ...) \ ++__DEFINE_UNLOCK_GUARD(_name, _type, _unlock, __VA_ARGS__) \ ++__DEFINE_LOCK_GUARD_1(_name, _type, _lock) ++ ++#define DEFINE_LOCK_GUARD_0(_name, _lock, _unlock, ...) \ ++__DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__) \ ++__DEFINE_LOCK_GUARD_0(_name, _lock) ++ ++#endif /* __LINUX_GUARDS_H */ +--- a/include/linux/compiler-clang.h ++++ b/include/linux/compiler-clang.h +@@ -5,6 +5,15 @@ + + /* Compiler specific definitions for Clang compiler */ + ++/* ++ * Clang prior to 17 is being silly and considers many __cleanup() variables ++ * as unused (because they are, their sole purpose is to go out of scope). ++ * ++ * https://reviews.llvm.org/D152180 ++ */ ++#undef __cleanup ++#define __cleanup(func) __maybe_unused __attribute__((__cleanup__(func))) ++ + /* same as gcc, this was present in clang-2.6 so we can assume it works + * with any version that can compile the kernel + */ +--- a/include/linux/compiler_attributes.h ++++ b/include/linux/compiler_attributes.h +@@ -81,6 +81,12 @@ + #define __cold __attribute__((__cold__)) + + /* ++ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute ++ * clang: https://clang.llvm.org/docs/AttributeReference.html#cleanup ++ */ ++#define __cleanup(func) __attribute__((__cleanup__(func))) ++ ++/* + * Note the long name. + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + + struct device; +@@ -825,6 +826,9 @@ void device_unregister(struct device *de + void device_initialize(struct device *dev); + int __must_check device_add(struct device *dev); + void device_del(struct device *dev); ++ ++DEFINE_FREE(device_del, struct device *, if (_T) device_del(_T)) ++ + int device_for_each_child(struct device *dev, void *data, + int (*fn)(struct device *dev, void *data)); + int device_for_each_child_reverse(struct device *dev, void *data, +@@ -955,6 +959,9 @@ extern int (*platform_notify_remove)(str + */ + struct device *get_device(struct device *dev); + void put_device(struct device *dev); ++ ++DEFINE_FREE(put_device, struct device *, if (_T) put_device(_T)) ++ + bool kill_device(struct device *dev); + + #ifdef CONFIG_DEVTMPFS +--- a/include/linux/file.h ++++ b/include/linux/file.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + struct file; + +@@ -82,6 +83,8 @@ static inline void fdput_pos(struct fd f + fdput(f); + } + ++DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd) ++ + extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); + extern int replace_fd(unsigned fd, struct file *file, unsigned flags); + extern void set_close_on_exec(unsigned int fd, int flag); +@@ -90,6 +93,9 @@ extern int __get_unused_fd_flags(unsigne + extern int get_unused_fd_flags(unsigned flags); + extern void put_unused_fd(unsigned int fd); + ++DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T), ++ get_unused_fd_flags(flags), unsigned flags) ++ + extern void fd_install(unsigned int fd, struct file *file); + + extern int __receive_fd(struct file *file, int __user *ufd, +--- a/include/linux/irqflags.h ++++ b/include/linux/irqflags.h +@@ -13,6 +13,7 @@ + #define _LINUX_TRACE_IRQFLAGS_H + + #include ++#include + #include + #include + +@@ -260,4 +261,10 @@ extern void warn_bogus_irq_restore(void) + + #define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) + ++DEFINE_LOCK_GUARD_0(irq, local_irq_disable(), local_irq_enable()) ++DEFINE_LOCK_GUARD_0(irqsave, ++ local_irq_save(_T->flags), ++ local_irq_restore(_T->flags), ++ unsigned long flags) ++ + #endif +--- a/include/linux/mutex.h ++++ b/include/linux/mutex.h +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + struct device; + +@@ -246,4 +247,7 @@ extern void mutex_unlock(struct mutex *l + + extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock); + ++DEFINE_GUARD(mutex, struct mutex *, mutex_lock(_T), mutex_unlock(_T)) ++DEFINE_FREE(mutex, struct mutex *, if (_T) mutex_unlock(_T)) ++ + #endif /* __LINUX_MUTEX_H */ +--- a/include/linux/percpu.h ++++ b/include/linux/percpu.h +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + +@@ -134,6 +135,9 @@ extern void __init setup_per_cpu_areas(v + extern void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp); + extern void __percpu *__alloc_percpu(size_t size, size_t align); + extern void free_percpu(void __percpu *__pdata); ++ ++DEFINE_FREE(free_percpu, void __percpu *, free_percpu(_T)) ++ + extern phys_addr_t per_cpu_ptr_to_phys(void *addr); + + #define alloc_percpu_gfp(type, gfp) \ +--- a/include/linux/preempt.h ++++ b/include/linux/preempt.h +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include + + /* +@@ -431,4 +432,50 @@ static inline void migrate_enable(void) + + #endif /* CONFIG_SMP */ + ++/** ++ * preempt_disable_nested - Disable preemption inside a normally preempt disabled section ++ * ++ * Use for code which requires preemption protection inside a critical ++ * section which has preemption disabled implicitly on non-PREEMPT_RT ++ * enabled kernels, by e.g.: ++ * - holding a spinlock/rwlock ++ * - soft interrupt context ++ * - regular interrupt handlers ++ * ++ * On PREEMPT_RT enabled kernels spinlock/rwlock held sections, soft ++ * interrupt context and regular interrupt handlers are preemptible and ++ * only prevent migration. preempt_disable_nested() ensures that preemption ++ * is disabled for cases which require CPU local serialization even on ++ * PREEMPT_RT. For non-PREEMPT_RT kernels this is a NOP. ++ * ++ * The use cases are code sequences which are not serialized by a ++ * particular lock instance, e.g.: ++ * - seqcount write side critical sections where the seqcount is not ++ * associated to a particular lock and therefore the automatic ++ * protection mechanism does not work. This prevents a live lock ++ * against a preempting high priority reader. ++ * - RMW per CPU variable updates like vmstat. ++ */ ++/* Macro to avoid header recursion hell vs. lockdep */ ++#define preempt_disable_nested() \ ++do { \ ++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) \ ++ preempt_disable(); \ ++ else \ ++ lockdep_assert_preemption_disabled(); \ ++} while (0) ++ ++/** ++ * preempt_enable_nested - Undo the effect of preempt_disable_nested() ++ */ ++static __always_inline void preempt_enable_nested(void) ++{ ++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) ++ preempt_enable(); ++} ++ ++DEFINE_LOCK_GUARD_0(preempt, preempt_disable(), preempt_enable()) ++DEFINE_LOCK_GUARD_0(preempt_notrace, preempt_disable_notrace(), preempt_enable_notrace()) ++DEFINE_LOCK_GUARD_0(migrate, migrate_disable(), migrate_enable()) ++ + #endif /* __LINUX_PREEMPT_H */ +--- a/include/linux/rcupdate.h ++++ b/include/linux/rcupdate.h +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -1060,4 +1061,6 @@ rcu_head_after_call_rcu(struct rcu_head + extern int rcu_expedited; + extern int rcu_normal; + ++DEFINE_LOCK_GUARD_0(rcu, rcu_read_lock(), rcu_read_unlock()) ++ + #endif /* __LINUX_RCUPDATE_H */ +--- a/include/linux/rwsem.h ++++ b/include/linux/rwsem.h +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_DEBUG_LOCK_ALLOC + # define __RWSEM_DEP_MAP_INIT(lockname) \ +@@ -202,6 +203,13 @@ extern void up_read(struct rw_semaphore + */ + extern void up_write(struct rw_semaphore *sem); + ++DEFINE_GUARD(rwsem_read, struct rw_semaphore *, down_read(_T), up_read(_T)) ++DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T)) ++ ++DEFINE_FREE(up_read, struct rw_semaphore *, if (_T) up_read(_T)) ++DEFINE_FREE(up_write, struct rw_semaphore *, if (_T) up_write(_T)) ++ ++ + /* + * downgrade write lock to read lock + */ +--- a/include/linux/sched/task.h ++++ b/include/linux/sched/task.h +@@ -142,6 +142,8 @@ static inline void put_task_struct(struc + __put_task_struct(t); + } + ++DEFINE_FREE(put_task, struct task_struct *, if (_T) put_task_struct(_T)) ++ + static inline void put_task_struct_many(struct task_struct *t, int nr) + { + if (refcount_sub_and_test(nr, &t->usage)) +--- a/include/linux/slab.h ++++ b/include/linux/slab.h +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + + /* +@@ -186,6 +187,8 @@ void kfree(const void *objp); + void kfree_sensitive(const void *objp); + size_t __ksize(const void *objp); + ++DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) ++ + /** + * ksize - Report actual allocation size of associated object + * +--- a/include/linux/spinlock.h ++++ b/include/linux/spinlock.h +@@ -61,6 +61,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -506,4 +507,35 @@ int __alloc_bucket_spinlocks(spinlock_t + + void free_bucket_spinlocks(spinlock_t *locks); + ++DEFINE_LOCK_GUARD_1(raw_spinlock, raw_spinlock_t, ++ raw_spin_lock(_T->lock), ++ raw_spin_unlock(_T->lock)) ++ ++DEFINE_LOCK_GUARD_1(raw_spinlock_nested, raw_spinlock_t, ++ raw_spin_lock_nested(_T->lock, SINGLE_DEPTH_NESTING), ++ raw_spin_unlock(_T->lock)) ++ ++DEFINE_LOCK_GUARD_1(raw_spinlock_irq, raw_spinlock_t, ++ raw_spin_lock_irq(_T->lock), ++ raw_spin_unlock_irq(_T->lock)) ++ ++DEFINE_LOCK_GUARD_1(raw_spinlock_irqsave, raw_spinlock_t, ++ raw_spin_lock_irqsave(_T->lock, _T->flags), ++ raw_spin_unlock_irqrestore(_T->lock, _T->flags), ++ unsigned long flags) ++ ++DEFINE_LOCK_GUARD_1(spinlock, spinlock_t, ++ spin_lock(_T->lock), ++ spin_unlock(_T->lock)) ++ ++DEFINE_LOCK_GUARD_1(spinlock_irq, spinlock_t, ++ spin_lock_irq(_T->lock), ++ spin_unlock_irq(_T->lock)) ++ ++DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t, ++ spin_lock_irqsave(_T->lock, _T->flags), ++ spin_unlock_irqrestore(_T->lock, _T->flags), ++ unsigned long flags) ++ ++#undef __LINUX_INSIDE_SPINLOCK_H + #endif /* __LINUX_SPINLOCK_H */ +--- a/include/linux/srcu.h ++++ b/include/linux/srcu.h +@@ -211,4 +211,9 @@ static inline void smp_mb__after_srcu_re + /* __srcu_read_unlock has smp_mb() internally so nothing to do here. */ + } + ++DEFINE_LOCK_GUARD_1(srcu, struct srcu_struct, ++ _T->idx = srcu_read_lock(_T->lock), ++ srcu_read_unlock(_T->lock, _T->idx), ++ int idx) ++ + #endif +--- a/scripts/checkpatch.pl ++++ b/scripts/checkpatch.pl +@@ -4895,7 +4895,7 @@ sub process { + if|for|while|switch|return|case| + volatile|__volatile__| + __attribute__|format|__extension__| +- asm|__asm__)$/x) ++ asm|__asm__|scoped_guard)$/x) + { + # cpp #define statements have non-optional spaces, ie + # if there is a space between the name and the open diff --git a/queue-5.15/media-mc-clear-minor-number-before-put-device.patch b/queue-5.15/media-mc-clear-minor-number-before-put-device.patch new file mode 100644 index 0000000000..23c249ff1c --- /dev/null +++ b/queue-5.15/media-mc-clear-minor-number-before-put-device.patch @@ -0,0 +1,51 @@ +From stable+bounces-185528-greg=kroah.com@vger.kernel.org Tue Oct 14 00:21:52 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 18:21:45 -0400 +Subject: media: mc: Clear minor number before put device +To: stable@vger.kernel.org +Cc: Edward Adam Davis , syzbot+031d0cfd7c362817963f@syzkaller.appspotmail.com, Sakari Ailus , Hans Verkuil , Sasha Levin +Message-ID: <20251013222145.3663624-1-sashal@kernel.org> + +From: Edward Adam Davis + +[ Upstream commit 8cfc8cec1b4da88a47c243a11f384baefd092a50 ] + +The device minor should not be cleared after the device is released. + +Fixes: 9e14868dc952 ("media: mc: Clear minor number reservation at unregistration time") +Cc: stable@vger.kernel.org +Reported-by: syzbot+031d0cfd7c362817963f@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=031d0cfd7c362817963f +Tested-by: syzbot+031d0cfd7c362817963f@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +[ moved clear_bit from media_devnode_release callback to media_devnode_unregister before put_device ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/mc/mc-devnode.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/drivers/media/mc/mc-devnode.c ++++ b/drivers/media/mc/mc-devnode.c +@@ -50,11 +50,6 @@ static void media_devnode_release(struct + { + struct media_devnode *devnode = to_media_devnode(cd); + +- mutex_lock(&media_devnode_lock); +- /* Mark device node number as free */ +- clear_bit(devnode->minor, media_devnode_nums); +- mutex_unlock(&media_devnode_lock); +- + /* Release media_devnode and perform other cleanups as needed. */ + if (devnode->release) + devnode->release(devnode); +@@ -283,6 +278,7 @@ void media_devnode_unregister(struct med + /* Delete the cdev on this minor as well */ + cdev_device_del(&devnode->cdev, &devnode->dev); + devnode->media_dev = NULL; ++ clear_bit(devnode->minor, media_devnode_nums); + mutex_unlock(&media_devnode_lock); + + put_device(&devnode->dev); diff --git a/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-drop-unneeded-assignment-for-cache_type.patch b/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-drop-unneeded-assignment-for-cache_type.patch new file mode 100644 index 0000000000..433441ac82 --- /dev/null +++ b/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-drop-unneeded-assignment-for-cache_type.patch @@ -0,0 +1,39 @@ +From stable+bounces-185546-greg=kroah.com@vger.kernel.org Tue Oct 14 01:22:35 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 19:22:23 -0400 +Subject: mfd: intel_soc_pmic_chtdc_ti: Drop unneeded assignment for cache_type +To: stable@vger.kernel.org +Cc: Andy Shevchenko , Hans de Goede , Lee Jones , Sasha Levin +Message-ID: <20251013232224.3709547-2-sashal@kernel.org> + +From: Andy Shevchenko + +[ Upstream commit 9eb99c08508714906db078b5efbe075329a3fb06 ] + +REGCACHE_NONE is the default type of the cache when not provided. +Drop unneeded explicit assignment to it. + +Note, it's defined to 0, and if ever be redefined, it will break +literally a lot of the drivers, so it very unlikely to happen. + +Signed-off-by: Andy Shevchenko +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/20250129152823.1802273-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Lee Jones +Stable-dep-of: 64e0d839c589 ("mfd: intel_soc_pmic_chtdc_ti: Set use_single_read regmap_config flag") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mfd/intel_soc_pmic_chtdc_ti.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/mfd/intel_soc_pmic_chtdc_ti.c ++++ b/drivers/mfd/intel_soc_pmic_chtdc_ti.c +@@ -82,7 +82,6 @@ static const struct regmap_config chtdc_ + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, +- .cache_type = REGCACHE_NONE, + }; + + static const struct regmap_irq chtdc_ti_irqs[] = { diff --git a/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-fix-invalid-regmap-config-max_register-value.patch b/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-fix-invalid-regmap-config-max_register-value.patch new file mode 100644 index 0000000000..eb827d3e1d --- /dev/null +++ b/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-fix-invalid-regmap-config-max_register-value.patch @@ -0,0 +1,40 @@ +From stable+bounces-185545-greg=kroah.com@vger.kernel.org Tue Oct 14 01:22:42 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 19:22:22 -0400 +Subject: mfd: intel_soc_pmic_chtdc_ti: Fix invalid regmap-config max_register value +To: stable@vger.kernel.org +Cc: Hans de Goede , Andy Shevchenko , Lee Jones , Sasha Levin +Message-ID: <20251013232224.3709547-1-sashal@kernel.org> + +From: Hans de Goede + +[ Upstream commit 70e997e0107e5ed85c1a3ef2adfccbe351c29d71 ] + +The max_register = 128 setting in the regmap config is not valid. + +The Intel Dollar Cove TI PMIC has an eeprom unlock register at address 0x88 +and a number of EEPROM registers at 0xF?. Increase max_register to 0xff so +that these registers can be accessed. + +Signed-off-by: Hans de Goede +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241208150028.325349-1-hdegoede@redhat.com +Signed-off-by: Lee Jones +Stable-dep-of: 64e0d839c589 ("mfd: intel_soc_pmic_chtdc_ti: Set use_single_read regmap_config flag") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mfd/intel_soc_pmic_chtdc_ti.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mfd/intel_soc_pmic_chtdc_ti.c ++++ b/drivers/mfd/intel_soc_pmic_chtdc_ti.c +@@ -81,7 +81,7 @@ static struct mfd_cell chtdc_ti_dev[] = + static const struct regmap_config chtdc_ti_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +- .max_register = 128, ++ .max_register = 0xff, + .cache_type = REGCACHE_NONE, + }; + diff --git a/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-set-use_single_read-regmap_config-flag.patch b/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-set-use_single_read-regmap_config-flag.patch new file mode 100644 index 0000000000..f1ad513820 --- /dev/null +++ b/queue-5.15/mfd-intel_soc_pmic_chtdc_ti-set-use_single_read-regmap_config-flag.patch @@ -0,0 +1,43 @@ +From stable+bounces-185547-greg=kroah.com@vger.kernel.org Tue Oct 14 01:22:36 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 19:22:24 -0400 +Subject: mfd: intel_soc_pmic_chtdc_ti: Set use_single_read regmap_config flag +To: stable@vger.kernel.org +Cc: Hans de Goede , Andy Shevchenko , Lee Jones , Sasha Levin +Message-ID: <20251013232224.3709547-3-sashal@kernel.org> + +From: Hans de Goede + +[ Upstream commit 64e0d839c589f4f2ecd2e3e5bdb5cee6ba6bade9 ] + +Testing has shown that reading multiple registers at once (for 10-bit +ADC values) does not work. Set the use_single_read regmap_config flag +to make regmap split these for us. + +This should fix temperature opregion accesses done by +drivers/acpi/pmic/intel_pmic_chtdc_ti.c and is also necessary for +the upcoming drivers for the ADC and battery MFD cells. + +Fixes: 6bac0606fdba ("mfd: Add support for Cherry Trail Dollar Cove TI PMIC") +Cc: stable@vger.kernel.org +Reviewed-by: Andy Shevchenko +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20250804133240.312383-1-hansg@kernel.org +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mfd/intel_soc_pmic_chtdc_ti.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mfd/intel_soc_pmic_chtdc_ti.c ++++ b/drivers/mfd/intel_soc_pmic_chtdc_ti.c +@@ -82,6 +82,8 @@ static const struct regmap_config chtdc_ + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, ++ /* The hardware does not support reading multiple registers at once */ ++ .use_single_read = true, + }; + + static const struct regmap_irq chtdc_ti_irqs[] = { diff --git a/queue-5.15/minmax-avoid-overly-complicated-constant-expressions-in-vm-code.patch b/queue-5.15/minmax-avoid-overly-complicated-constant-expressions-in-vm-code.patch new file mode 100644 index 0000000000..5004a3d7ac --- /dev/null +++ b/queue-5.15/minmax-avoid-overly-complicated-constant-expressions-in-vm-code.patch @@ -0,0 +1,66 @@ +From linux-staging+bounces-34820-greg=kroah.com@lists.linux.dev Wed Oct 8 17:33:38 2025 +From: Eliav Farber +Date: Wed, 8 Oct 2025 15:29:30 +0000 +Subject: minmax: avoid overly complicated constant expressions in VM code +To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +Cc: Linus Torvalds , Lorenzo Stoakes , David Laight +Message-ID: <20251008152946.29285-6-farbere@amazon.com> + +From: Linus Torvalds + +[ Upstream commit 3a7e02c040b130b5545e4b115aada7bacd80a2b6 ] + +The minmax infrastructure is overkill for simple constants, and can +cause huge expansions because those simple constants are then used by +other things. + +For example, 'pageblock_order' is a core VM constant, but because it was +implemented using 'min_t()' and all the type-checking that involves, it +actually expanded to something like 2.5kB of preprocessor noise. + +And when that simple constant was then used inside other expansions: + + #define pageblock_nr_pages (1UL << pageblock_order) + #define pageblock_start_pfn(pfn) ALIGN_DOWN((pfn), pageblock_nr_pages) + +and we then use that inside a 'max()' macro: + + case ISOLATE_SUCCESS: + update_cached = false; + last_migrated_pfn = max(cc->zone->zone_start_pfn, + pageblock_start_pfn(cc->migrate_pfn - 1)); + +the end result was that one statement expanding to 253kB in size. + +There are probably other cases of this, but this one case certainly +stood out. + +I've added 'MIN_T()' and 'MAX_T()' macros for this kind of "core simple +constant with specific type" use. These macros skip the type checking, +and as such need to be very sparingly used only for obvious cases that +have active issues like this. + +Reported-by: Lorenzo Stoakes +Link: https://lore.kernel.org/all/36aa2cad-1db1-4abf-8dd2-fb20484aabc3@lucifer.local/ +Cc: David Laight +Signed-off-by: Linus Torvalds +Signed-off-by: Eliav Farber +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/minmax.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/include/linux/minmax.h ++++ b/include/linux/minmax.h +@@ -270,4 +270,11 @@ static inline bool in_range32(u32 val, u + #define swap(a, b) \ + do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) + ++/* ++ * Use these carefully: no type checking, and uses the arguments ++ * multiple times. Use for obvious constants only. ++ */ ++#define MIN_T(type,a,b) __cmp(min,(type)(a),(type)(b)) ++#define MAX_T(type,a,b) __cmp(max,(type)(a),(type)(b)) ++ + #endif /* _LINUX_MINMAX_H */ diff --git a/queue-5.15/minmax-deduplicate-__unconst_integer_typeof.patch b/queue-5.15/minmax-deduplicate-__unconst_integer_typeof.patch new file mode 100644 index 0000000000..3b17f8c554 --- /dev/null +++ b/queue-5.15/minmax-deduplicate-__unconst_integer_typeof.patch @@ -0,0 +1,71 @@ +From stable+bounces-183615-greg=kroah.com@vger.kernel.org Wed Oct 8 17:32:08 2025 +From: Eliav Farber +Date: Wed, 8 Oct 2025 15:29:28 +0000 +Subject: minmax: deduplicate __unconst_integer_typeof() +To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +Message-ID: <20251008152946.29285-4-farbere@amazon.com> + +From: Andy Shevchenko + +[ Upstream commit 5e57418a2031cd5e1863efdf3d7447a16a368172 ] + +It appears that compiler_types.h already have an implementation of the +__unconst_integer_typeof() called __unqual_scalar_typeof(). Use it +instead of the copy. + +Link: https://lkml.kernel.org/r/20230911154913.4176033-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Andy Shevchenko +Acked-by: Herve Codina +Signed-off-by: Andrew Morton +Signed-off-by: Eliav Farber +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/minmax.h | 25 ++----------------------- + 1 file changed, 2 insertions(+), 23 deletions(-) + +--- a/include/linux/minmax.h ++++ b/include/linux/minmax.h +@@ -169,27 +169,6 @@ + #define max_t(type, x, y) __careful_cmp(max, (type)(x), (type)(y)) + + /* +- * Remove a const qualifier from integer types +- * _Generic(foo, type-name: association, ..., default: association) performs a +- * comparison against the foo type (not the qualified type). +- * Do not use the const keyword in the type-name as it will not match the +- * unqualified type of foo. +- */ +-#define __unconst_integer_type_cases(type) \ +- unsigned type: (unsigned type)0, \ +- signed type: (signed type)0 +- +-#define __unconst_integer_typeof(x) typeof( \ +- _Generic((x), \ +- char: (char)0, \ +- __unconst_integer_type_cases(char), \ +- __unconst_integer_type_cases(short), \ +- __unconst_integer_type_cases(int), \ +- __unconst_integer_type_cases(long), \ +- __unconst_integer_type_cases(long long), \ +- default: (x))) +- +-/* + * Do not check the array parameter using __must_be_array(). + * In the following legit use-case where the "array" passed is a simple pointer, + * __must_be_array() will return a failure. +@@ -203,13 +182,13 @@ + * 'int *buff' and 'int buff[N]' types. + * + * The array can be an array of const items. +- * typeof() keeps the const qualifier. Use __unconst_integer_typeof() in order ++ * typeof() keeps the const qualifier. Use __unqual_scalar_typeof() in order + * to discard the const qualifier for the __element variable. + */ + #define __minmax_array(op, array, len) ({ \ + typeof(&(array)[0]) __array = (array); \ + typeof(len) __len = (len); \ +- __unconst_integer_typeof(__array[0]) __element = __array[--__len]; \ ++ __unqual_scalar_typeof(__array[0]) __element = __array[--__len];\ + while (__len--) \ + __element = op(__element, __array[__len]); \ + __element; }) diff --git a/queue-5.15/minmax-fix-indentation-of-__cmp_once-and-__clamp_once.patch b/queue-5.15/minmax-fix-indentation-of-__cmp_once-and-__clamp_once.patch new file mode 100644 index 0000000000..9b0994a437 --- /dev/null +++ b/queue-5.15/minmax-fix-indentation-of-__cmp_once-and-__clamp_once.patch @@ -0,0 +1,74 @@ +From stable+bounces-183616-greg=kroah.com@vger.kernel.org Wed Oct 8 17:33:08 2025 +From: Eliav Farber +Date: Wed, 8 Oct 2025 15:29:29 +0000 +Subject: minmax: fix indentation of __cmp_once() and __clamp_once() +To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +Cc: Christoph Hellwig , "Jason A. Donenfeld" , Linus Torvalds +Message-ID: <20251008152946.29285-5-farbere@amazon.com> + +From: David Laight + +[ Upstream commit f4b84b2ff851f01d0fac619eadef47eb41648534 ] + +Remove the extra indentation and align continuation markers. + +Link: https://lkml.kernel.org/r/bed41317a05c498ea0209eafbcab45a5@AcuMS.aculab.com +Signed-off-by: David Laight +Cc: Andy Shevchenko +Cc: Christoph Hellwig +Cc: Jason A. Donenfeld +Cc: Linus Torvalds +Cc: Matthew Wilcox (Oracle) +Signed-off-by: Andrew Morton +Signed-off-by: Eliav Farber +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/minmax.h | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +--- a/include/linux/minmax.h ++++ b/include/linux/minmax.h +@@ -46,11 +46,11 @@ + #define __cmp(op, x, y) ((x) __cmp_op_##op (y) ? (x) : (y)) + + #define __cmp_once(op, x, y, unique_x, unique_y) ({ \ +- typeof(x) unique_x = (x); \ +- typeof(y) unique_y = (y); \ +- static_assert(__types_ok(x, y), \ +- #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ +- __cmp(op, unique_x, unique_y); }) ++ typeof(x) unique_x = (x); \ ++ typeof(y) unique_y = (y); \ ++ static_assert(__types_ok(x, y), \ ++ #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ ++ __cmp(op, unique_x, unique_y); }) + + #define __careful_cmp(op, x, y) \ + __builtin_choose_expr(__is_constexpr((x) - (y)), \ +@@ -60,16 +60,16 @@ + #define __clamp(val, lo, hi) \ + ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) + +-#define __clamp_once(val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ +- typeof(val) unique_val = (val); \ +- typeof(lo) unique_lo = (lo); \ +- typeof(hi) unique_hi = (hi); \ +- static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ +- (lo) <= (hi), true), \ +- "clamp() low limit " #lo " greater than high limit " #hi); \ +- static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ +- static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ +- __clamp(unique_val, unique_lo, unique_hi); }) ++#define __clamp_once(val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ ++ typeof(val) unique_val = (val); \ ++ typeof(lo) unique_lo = (lo); \ ++ typeof(hi) unique_hi = (hi); \ ++ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ ++ (lo) <= (hi), true), \ ++ "clamp() low limit " #lo " greater than high limit " #hi); \ ++ static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ ++ static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ ++ __clamp(unique_val, unique_lo, unique_hi); }) + + #define __careful_clamp(val, lo, hi) ({ \ + __builtin_choose_expr(__is_constexpr((val) - (lo) + (hi)), \ diff --git a/queue-5.15/minmax-introduce-min-max-_array.patch b/queue-5.15/minmax-introduce-min-max-_array.patch new file mode 100644 index 0000000000..764efb5dff --- /dev/null +++ b/queue-5.15/minmax-introduce-min-max-_array.patch @@ -0,0 +1,99 @@ +From stable+bounces-183614-greg=kroah.com@vger.kernel.org Wed Oct 8 17:31:31 2025 +From: Eliav Farber +Date: Wed, 8 Oct 2025 15:29:27 +0000 +Subject: minmax: Introduce {min,max}_array() +To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +Cc: Andy Shevchenko , Christophe Leroy +Message-ID: <20251008152946.29285-3-farbere@amazon.com> + +From: Herve Codina + +[ Upstream commit c952c748c7a983a8bda9112984e6f2c1f6e441a5 ] + +Introduce min_array() (resp max_array()) in order to get the +minimal (resp maximum) of values present in an array. + +Signed-off-by: Herve Codina +Reviewed-by: Andy Shevchenko +Reviewed-by: Christophe Leroy +Link: https://lore.kernel.org/r/20230623085830.749991-8-herve.codina@bootlin.com +Signed-off-by: Mark Brown +Signed-off-by: Eliav Farber +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/minmax.h | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +--- a/include/linux/minmax.h ++++ b/include/linux/minmax.h +@@ -168,6 +168,70 @@ + */ + #define max_t(type, x, y) __careful_cmp(max, (type)(x), (type)(y)) + ++/* ++ * Remove a const qualifier from integer types ++ * _Generic(foo, type-name: association, ..., default: association) performs a ++ * comparison against the foo type (not the qualified type). ++ * Do not use the const keyword in the type-name as it will not match the ++ * unqualified type of foo. ++ */ ++#define __unconst_integer_type_cases(type) \ ++ unsigned type: (unsigned type)0, \ ++ signed type: (signed type)0 ++ ++#define __unconst_integer_typeof(x) typeof( \ ++ _Generic((x), \ ++ char: (char)0, \ ++ __unconst_integer_type_cases(char), \ ++ __unconst_integer_type_cases(short), \ ++ __unconst_integer_type_cases(int), \ ++ __unconst_integer_type_cases(long), \ ++ __unconst_integer_type_cases(long long), \ ++ default: (x))) ++ ++/* ++ * Do not check the array parameter using __must_be_array(). ++ * In the following legit use-case where the "array" passed is a simple pointer, ++ * __must_be_array() will return a failure. ++ * --- 8< --- ++ * int *buff ++ * ... ++ * min = min_array(buff, nb_items); ++ * --- 8< --- ++ * ++ * The first typeof(&(array)[0]) is needed in order to support arrays of both ++ * 'int *buff' and 'int buff[N]' types. ++ * ++ * The array can be an array of const items. ++ * typeof() keeps the const qualifier. Use __unconst_integer_typeof() in order ++ * to discard the const qualifier for the __element variable. ++ */ ++#define __minmax_array(op, array, len) ({ \ ++ typeof(&(array)[0]) __array = (array); \ ++ typeof(len) __len = (len); \ ++ __unconst_integer_typeof(__array[0]) __element = __array[--__len]; \ ++ while (__len--) \ ++ __element = op(__element, __array[__len]); \ ++ __element; }) ++ ++/** ++ * min_array - return minimum of values present in an array ++ * @array: array ++ * @len: array length ++ * ++ * Note that @len must not be zero (empty array). ++ */ ++#define min_array(array, len) __minmax_array(min, array, len) ++ ++/** ++ * max_array - return maximum of values present in an array ++ * @array: array ++ * @len: array length ++ * ++ * Note that @len must not be zero (empty array). ++ */ ++#define max_array(array, len) __minmax_array(max, array, len) ++ + /** + * clamp_t - return a value clamped to a given range using a given type + * @type: the type of variable to use diff --git a/queue-5.15/net-usb-asix-hold-pm-usage-ref-to-avoid-pm-mdio-rtnl-deadlock.patch b/queue-5.15/net-usb-asix-hold-pm-usage-ref-to-avoid-pm-mdio-rtnl-deadlock.patch new file mode 100644 index 0000000000..3606767f7d --- /dev/null +++ b/queue-5.15/net-usb-asix-hold-pm-usage-ref-to-avoid-pm-mdio-rtnl-deadlock.patch @@ -0,0 +1,117 @@ +From stable+bounces-185702-greg=kroah.com@vger.kernel.org Tue Oct 14 18:56:23 2025 +From: Sasha Levin +Date: Tue, 14 Oct 2025 12:56:14 -0400 +Subject: net: usb: asix: hold PM usage ref to avoid PM/MDIO + RTNL deadlock +To: stable@vger.kernel.org +Cc: "Oleksij Rempel" , "Hubert Wiśniewski" , "Marek Szyprowski" , "Paolo Abeni" , "Sasha Levin" +Message-ID: <20251014165614.192458-1-sashal@kernel.org> + +From: Oleksij Rempel + +[ Upstream commit 3d3c4cd5c62f24bb3cb4511b7a95df707635e00a ] + +Prevent USB runtime PM (autosuspend) for AX88772* in bind. + +usbnet enables runtime PM (autosuspend) by default, so disabling it via +the usb_driver flag is ineffective. On AX88772B, autosuspend shows no +measurable power saving with current driver (no link partner, admin +up/down). The ~0.453 W -> ~0.248 W drop on v6.1 comes from phylib powering +the PHY off on admin-down, not from USB autosuspend. + +The real hazard is that with runtime PM enabled, ndo_open() (under RTNL) +may synchronously trigger autoresume (usb_autopm_get_interface()) into +asix_resume() while the USB PM lock is held. Resume paths then invoke +phylink/phylib and MDIO, which also expect RTNL, leading to possible +deadlocks or PM lock vs MDIO wake issues. + +To avoid this, keep the device runtime-PM active by taking a usage +reference in ax88772_bind() and dropping it in unbind(). A non-zero PM +usage count blocks runtime suspend regardless of userspace policy +(.../power/control - pm_runtime_allow/forbid), making this approach +robust against sysfs overrides. + +Holding a runtime-PM usage ref does not affect system-wide suspend; +system sleep/resume callbacks continue to run as before. + +Fixes: 4a2c7217cd5a ("net: usb: asix: ax88772: manage PHY PM from MAC") +Reported-by: Hubert Wiśniewski +Closes: https://lore.kernel.org/all/DCGHG5UJT9G3.2K1GHFZ3H87T0@gmail.com +Tested-by: Hubert Wiśniewski +Reported-by: Marek Szyprowski +Closes: https://lore.kernel.org/all/b5ea8296-f981-445d-a09a-2f389d7f6fdd@samsung.com +Cc: stable@vger.kernel.org +Signed-off-by: Oleksij Rempel +Link: https://patch.msgid.link/20251005081203.3067982-1-o.rempel@pengutronix.de +Signed-off-by: Paolo Abeni +[ adapted to phylib-only ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/asix_devices.c | 35 ++++++++++++++++++++++++++++++++++- + 1 file changed, 34 insertions(+), 1 deletion(-) + +--- a/drivers/net/usb/asix_devices.c ++++ b/drivers/net/usb/asix_devices.c +@@ -608,6 +608,21 @@ static void ax88772_suspend(struct usbne + asix_read_medium_status(dev, 1)); + } + ++/* Notes on PM callbacks and locking context: ++ * ++ * - asix_suspend()/asix_resume() are invoked for both runtime PM and ++ * system-wide suspend/resume. For struct usb_driver the ->resume() ++ * callback does not receive pm_message_t, so the resume type cannot ++ * be distinguished here. ++ * ++ * - The MAC driver must hold RTNL when calling phylink interfaces such as ++ * phylink_suspend()/resume(). Those calls will also perform MDIO I/O. ++ * ++ * - Taking RTNL and doing MDIO from a runtime-PM resume callback (while ++ * the USB PM lock is held) is fragile. Since autosuspend brings no ++ * measurable power saving here, we block it by holding a PM usage ++ * reference in ax88772_bind(). ++ */ + static int asix_suspend(struct usb_interface *intf, pm_message_t message) + { + struct usbnet *dev = usb_get_intfdata(intf); +@@ -809,7 +824,18 @@ static int ax88772_bind(struct usbnet *d + if (ret) + return ret; + +- return ax88772_init_phy(dev); ++ ret = ax88772_init_phy(dev); ++ if (ret) ++ return ret; ++ ++ /* Keep this interface runtime-PM active by taking a usage ref. ++ * Prevents runtime suspend while bound and avoids resume paths ++ * that could deadlock (autoresume under RTNL while USB PM lock ++ * is held, phylink/MDIO wants RTNL). ++ */ ++ pm_runtime_get_noresume(&intf->dev); ++ ++ return 0; + } + + static int ax88772_stop(struct usbnet *dev) +@@ -827,6 +853,8 @@ static void ax88772_unbind(struct usbnet + + phy_disconnect(priv->phydev); + asix_rx_fixup_common_free(dev->driver_priv); ++ /* Drop the PM usage ref taken in bind() */ ++ pm_runtime_put(&intf->dev); + } + + static void ax88178_unbind(struct usbnet *dev, struct usb_interface *intf) +@@ -1452,6 +1480,11 @@ static struct usb_driver asix_driver = { + .resume = asix_resume, + .reset_resume = asix_resume, + .disconnect = usbnet_disconnect, ++ /* usbnet enables autosuspend by default (supports_autosuspend=1). ++ * We keep runtime-PM active for AX88772* by taking a PM usage ++ * reference in ax88772_bind() (pm_runtime_get_noresume()) and ++ * dropping it in unbind(), which effectively blocks autosuspend. ++ */ + .supports_autosuspend = 1, + .disable_hub_initiated_lpm = 1, + }; diff --git a/queue-5.15/series b/queue-5.15/series index 2efb16af08..0e0d600b62 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -223,3 +223,24 @@ ext4-correctly-handle-queries-for-metadata-mappings.patch ext4-guard-against-ea-inode-refcount-underflow-in-xattr-update.patch ext4-free-orphan-info-with-kvfree.patch lib-crypto-curve25519-hacl64-disable-kasan-with-clang-17-and-older.patch +kvm-x86-don-t-re-check-l1-intercepts-when-completing-userspace-i-o.patch +asoc-codecs-wcd934x-simplify-with-dev_err_probe.patch +asoc-wcd934x-fix-error-handling-in-wcd934x_codec_parse_data.patch +squashfs-add-additional-inode-sanity-checking.patch +squashfs-reject-negative-file-sizes-in-squashfs_read_inode.patch +media-mc-clear-minor-number-before-put-device.patch +mfd-intel_soc_pmic_chtdc_ti-fix-invalid-regmap-config-max_register-value.patch +mfd-intel_soc_pmic_chtdc_ti-drop-unneeded-assignment-for-cache_type.patch +mfd-intel_soc_pmic_chtdc_ti-set-use_single_read-regmap_config-flag.patch +net-usb-asix-hold-pm-usage-ref-to-avoid-pm-mdio-rtnl-deadlock.patch +ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch +tracing-fix-race-condition-in-kprobe-initialization-causing-null-pointer-dereference.patch +dm-fix-null-pointer-dereference-in-__dm_suspend.patch +locking-introduce-__cleanup-based-infrastructure.patch +fscontext-do-not-consume-log-entries-when-returning-emsgsize.patch +btrfs-fix-the-incorrect-max_bytes-value-for-find_lock_delalloc_range.patch +arm64-dts-qcom-sdm845-fix-slimbam-num-channels-ees.patch +minmax-introduce-min-max-_array.patch +minmax-deduplicate-__unconst_integer_typeof.patch +minmax-fix-indentation-of-__cmp_once-and-__clamp_once.patch +minmax-avoid-overly-complicated-constant-expressions-in-vm-code.patch diff --git a/queue-5.15/squashfs-add-additional-inode-sanity-checking.patch b/queue-5.15/squashfs-add-additional-inode-sanity-checking.patch new file mode 100644 index 0000000000..20640856ae --- /dev/null +++ b/queue-5.15/squashfs-add-additional-inode-sanity-checking.patch @@ -0,0 +1,90 @@ +From stable+bounces-185520-greg=kroah.com@vger.kernel.org Mon Oct 13 23:45:11 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 17:45:03 -0400 +Subject: Squashfs: add additional inode sanity checking +To: stable@vger.kernel.org +Cc: Phillip Lougher , Andrew Morton , Sasha Levin +Message-ID: <20251013214504.3637196-1-sashal@kernel.org> + +From: Phillip Lougher + +[ Upstream commit 9ee94bfbe930a1b39df53fa2d7b31141b780eb5a ] + +Patch series "Squashfs: performance improvement and a sanity check". + +This patchset adds an additional sanity check when reading regular file +inodes, and adds support for SEEK_DATA/SEEK_HOLE lseek() whence values. + +This patch (of 2): + +Add an additional sanity check when reading regular file inodes. + +A regular file if the file size is an exact multiple of the filesystem +block size cannot have a fragment. This is because by definition a +fragment block stores tailends which are not a whole block in size. + +Link: https://lkml.kernel.org/r/20250923220652.568416-1-phillip@squashfs.org.uk +Link: https://lkml.kernel.org/r/20250923220652.568416-2-phillip@squashfs.org.uk +Signed-off-by: Phillip Lougher +Signed-off-by: Andrew Morton +Stable-dep-of: 9f1c14c1de1b ("Squashfs: reject negative file sizes in squashfs_read_inode()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/squashfs/inode.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +--- a/fs/squashfs/inode.c ++++ b/fs/squashfs/inode.c +@@ -140,8 +140,17 @@ int squashfs_read_inode(struct inode *in + if (err < 0) + goto failed_read; + ++ inode->i_size = le32_to_cpu(sqsh_ino->file_size); + frag = le32_to_cpu(sqsh_ino->fragment); + if (frag != SQUASHFS_INVALID_FRAG) { ++ /* ++ * the file cannot have a fragment (tailend) and have a ++ * file size a multiple of the block size ++ */ ++ if ((inode->i_size & (msblk->block_size - 1)) == 0) { ++ err = -EINVAL; ++ goto failed_read; ++ } + frag_offset = le32_to_cpu(sqsh_ino->offset); + frag_size = squashfs_frag_lookup(sb, frag, &frag_blk); + if (frag_size < 0) { +@@ -155,7 +164,6 @@ int squashfs_read_inode(struct inode *in + } + + set_nlink(inode, 1); +- inode->i_size = le32_to_cpu(sqsh_ino->file_size); + inode->i_fop = &generic_ro_fops; + inode->i_mode |= S_IFREG; + inode->i_blocks = ((inode->i_size - 1) >> 9) + 1; +@@ -184,8 +192,17 @@ int squashfs_read_inode(struct inode *in + if (err < 0) + goto failed_read; + ++ inode->i_size = le64_to_cpu(sqsh_ino->file_size); + frag = le32_to_cpu(sqsh_ino->fragment); + if (frag != SQUASHFS_INVALID_FRAG) { ++ /* ++ * the file cannot have a fragment (tailend) and have a ++ * file size a multiple of the block size ++ */ ++ if ((inode->i_size & (msblk->block_size - 1)) == 0) { ++ err = -EINVAL; ++ goto failed_read; ++ } + frag_offset = le32_to_cpu(sqsh_ino->offset); + frag_size = squashfs_frag_lookup(sb, frag, &frag_blk); + if (frag_size < 0) { +@@ -200,7 +217,6 @@ int squashfs_read_inode(struct inode *in + + xattr_id = le32_to_cpu(sqsh_ino->xattr); + set_nlink(inode, le32_to_cpu(sqsh_ino->nlink)); +- inode->i_size = le64_to_cpu(sqsh_ino->file_size); + inode->i_op = &squashfs_inode_ops; + inode->i_fop = &generic_ro_fops; + inode->i_mode |= S_IFREG; diff --git a/queue-5.15/squashfs-reject-negative-file-sizes-in-squashfs_read_inode.patch b/queue-5.15/squashfs-reject-negative-file-sizes-in-squashfs_read_inode.patch new file mode 100644 index 0000000000..f243fc0d49 --- /dev/null +++ b/queue-5.15/squashfs-reject-negative-file-sizes-in-squashfs_read_inode.patch @@ -0,0 +1,48 @@ +From stable+bounces-185521-greg=kroah.com@vger.kernel.org Mon Oct 13 23:45:15 2025 +From: Sasha Levin +Date: Mon, 13 Oct 2025 17:45:04 -0400 +Subject: Squashfs: reject negative file sizes in squashfs_read_inode() +To: stable@vger.kernel.org +Cc: Phillip Lougher , syzbot+f754e01116421e9754b9@syzkaller.appspotmail.com, Amir Goldstein , Andrew Morton , Sasha Levin +Message-ID: <20251013214504.3637196-2-sashal@kernel.org> + +From: Phillip Lougher + +[ Upstream commit 9f1c14c1de1bdde395f6cc893efa4f80a2ae3b2b ] + +Syskaller reports a "WARNING in ovl_copy_up_file" in overlayfs. + +This warning is ultimately caused because the underlying Squashfs file +system returns a file with a negative file size. + +This commit checks for a negative file size and returns EINVAL. + +[phillip@squashfs.org.uk: only need to check 64 bit quantity] + Link: https://lkml.kernel.org/r/20250926222305.110103-1-phillip@squashfs.org.uk +Link: https://lkml.kernel.org/r/20250926215935.107233-1-phillip@squashfs.org.uk +Fixes: 6545b246a2c8 ("Squashfs: inode operations") +Signed-off-by: Phillip Lougher +Reported-by: syzbot+f754e01116421e9754b9@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/68d580e5.a00a0220.303701.0019.GAE@google.com/ +Cc: Amir Goldstein +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/squashfs/inode.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/squashfs/inode.c ++++ b/fs/squashfs/inode.c +@@ -193,6 +193,10 @@ int squashfs_read_inode(struct inode *in + goto failed_read; + + inode->i_size = le64_to_cpu(sqsh_ino->file_size); ++ if (inode->i_size < 0) { ++ err = -EINVAL; ++ goto failed_read; ++ } + frag = le32_to_cpu(sqsh_ino->fragment); + if (frag != SQUASHFS_INVALID_FRAG) { + /* diff --git a/queue-5.15/tracing-fix-race-condition-in-kprobe-initialization-causing-null-pointer-dereference.patch b/queue-5.15/tracing-fix-race-condition-in-kprobe-initialization-causing-null-pointer-dereference.patch new file mode 100644 index 0000000000..19999de46b --- /dev/null +++ b/queue-5.15/tracing-fix-race-condition-in-kprobe-initialization-causing-null-pointer-dereference.patch @@ -0,0 +1,239 @@ +From stable+bounces-185638-greg=kroah.com@vger.kernel.org Tue Oct 14 13:37:23 2025 +From: Sasha Levin +Date: Tue, 14 Oct 2025 07:37:14 -0400 +Subject: tracing: Fix race condition in kprobe initialization causing NULL pointer dereference +To: stable@vger.kernel.org +Cc: Yuan Chen , "Masami Hiramatsu (Google)" , Sasha Levin +Message-ID: <20251014113714.4153034-1-sashal@kernel.org> + +From: Yuan Chen + +[ Upstream commit 9cf9aa7b0acfde7545c1a1d912576e9bab28dc6f ] + +There is a critical race condition in kprobe initialization that can lead to +NULL pointer dereference and kernel crash. + +[1135630.084782] Unable to handle kernel paging request at virtual address 0000710a04630000 +... +[1135630.260314] pstate: 404003c9 (nZcv DAIF +PAN -UAO) +[1135630.269239] pc : kprobe_perf_func+0x30/0x260 +[1135630.277643] lr : kprobe_dispatcher+0x44/0x60 +[1135630.286041] sp : ffffaeff4977fa40 +[1135630.293441] x29: ffffaeff4977fa40 x28: ffffaf015340e400 +[1135630.302837] x27: 0000000000000000 x26: 0000000000000000 +[1135630.312257] x25: ffffaf029ed108a8 x24: ffffaf015340e528 +[1135630.321705] x23: ffffaeff4977fc50 x22: ffffaeff4977fc50 +[1135630.331154] x21: 0000000000000000 x20: ffffaeff4977fc50 +[1135630.340586] x19: ffffaf015340e400 x18: 0000000000000000 +[1135630.349985] x17: 0000000000000000 x16: 0000000000000000 +[1135630.359285] x15: 0000000000000000 x14: 0000000000000000 +[1135630.368445] x13: 0000000000000000 x12: 0000000000000000 +[1135630.377473] x11: 0000000000000000 x10: 0000000000000000 +[1135630.386411] x9 : 0000000000000000 x8 : 0000000000000000 +[1135630.395252] x7 : 0000000000000000 x6 : 0000000000000000 +[1135630.403963] x5 : 0000000000000000 x4 : 0000000000000000 +[1135630.412545] x3 : 0000710a04630000 x2 : 0000000000000006 +[1135630.421021] x1 : ffffaeff4977fc50 x0 : 0000710a04630000 +[1135630.429410] Call trace: +[1135630.434828] kprobe_perf_func+0x30/0x260 +[1135630.441661] kprobe_dispatcher+0x44/0x60 +[1135630.448396] aggr_pre_handler+0x70/0xc8 +[1135630.454959] kprobe_breakpoint_handler+0x140/0x1e0 +[1135630.462435] brk_handler+0xbc/0xd8 +[1135630.468437] do_debug_exception+0x84/0x138 +[1135630.475074] el1_dbg+0x18/0x8c +[1135630.480582] security_file_permission+0x0/0xd0 +[1135630.487426] vfs_write+0x70/0x1c0 +[1135630.493059] ksys_write+0x5c/0xc8 +[1135630.498638] __arm64_sys_write+0x24/0x30 +[1135630.504821] el0_svc_common+0x78/0x130 +[1135630.510838] el0_svc_handler+0x38/0x78 +[1135630.516834] el0_svc+0x8/0x1b0 + +kernel/trace/trace_kprobe.c: 1308 +0xffff3df8995039ec : ldr x21, [x24,#120] +include/linux/compiler.h: 294 +0xffff3df8995039f0 : ldr x1, [x21,x0] + +kernel/trace/trace_kprobe.c +1308: head = this_cpu_ptr(call->perf_events); +1309: if (hlist_empty(head)) +1310: return 0; + +crash> struct trace_event_call -o +struct trace_event_call { + ... + [120] struct hlist_head *perf_events; //(call->perf_event) + ... +} + +crash> struct trace_event_call ffffaf015340e528 +struct trace_event_call { + ... + perf_events = 0xffff0ad5fa89f088, //this value is correct, but x21 = 0 + ... +} + +Race Condition Analysis: + +The race occurs between kprobe activation and perf_events initialization: + + CPU0 CPU1 + ==== ==== + perf_kprobe_init + perf_trace_event_init + tp_event->perf_events = list;(1) + tp_event->class->reg (2)← KPROBE ACTIVE + Debug exception triggers + ... + kprobe_dispatcher + kprobe_perf_func (tk->tp.flags & TP_FLAG_PROFILE) + head = this_cpu_ptr(call->perf_events)(3) + (perf_events is still NULL) + +Problem: +1. CPU0 executes (1) assigning tp_event->perf_events = list +2. CPU0 executes (2) enabling kprobe functionality via class->reg() +3. CPU1 triggers and reaches kprobe_dispatcher +4. CPU1 checks TP_FLAG_PROFILE - condition passes (step 2 completed) +5. CPU1 calls kprobe_perf_func() and crashes at (3) because + call->perf_events is still NULL + +CPU1 sees that kprobe functionality is enabled but does not see that +perf_events has been assigned. + +Add pairing read and write memory barriers to guarantee that if CPU1 +sees that kprobe functionality is enabled, it must also see that +perf_events has been assigned. + +Link: https://lore.kernel.org/all/20251001022025.44626-1-chenyuan_fl@163.com/ + +Fixes: 50d780560785 ("tracing/kprobes: Add probe handler dispatcher to support perf and ftrace concurrent use") +Cc: stable@vger.kernel.org +Signed-off-by: Yuan Chen +Signed-off-by: Masami Hiramatsu (Google) +[ Drop fprobe changes + context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_kprobe.c | 11 +++++++---- + kernel/trace/trace_probe.h | 9 +++++++-- + kernel/trace/trace_uprobe.c | 12 ++++++++---- + 3 files changed, 22 insertions(+), 10 deletions(-) + +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -1722,14 +1722,15 @@ static int kprobe_register(struct trace_ + static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) + { + struct trace_kprobe *tk = container_of(kp, struct trace_kprobe, rp.kp); ++ unsigned int flags = trace_probe_load_flag(&tk->tp); + int ret = 0; + + raw_cpu_inc(*tk->nhit); + +- if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE)) ++ if (flags & TP_FLAG_TRACE) + kprobe_trace_func(tk, regs); + #ifdef CONFIG_PERF_EVENTS +- if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE)) ++ if (flags & TP_FLAG_PROFILE) + ret = kprobe_perf_func(tk, regs); + #endif + return ret; +@@ -1741,6 +1742,7 @@ kretprobe_dispatcher(struct kretprobe_in + { + struct kretprobe *rp = get_kretprobe(ri); + struct trace_kprobe *tk; ++ unsigned int flags; + + /* + * There is a small chance that get_kretprobe(ri) returns NULL when +@@ -1753,10 +1755,11 @@ kretprobe_dispatcher(struct kretprobe_in + tk = container_of(rp, struct trace_kprobe, rp); + raw_cpu_inc(*tk->nhit); + +- if (trace_probe_test_flag(&tk->tp, TP_FLAG_TRACE)) ++ flags = trace_probe_load_flag(&tk->tp); ++ if (flags & TP_FLAG_TRACE) + kretprobe_trace_func(tk, ri, regs); + #ifdef CONFIG_PERF_EVENTS +- if (trace_probe_test_flag(&tk->tp, TP_FLAG_PROFILE)) ++ if (flags & TP_FLAG_PROFILE) + kretprobe_perf_func(tk, ri, regs); + #endif + return 0; /* We don't tweak kernel, so just return 0 */ +--- a/kernel/trace/trace_probe.h ++++ b/kernel/trace/trace_probe.h +@@ -258,16 +258,21 @@ struct event_file_link { + struct list_head list; + }; + ++static inline unsigned int trace_probe_load_flag(struct trace_probe *tp) ++{ ++ return smp_load_acquire(&tp->event->flags); ++} ++ + static inline bool trace_probe_test_flag(struct trace_probe *tp, + unsigned int flag) + { +- return !!(tp->event->flags & flag); ++ return !!(trace_probe_load_flag(tp) & flag); + } + + static inline void trace_probe_set_flag(struct trace_probe *tp, + unsigned int flag) + { +- tp->event->flags |= flag; ++ smp_store_release(&tp->event->flags, tp->event->flags | flag); + } + + static inline void trace_probe_clear_flag(struct trace_probe *tp, +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -1485,6 +1485,7 @@ static int uprobe_dispatcher(struct upro + struct uprobe_dispatch_data udd; + struct uprobe_cpu_buffer *ucb; + int dsize, esize; ++ unsigned int flags; + int ret = 0; + + +@@ -1505,11 +1506,12 @@ static int uprobe_dispatcher(struct upro + ucb = uprobe_buffer_get(); + store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize); + +- if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE)) ++ flags = trace_probe_load_flag(&tu->tp); ++ if (flags & TP_FLAG_TRACE) + ret |= uprobe_trace_func(tu, regs, ucb, dsize); + + #ifdef CONFIG_PERF_EVENTS +- if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE)) ++ if (flags & TP_FLAG_PROFILE) + ret |= uprobe_perf_func(tu, regs, ucb, dsize); + #endif + uprobe_buffer_put(ucb); +@@ -1523,6 +1525,7 @@ static int uretprobe_dispatcher(struct u + struct uprobe_dispatch_data udd; + struct uprobe_cpu_buffer *ucb; + int dsize, esize; ++ unsigned int flags; + + tu = container_of(con, struct trace_uprobe, consumer); + +@@ -1540,11 +1543,12 @@ static int uretprobe_dispatcher(struct u + ucb = uprobe_buffer_get(); + store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize); + +- if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE)) ++ flags = trace_probe_load_flag(&tu->tp); ++ if (flags & TP_FLAG_TRACE) + uretprobe_trace_func(tu, func, regs, ucb, dsize); + + #ifdef CONFIG_PERF_EVENTS +- if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE)) ++ if (flags & TP_FLAG_PROFILE) + uretprobe_perf_func(tu, func, regs, ucb, dsize); + #endif + uprobe_buffer_put(ucb);