--- /dev/null
+From 5cbb549e283e1d42824bb61bc9e4ab3d10b22557 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Sep 2024 11:18:38 +0100
+Subject: arm64: Force position-independent veneers
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+[ Upstream commit 9abe390e689f4f5c23c5f507754f8678431b4f72 ]
+
+Certain portions of code always need to be position-independent
+regardless of CONFIG_RELOCATABLE, including code which is executed in an
+idmap or which is executed before relocations are applied. In some
+kernel configurations the LLD linker generates position-dependent
+veneers for such code, and when executed these result in early boot-time
+failures.
+
+Marc Zyngier encountered a boot failure resulting from this when
+building a (particularly cursed) configuration with LLVM, as he reported
+to the list:
+
+ https://lore.kernel.org/linux-arm-kernel/86wmjwvatn.wl-maz@kernel.org/
+
+In Marc's kernel configuration, the .head.text and .rodata.text sections
+end up more than 128MiB apart, requiring a veneer to branch between the
+two:
+
+| [mark@lakrids:~/src/linux]% usekorg 14.1.0 aarch64-linux-objdump -t vmlinux | grep -w _text
+| ffff800080000000 g .head.text 0000000000000000 _text
+| [mark@lakrids:~/src/linux]% usekorg 14.1.0 aarch64-linux-objdump -t vmlinux | grep -w primary_entry
+| ffff8000889df0e0 g .rodata.text 000000000000006c primary_entry,
+
+... consequently, LLD inserts a position-dependent veneer for the branch
+from _stext (in .head.text) to primary_entry (in .rodata.text):
+
+| ffff800080000000 <_text>:
+| ffff800080000000: fa405a4d ccmp x18, #0x0, #0xd, pl // pl = nfrst
+| ffff800080000004: 14003fff b ffff800080010000 <__AArch64AbsLongThunk_primary_entry>
+...
+| ffff800080010000 <__AArch64AbsLongThunk_primary_entry>:
+| ffff800080010000: 58000050 ldr x16, ffff800080010008 <__AArch64AbsLongThunk_primary_entry+0x8>
+| ffff800080010004: d61f0200 br x16
+| ffff800080010008: 889df0e0 .word 0x889df0e0
+| ffff80008001000c: ffff8000 .word 0xffff8000
+
+... and as this is executed early in boot before the kernel is mapped in
+TTBR1 this results in a silent boot failure.
+
+Fix this by passing '--pic-veneer' to the linker, which will cause the
+linker to use position-independent veneers, e.g.
+
+| ffff800080000000 <_text>:
+| ffff800080000000: fa405a4d ccmp x18, #0x0, #0xd, pl // pl = nfrst
+| ffff800080000004: 14003fff b ffff800080010000 <__AArch64ADRPThunk_primary_entry>
+...
+| ffff800080010000 <__AArch64ADRPThunk_primary_entry>:
+| ffff800080010000: f004e3f0 adrp x16, ffff800089c8f000 <__idmap_text_start>
+| ffff800080010004: 91038210 add x16, x16, #0xe0
+| ffff800080010008: d61f0200 br x16
+
+I've opted to pass '--pic-veneer' unconditionally, as:
+
+* In addition to solving the boot failure, these sequences are generally
+ nicer as they require fewer instructions and don't need to perform
+ data accesses.
+
+* While the position-independent veneer sequences have a limited +/-2GiB
+ range, this is not a new restriction. Even kernels built with
+ CONFIG_RELOCATABLE=n are limited to 2GiB in size as we have several
+ structues using 32-bit relative offsets and PPREL32 relocations, which
+ are similarly limited to +/-2GiB in range. These include extable
+ entries, jump table entries, and alt_instr entries.
+
+* GNU LD defaults to using position-independent veneers, and supports
+ the same '--pic-veneer' option, so this change is not expected to
+ adversely affect GNU LD.
+
+I've tested with GNU LD 2.30 to 2.42 inclusive and LLVM 13.0.1 to 19.1.0
+inclusive, using the kernel.org binaries from:
+
+* https://mirrors.edge.kernel.org/pub/tools/crosstool/
+* https://mirrors.edge.kernel.org/pub/tools/llvm/
+
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Reported-by: Marc Zyngier <maz@kernel.org>
+Cc: Ard Biesheuvel <ardb@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: Will Deacon <will@kernel.org>
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Nathan Chancellor <nathan@kernel.org>
+Link: https://lore.kernel.org/r/20240927101838.3061054-1-mark.rutland@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
+index f6bc3da1ef110..c8e237b20ef29 100644
+--- a/arch/arm64/Makefile
++++ b/arch/arm64/Makefile
+@@ -10,7 +10,7 @@
+ #
+ # Copyright (C) 1995-2001 by Russell King
+
+-LDFLAGS_vmlinux :=--no-undefined -X
++LDFLAGS_vmlinux :=--no-undefined -X --pic-veneer
+
+ ifeq ($(CONFIG_RELOCATABLE), y)
+ # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
+--
+2.43.0
+
--- /dev/null
+From 4bfc6749ecf08690fc7e222e376f10f50042cdf1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Sep 2024 00:44:08 -0400
+Subject: ASoC: amd: yc: Add quirk for HP Dragonfly pro one
+
+From: David Lawrence Glanzman <davidglanzman@yahoo.com>
+
+[ Upstream commit 84e8d59651879b2ff8499bddbbc9549b7f1a646b ]
+
+Adds a quirk entry to enable the mic on HP Dragonfly pro one laptop
+
+Signed-off-by: David Lawrence Glanzman <davidglanzman@yahoo.com>
+Link: https://patch.msgid.link/1249c09bd6bf696b59d087a4f546ae397828656c.camel@yahoo.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/amd/yc/acp6x-mach.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index 06349bf0b6587..ace6328e91e31 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -444,6 +444,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "8A3E"),
+ }
+ },
++ {
++ .driver_data = &acp6x_card,
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
++ DMI_MATCH(DMI_BOARD_NAME, "8A7F"),
++ }
++ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+--
+2.43.0
+
--- /dev/null
+From 437bf695e6f04bb77d5060163d8b0643f19c30a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Sep 2024 05:38:23 +0100
+Subject: ASoC: codecs: lpass-rx-macro: add missing CDC_RX_BCL_VBAT_RF_PROC2 to
+ default regs values
+
+From: Alexey Klimov <alexey.klimov@linaro.org>
+
+[ Upstream commit e249786b2188107a7c50e7174d35f955a60988a1 ]
+
+CDC_RX_BCL_VBAT_RF_PROC1 is listed twice and its default value
+is 0x2a which is overwriten by its next occurence in rx_defaults[].
+The second one should be missing CDC_RX_BCL_VBAT_RF_PROC2 instead
+and its default value is expected 0x0.
+
+Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
+Link: https://patch.msgid.link/20240925043823.520218-2-alexey.klimov@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/lpass-rx-macro.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
+index ce42749660c87..ac759f4a880d0 100644
+--- a/sound/soc/codecs/lpass-rx-macro.c
++++ b/sound/soc/codecs/lpass-rx-macro.c
+@@ -958,7 +958,7 @@ static const struct reg_default rx_defaults[] = {
+ { CDC_RX_BCL_VBAT_PK_EST2, 0x01 },
+ { CDC_RX_BCL_VBAT_PK_EST3, 0x40 },
+ { CDC_RX_BCL_VBAT_RF_PROC1, 0x2A },
+- { CDC_RX_BCL_VBAT_RF_PROC1, 0x00 },
++ { CDC_RX_BCL_VBAT_RF_PROC2, 0x00 },
+ { CDC_RX_BCL_VBAT_TAC1, 0x00 },
+ { CDC_RX_BCL_VBAT_TAC2, 0x18 },
+ { CDC_RX_BCL_VBAT_TAC3, 0x18 },
+--
+2.43.0
+
--- /dev/null
+From 847faecce33588ee55b38068a89a4c82d210190f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Sep 2024 14:08:28 +0800
+Subject: ASoC: fsl_sai: Enable 'FIFO continue on error' FCONT bit
+
+From: Shengjiu Wang <shengjiu.wang@nxp.com>
+
+[ Upstream commit 72455e33173c1a00c0ce93d2b0198eb45d5f4195 ]
+
+FCONT=1 means On FIFO error, the SAI will continue from the
+same word that caused the FIFO error to set after the FIFO
+warning flag has been cleared.
+
+Set FCONT bit in control register to avoid the channel swap
+issue after SAI xrun.
+
+Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
+Link: https://patch.msgid.link/1727676508-22830-1-git-send-email-shengjiu.wang@nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/fsl_sai.c | 5 ++++-
+ sound/soc/fsl/fsl_sai.h | 1 +
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
+index d03b0172b8ad2..a1f03c97b7bb8 100644
+--- a/sound/soc/fsl/fsl_sai.c
++++ b/sound/soc/fsl/fsl_sai.c
+@@ -613,6 +613,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
+
+ val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
+
++ /* Set to avoid channel swap */
++ val_cr4 |= FSL_SAI_CR4_FCONT;
++
+ /* Set to output mode to avoid tri-stated data pins */
+ if (tx)
+ val_cr4 |= FSL_SAI_CR4_CHMOD;
+@@ -699,7 +702,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
+
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
+ FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
+- FSL_SAI_CR4_CHMOD_MASK,
++ FSL_SAI_CR4_CHMOD_MASK | FSL_SAI_CR4_FCONT_MASK,
+ val_cr4);
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
+ FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
+diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
+index dadbd16ee3945..9c4d19fe22c65 100644
+--- a/sound/soc/fsl/fsl_sai.h
++++ b/sound/soc/fsl/fsl_sai.h
+@@ -137,6 +137,7 @@
+
+ /* SAI Transmit and Receive Configuration 4 Register */
+
++#define FSL_SAI_CR4_FCONT_MASK BIT(28)
+ #define FSL_SAI_CR4_FCONT BIT(28)
+ #define FSL_SAI_CR4_FCOMB_SHIFT BIT(26)
+ #define FSL_SAI_CR4_FCOMB_SOFT BIT(27)
+--
+2.43.0
+
--- /dev/null
+From dfca25124edec0cfe306fae6f488cb79d1a8692e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Oct 2024 03:20:10 +0100
+Subject: ASoC: qcom: sm8250: add qrb4210-rb2-sndcard compatible string
+
+From: Alexey Klimov <alexey.klimov@linaro.org>
+
+[ Upstream commit b97bc0656a66f89f78098d4d72dc04fa9518ab11 ]
+
+Add "qcom,qrb4210-rb2-sndcard" to the list of recognizable
+devices.
+
+Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
+Link: https://patch.msgid.link/20241002022015.867031-3-alexey.klimov@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/sm8250.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
+index a15dafb99b337..50e175fd521ce 100644
+--- a/sound/soc/qcom/sm8250.c
++++ b/sound/soc/qcom/sm8250.c
+@@ -166,6 +166,7 @@ static int sm8250_platform_probe(struct platform_device *pdev)
+
+ static const struct of_device_id snd_sm8250_dt_match[] = {
+ {.compatible = "qcom,sm8250-sndcard"},
++ {.compatible = "qcom,qrb4210-rb2-sndcard"},
+ {.compatible = "qcom,qrb5165-rb5-sndcard"},
+ {}
+ };
+--
+2.43.0
+
--- /dev/null
+From ec508a5930024b40064d70cb3dbdf856760cdf5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Sep 2024 12:16:38 +0200
+Subject: btrfs: also add stripe entries for NOCOW writes
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+[ Upstream commit 97f9782276fc9cb0de37a5eecb82204e48a5a612 ]
+
+NOCOW writes do not generate stripe_extent entries in the RAID stripe
+tree, as the RAID stripe-tree feature initially was designed with a
+zoned filesystem in mind and on a zoned filesystem, we do not allow NOCOW
+writes. But the RAID stripe-tree feature is independent from the zoned
+feature, so we must also do NOCOW writes for RAID stripe-tree filesystems.
+
+Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index b1b6564ab68f0..48149c2e68954 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -3087,6 +3087,11 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
+ ret = btrfs_update_inode_fallback(trans, inode);
+ if (ret) /* -ENOMEM or corruption */
+ btrfs_abort_transaction(trans, ret);
++
++ ret = btrfs_insert_raid_extent(trans, ordered_extent);
++ if (ret)
++ btrfs_abort_transaction(trans, ret);
++
+ goto out;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 3dc1710f39f70715f415b77ecc4b15a5ce1e17c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 28 Sep 2024 23:59:47 +0200
+Subject: cifs: Validate content of NFS reparse point buffer
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 556ac52bb1e76cc28fd30aa117b42989965b3efd ]
+
+Symlink target location stored in DataBuffer is encoded in UTF-16. So check
+that symlink DataBuffer length is non-zero and even number. And check that
+DataBuffer does not contain UTF-16 null codepoint because Linux cannot
+process symlink with null byte.
+
+DataBuffer for char and block devices is 8 bytes long as it contains two
+32-bit numbers (major and minor). Add check for this.
+
+DataBuffer buffer for sockets and fifos zero-length. Add checks for this.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/reparse.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
+index ad0e0de9a165d..7429b96a6ae5e 100644
+--- a/fs/smb/client/reparse.c
++++ b/fs/smb/client/reparse.c
+@@ -330,6 +330,18 @@ static int parse_reparse_posix(struct reparse_posix_data *buf,
+
+ switch ((type = le64_to_cpu(buf->InodeType))) {
+ case NFS_SPECFILE_LNK:
++ if (len == 0 || (len % 2)) {
++ cifs_dbg(VFS, "srv returned malformed nfs symlink buffer\n");
++ return -EIO;
++ }
++ /*
++ * Check that buffer does not contain UTF-16 null codepoint
++ * because Linux cannot process symlink with null byte.
++ */
++ if (UniStrnlen((wchar_t *)buf->DataBuffer, len/2) != len/2) {
++ cifs_dbg(VFS, "srv returned null byte in nfs symlink target location\n");
++ return -EIO;
++ }
+ data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer,
+ len, true,
+ cifs_sb->local_nls);
+@@ -340,8 +352,19 @@ static int parse_reparse_posix(struct reparse_posix_data *buf,
+ break;
+ case NFS_SPECFILE_CHR:
+ case NFS_SPECFILE_BLK:
++ /* DataBuffer for block and char devices contains two 32-bit numbers */
++ if (len != 8) {
++ cifs_dbg(VFS, "srv returned malformed nfs buffer for type: 0x%llx\n", type);
++ return -EIO;
++ }
++ break;
+ case NFS_SPECFILE_FIFO:
+ case NFS_SPECFILE_SOCK:
++ /* DataBuffer for fifos and sockets is empty */
++ if (len != 0) {
++ cifs_dbg(VFS, "srv returned malformed nfs buffer for type: 0x%llx\n", type);
++ return -EIO;
++ }
+ break;
+ default:
+ cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n",
+--
+2.43.0
+
--- /dev/null
+From e013605d4d89172ea0fe6db383a17b0426d75278 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 12:45:23 +0200
+Subject: drm/vboxvideo: Replace fake VLA at end of vbva_mouse_pointer_shape
+ with real VLA
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit d92b90f9a54d9300a6e883258e79f36dab53bfae ]
+
+Replace the fake VLA at end of the vbva_mouse_pointer_shape shape with
+a real VLA to fix a "memcpy: detected field-spanning write error" warning:
+
+[ 13.319813] memcpy: detected field-spanning write (size 16896) of single field "p->data" at drivers/gpu/drm/vboxvideo/hgsmi_base.c:154 (size 4)
+[ 13.319841] WARNING: CPU: 0 PID: 1105 at drivers/gpu/drm/vboxvideo/hgsmi_base.c:154 hgsmi_update_pointer_shape+0x192/0x1c0 [vboxvideo]
+[ 13.320038] Call Trace:
+[ 13.320173] hgsmi_update_pointer_shape [vboxvideo]
+[ 13.320184] vbox_cursor_atomic_update [vboxvideo]
+
+Note as mentioned in the added comment it seems the original length
+calculation for the allocated and send hgsmi buffer is 4 bytes too large.
+Changing this is not the goal of this patch, so this behavior is kept.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240827104523.17442-1-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vboxvideo/hgsmi_base.c | 10 +++++++++-
+ drivers/gpu/drm/vboxvideo/vboxvideo.h | 4 +---
+ 2 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/vboxvideo/hgsmi_base.c b/drivers/gpu/drm/vboxvideo/hgsmi_base.c
+index 8c041d7ce4f1b..87dccaecc3e57 100644
+--- a/drivers/gpu/drm/vboxvideo/hgsmi_base.c
++++ b/drivers/gpu/drm/vboxvideo/hgsmi_base.c
+@@ -139,7 +139,15 @@ int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags,
+ flags |= VBOX_MOUSE_POINTER_VISIBLE;
+ }
+
+- p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
++ /*
++ * The 4 extra bytes come from switching struct vbva_mouse_pointer_shape
++ * from having a 4 bytes fixed array at the end to using a proper VLA
++ * at the end. These 4 extra bytes were not subtracted from sizeof(*p)
++ * before the switch to the VLA, so this way the behavior is unchanged.
++ * Chances are these 4 extra bytes are not necessary but they are kept
++ * to avoid regressions.
++ */
++ p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len + 4, HGSMI_CH_VBVA,
+ VBVA_MOUSE_POINTER_SHAPE);
+ if (!p)
+ return -ENOMEM;
+diff --git a/drivers/gpu/drm/vboxvideo/vboxvideo.h b/drivers/gpu/drm/vboxvideo/vboxvideo.h
+index f60d82504da02..79ec8481de0e4 100644
+--- a/drivers/gpu/drm/vboxvideo/vboxvideo.h
++++ b/drivers/gpu/drm/vboxvideo/vboxvideo.h
+@@ -351,10 +351,8 @@ struct vbva_mouse_pointer_shape {
+ * Bytes in the gap between the AND and the XOR mask are undefined.
+ * XOR mask scanlines have no gap between them and size of XOR mask is:
+ * xor_len = width * 4 * height.
+- *
+- * Preallocate 4 bytes for accessing actual data as p->data.
+ */
+- u8 data[4];
++ u8 data[];
+ } __packed;
+
+ /* pointer is visible */
+--
+2.43.0
+
--- /dev/null
+From 8cdafe24d79effa5a810f6b19e511745712ff40d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Sep 2024 18:13:15 -0300
+Subject: drm/xe/mcr: Use Xe2_LPM steering tables for Xe2_HPM
+
+From: Gustavo Sousa <gustavo.sousa@intel.com>
+
+[ Upstream commit 7929ffce0f8b9c76cb5c2a67d1966beaed20ab61 ]
+
+According to Bspec, Xe2 steering tables must be used for Xe2_HPM, just
+as it is with Xe2_LPM. Update our driver to reflect that.
+
+Bspec: 71186
+Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
+Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
+Reviewed-by: Tejas Upadhyay <tejas.upadhyay@intel.com>
+Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240920211459.255181-2-gustavo.sousa@intel.com
+(cherry picked from commit 21ae035ae5c33ef176f4062bd9d4aa973dde240b)
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt_mcr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
+index 6d948a4691264..d57a765a1a969 100644
+--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
++++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
+@@ -407,7 +407,7 @@ void xe_gt_mcr_init(struct xe_gt *gt)
+ if (gt->info.type == XE_GT_TYPE_MEDIA) {
+ drm_WARN_ON(&xe->drm, MEDIA_VER(xe) < 13);
+
+- if (MEDIA_VER(xe) >= 20) {
++ if (MEDIA_VERx100(xe) >= 1301) {
+ gt->steering[OADDRM].ranges = xe2lpm_gpmxmt_steering_table;
+ gt->steering[INSTANCE0].ranges = xe2lpm_instance0_steering_table;
+ } else {
+--
+2.43.0
+
--- /dev/null
+From af603e3969ff4dbbed40ab86b65a2488b9db9bd4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 16:06:23 +0200
+Subject: fsnotify: Avoid data race between fsnotify_recalc_mask() and
+ fsnotify_object_watched()
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit 35ceae44742e1101f9d20adadbbbd92c05d7d659 ]
+
+When __fsnotify_recalc_mask() recomputes the mask on the watched object,
+the compiler can "optimize" the code to perform partial updates to the
+mask (including zeroing it at the beginning). Thus places checking
+the object mask without conn->lock such as fsnotify_object_watched()
+could see invalid states of the mask. Make sure the mask update is
+performed by one memory store using WRITE_ONCE().
+
+Reported-by: syzbot+701037856c25b143f1ad@syzkaller.appspotmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Link: https://lore.kernel.org/all/CACT4Y+Zk0ohwwwHSD63U2-PQ=UuamXczr1mKBD6xtj2dyYKBvA@mail.gmail.com
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Link: https://patch.msgid.link/20240717140623.27768-1-jack@suse.cz
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/notify/fsnotify.c | 21 ++++++++++++---------
+ fs/notify/inotify/inotify_user.c | 2 +-
+ fs/notify/mark.c | 8 ++++++--
+ 3 files changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
+index 272c8a1dab3c2..82ae8254c068b 100644
+--- a/fs/notify/fsnotify.c
++++ b/fs/notify/fsnotify.c
+@@ -183,8 +183,10 @@ static bool fsnotify_event_needs_parent(struct inode *inode, __u32 mnt_mask,
+ BUILD_BUG_ON(FS_EVENTS_POSS_ON_CHILD & ~FS_EVENTS_POSS_TO_PARENT);
+
+ /* Did either inode/sb/mount subscribe for events with parent/name? */
+- marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask);
+- marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask);
++ marks_mask |= fsnotify_parent_needed_mask(
++ READ_ONCE(inode->i_fsnotify_mask));
++ marks_mask |= fsnotify_parent_needed_mask(
++ READ_ONCE(inode->i_sb->s_fsnotify_mask));
+ marks_mask |= fsnotify_parent_needed_mask(mnt_mask);
+
+ /* Did they subscribe for this event with parent/name info? */
+@@ -195,8 +197,8 @@ static bool fsnotify_event_needs_parent(struct inode *inode, __u32 mnt_mask,
+ static inline bool fsnotify_object_watched(struct inode *inode, __u32 mnt_mask,
+ __u32 mask)
+ {
+- __u32 marks_mask = inode->i_fsnotify_mask | mnt_mask |
+- inode->i_sb->s_fsnotify_mask;
++ __u32 marks_mask = READ_ONCE(inode->i_fsnotify_mask) | mnt_mask |
++ READ_ONCE(inode->i_sb->s_fsnotify_mask);
+
+ return mask & marks_mask & ALL_FSNOTIFY_EVENTS;
+ }
+@@ -213,7 +215,8 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
+ int data_type)
+ {
+ const struct path *path = fsnotify_data_path(data, data_type);
+- __u32 mnt_mask = path ? real_mount(path->mnt)->mnt_fsnotify_mask : 0;
++ __u32 mnt_mask = path ?
++ READ_ONCE(real_mount(path->mnt)->mnt_fsnotify_mask) : 0;
+ struct inode *inode = d_inode(dentry);
+ struct dentry *parent;
+ bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
+@@ -557,13 +560,13 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
+ (!inode2 || !inode2->i_fsnotify_marks))
+ return 0;
+
+- marks_mask = sb->s_fsnotify_mask;
++ marks_mask = READ_ONCE(sb->s_fsnotify_mask);
+ if (mnt)
+- marks_mask |= mnt->mnt_fsnotify_mask;
++ marks_mask |= READ_ONCE(mnt->mnt_fsnotify_mask);
+ if (inode)
+- marks_mask |= inode->i_fsnotify_mask;
++ marks_mask |= READ_ONCE(inode->i_fsnotify_mask);
+ if (inode2)
+- marks_mask |= inode2->i_fsnotify_mask;
++ marks_mask |= READ_ONCE(inode2->i_fsnotify_mask);
+
+
+ /*
+diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
+index 4ffc30606e0b9..e163a4b790224 100644
+--- a/fs/notify/inotify/inotify_user.c
++++ b/fs/notify/inotify/inotify_user.c
+@@ -569,7 +569,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
+ /* more bits in old than in new? */
+ int dropped = (old_mask & ~new_mask);
+ /* more bits in this fsn_mark than the inode's mask? */
+- int do_inode = (new_mask & ~inode->i_fsnotify_mask);
++ int do_inode = (new_mask & ~READ_ONCE(inode->i_fsnotify_mask));
+
+ /* update the inode with this new fsn_mark */
+ if (dropped || do_inode)
+diff --git a/fs/notify/mark.c b/fs/notify/mark.c
+index 5e170e7130886..c45b222cf9c11 100644
+--- a/fs/notify/mark.c
++++ b/fs/notify/mark.c
+@@ -128,7 +128,7 @@ __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn)
+ if (WARN_ON(!fsnotify_valid_obj_type(conn->type)))
+ return 0;
+
+- return *fsnotify_conn_mask_p(conn);
++ return READ_ONCE(*fsnotify_conn_mask_p(conn));
+ }
+
+ static void fsnotify_get_sb_watched_objects(struct super_block *sb)
+@@ -245,7 +245,11 @@ static void *__fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
+ !(mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF))
+ want_iref = true;
+ }
+- *fsnotify_conn_mask_p(conn) = new_mask;
++ /*
++ * We use WRITE_ONCE() to prevent silly compiler optimizations from
++ * confusing readers not holding conn->lock with partial updates.
++ */
++ WRITE_ONCE(*fsnotify_conn_mask_p(conn), new_mask);
+
+ return fsnotify_update_iref(conn, want_iref);
+ }
+--
+2.43.0
+
--- /dev/null
+From 725153a7bd715a8b7bc1cab106f37ee31fddaa9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Oct 2024 23:27:58 +0800
+Subject: platform/x86: dell-sysman: add support for alienware products
+
+From: Crag Wang <crag_wang@dell.com>
+
+[ Upstream commit a561509b4187a8908eb7fbb2d1bf35bbc20ec74b ]
+
+Alienware supports firmware-attributes and has its own OEM string.
+
+Signed-off-by: Crag Wang <crag_wang@dell.com>
+Link: https://lore.kernel.org/r/20241004152826.93992-1-crag_wang@dell.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/dell/dell-wmi-sysman/sysman.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
+index 9def7983d7d66..40ddc6eb75624 100644
+--- a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
++++ b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
+@@ -521,6 +521,7 @@ static int __init sysman_init(void)
+ int ret = 0;
+
+ if (!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL) &&
++ !dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Alienware", NULL) &&
+ !dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "www.dell.com", NULL)) {
+ pr_err("Unable to run on non-Dell system\n");
+ return -ENODEV;
+--
+2.43.0
+
xhci-dbgtty-remove-kfifo_out-wrapper.patch
xhci-dbgtty-use-kfifo-from-tty_port-struct.patch
xhci-dbc-honor-usb-transfer-size-boundaries.patch
+uprobe-avoid-out-of-bounds-memory-access-of-fetching.patch
+drm-vboxvideo-replace-fake-vla-at-end-of-vbva_mouse_.patch
+asoc-amd-yc-add-quirk-for-hp-dragonfly-pro-one.patch
+asoc-codecs-lpass-rx-macro-add-missing-cdc_rx_bcl_vb.patch
+asoc-fsl_sai-enable-fifo-continue-on-error-fcont-bit.patch
+arm64-force-position-independent-veneers.patch
+btrfs-also-add-stripe-entries-for-nocow-writes.patch
+udf-refactor-udf_current_aext-to-handle-error.patch
+udf-refactor-udf_next_aext-to-handle-error.patch
+udf-refactor-inode_bmap-to-handle-error.patch
+udf-fix-uninit-value-use-in-udf_get_fileshortad.patch
+asoc-qcom-sm8250-add-qrb4210-rb2-sndcard-compatible-.patch
+fsnotify-avoid-data-race-between-fsnotify_recalc_mas.patch
+drm-xe-mcr-use-xe2_lpm-steering-tables-for-xe2_hpm.patch
+cifs-validate-content-of-nfs-reparse-point-buffer.patch
+platform-x86-dell-sysman-add-support-for-alienware-p.patch
--- /dev/null
+From 2c607ec65d669a62a9703992a658c580ac34b73f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Sep 2024 09:46:15 +0200
+Subject: udf: fix uninit-value use in udf_get_fileshortad
+
+From: Gianfranco Trad <gianf.trad@gmail.com>
+
+[ Upstream commit 264db9d666ad9a35075cc9ed9ec09d021580fbb1 ]
+
+Check for overflow when computing alen in udf_current_aext to mitigate
+later uninit-value use in udf_get_fileshortad KMSAN bug[1].
+After applying the patch reproducer did not trigger any issue[2].
+
+[1] https://syzkaller.appspot.com/bug?extid=8901c4560b7ab5c2f9df
+[2] https://syzkaller.appspot.com/x/log.txt?x=10242227980000
+
+Reported-by: syzbot+8901c4560b7ab5c2f9df@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8901c4560b7ab5c2f9df
+Tested-by: syzbot+8901c4560b7ab5c2f9df@syzkaller.appspotmail.com
+Suggested-by: Jan Kara <jack@suse.com>
+Signed-off-by: Gianfranco Trad <gianf.trad@gmail.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240925074613.8475-3-gianf.trad@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/inode.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 80dae442ecd72..53511c726d575 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -2257,12 +2257,15 @@ int udf_current_aext(struct inode *inode, struct extent_position *epos,
+ alen = udf_file_entry_alloc_offset(inode) +
+ iinfo->i_lenAlloc;
+ } else {
++ struct allocExtDesc *header =
++ (struct allocExtDesc *)epos->bh->b_data;
++
+ if (!epos->offset)
+ epos->offset = sizeof(struct allocExtDesc);
+ ptr = epos->bh->b_data + epos->offset;
+- alen = sizeof(struct allocExtDesc) +
+- le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->
+- lengthAllocDescs);
++ if (check_add_overflow(sizeof(struct allocExtDesc),
++ le32_to_cpu(header->lengthAllocDescs), &alen))
++ return -1;
+ }
+
+ switch (iinfo->i_alloc_type) {
+--
+2.43.0
+
--- /dev/null
+From 3db19a69e1b7cd80e1c4e2bdae3eca3f80223bf8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 19:54:25 +0800
+Subject: udf: refactor inode_bmap() to handle error
+
+From: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+
+[ Upstream commit c226964ec786f3797ed389a16392ce4357697d24 ]
+
+Refactor inode_bmap() to handle error since udf_next_aext() can return
+error now. On situations like ftruncate, udf_extend_file() can now
+detect errors and bail out early without resorting to checking for
+particular offsets and assuming internal behavior of these functions.
+
+Reported-by: syzbot+7a4842f0b1801230a989@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=7a4842f0b1801230a989
+Tested-by: syzbot+7a4842f0b1801230a989@syzkaller.appspotmail.com
+Signed-off-by: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20241001115425.266556-4-zhaomzhao@126.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/directory.c | 13 ++++++++-----
+ fs/udf/inode.c | 40 +++++++++++++++++++++++++---------------
+ fs/udf/partition.c | 6 ++++--
+ fs/udf/truncate.c | 6 ++++--
+ fs/udf/udfdecl.h | 5 +++--
+ 5 files changed, 44 insertions(+), 26 deletions(-)
+
+diff --git a/fs/udf/directory.c b/fs/udf/directory.c
+index c6950050e7aeb..632453aa38934 100644
+--- a/fs/udf/directory.c
++++ b/fs/udf/directory.c
+@@ -246,6 +246,7 @@ int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
+ {
+ struct udf_inode_info *iinfo = UDF_I(dir);
+ int err = 0;
++ int8_t etype;
+
+ iter->dir = dir;
+ iter->bh[0] = iter->bh[1] = NULL;
+@@ -265,9 +266,9 @@ int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
+ goto out;
+ }
+
+- if (inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
+- &iter->eloc, &iter->elen, &iter->loffset) !=
+- (EXT_RECORDED_ALLOCATED >> 30)) {
++ err = inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
++ &iter->eloc, &iter->elen, &iter->loffset, &etype);
++ if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
+ if (pos == dir->i_size)
+ return 0;
+ udf_err(dir->i_sb,
+@@ -463,6 +464,7 @@ int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
+ sector_t block;
+ uint32_t old_elen = iter->elen;
+ int err;
++ int8_t etype;
+
+ if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB))
+ return -EINVAL;
+@@ -477,8 +479,9 @@ int udf_fiiter_append_blk(struct udf_fileident_iter *iter)
+ udf_fiiter_update_elen(iter, old_elen);
+ return err;
+ }
+- if (inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
+- &iter->loffset) != (EXT_RECORDED_ALLOCATED >> 30)) {
++ err = inode_bmap(iter->dir, block, &iter->epos, &iter->eloc, &iter->elen,
++ &iter->loffset, &etype);
++ if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
+ udf_err(iter->dir->i_sb,
+ "block %llu not allocated in directory (ino %lu)\n",
+ (unsigned long long)block, iter->dir->i_ino);
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 0459a87d4c02a..80dae442ecd72 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -406,7 +406,7 @@ struct udf_map_rq {
+
+ static int udf_map_block(struct inode *inode, struct udf_map_rq *map)
+ {
+- int err;
++ int ret;
+ struct udf_inode_info *iinfo = UDF_I(inode);
+
+ if (WARN_ON_ONCE(iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB))
+@@ -418,18 +418,24 @@ static int udf_map_block(struct inode *inode, struct udf_map_rq *map)
+ uint32_t elen;
+ sector_t offset;
+ struct extent_position epos = {};
++ int8_t etype;
+
+ down_read(&iinfo->i_data_sem);
+- if (inode_bmap(inode, map->lblk, &epos, &eloc, &elen, &offset)
+- == (EXT_RECORDED_ALLOCATED >> 30)) {
++ ret = inode_bmap(inode, map->lblk, &epos, &eloc, &elen, &offset,
++ &etype);
++ if (ret < 0)
++ goto out_read;
++ if (ret > 0 && etype == (EXT_RECORDED_ALLOCATED >> 30)) {
+ map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc,
+ offset);
+ map->oflags |= UDF_BLK_MAPPED;
++ ret = 0;
+ }
++out_read:
+ up_read(&iinfo->i_data_sem);
+ brelse(epos.bh);
+
+- return 0;
++ return ret;
+ }
+
+ down_write(&iinfo->i_data_sem);
+@@ -440,9 +446,9 @@ static int udf_map_block(struct inode *inode, struct udf_map_rq *map)
+ if (((loff_t)map->lblk) << inode->i_blkbits >= iinfo->i_lenExtents)
+ udf_discard_prealloc(inode);
+ udf_clear_extent_cache(inode);
+- err = inode_getblk(inode, map);
++ ret = inode_getblk(inode, map);
+ up_write(&iinfo->i_data_sem);
+- return err;
++ return ret;
+ }
+
+ static int __udf_get_block(struct inode *inode, sector_t block,
+@@ -664,8 +670,10 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
+ */
+ udf_discard_prealloc(inode);
+
+- etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
+- within_last_ext = (etype != -1);
++ err = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset, &etype);
++ if (err < 0)
++ goto out;
++ within_last_ext = (err == 1);
+ /* We don't expect extents past EOF... */
+ WARN_ON_ONCE(within_last_ext &&
+ elen > ((loff_t)offset + 1) << inode->i_blkbits);
+@@ -2403,13 +2411,15 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
+ return (elen >> 30);
+ }
+
+-int8_t inode_bmap(struct inode *inode, sector_t block,
+- struct extent_position *pos, struct kernel_lb_addr *eloc,
+- uint32_t *elen, sector_t *offset)
++/*
++ * Returns 1 on success, -errno on error, 0 on hit EOF.
++ */
++int inode_bmap(struct inode *inode, sector_t block, struct extent_position *pos,
++ struct kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset,
++ int8_t *etype)
+ {
+ unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
+ loff_t lbcount = 0, bcount = (loff_t) block << blocksize_bits;
+- int8_t etype;
+ struct udf_inode_info *iinfo;
+ int err = 0;
+
+@@ -2421,13 +2431,13 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
+ }
+ *elen = 0;
+ do {
+- err = udf_next_aext(inode, pos, eloc, elen, &etype, 1);
++ err = udf_next_aext(inode, pos, eloc, elen, etype, 1);
+ if (err <= 0) {
+ if (err == 0) {
+ *offset = (bcount - lbcount) >> blocksize_bits;
+ iinfo->i_lenExtents = lbcount;
+ }
+- return -1;
++ return err;
+ }
+ lbcount += *elen;
+ } while (lbcount <= bcount);
+@@ -2435,5 +2445,5 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
+ udf_update_extent_cache(inode, lbcount - *elen, pos);
+ *offset = (bcount + *elen - lbcount) >> blocksize_bits;
+
+- return etype;
++ return 1;
+ }
+diff --git a/fs/udf/partition.c b/fs/udf/partition.c
+index af877991edc13..2b85c9501bed8 100644
+--- a/fs/udf/partition.c
++++ b/fs/udf/partition.c
+@@ -282,9 +282,11 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
+ sector_t ext_offset;
+ struct extent_position epos = {};
+ uint32_t phyblock;
++ int8_t etype;
++ int err = 0;
+
+- if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
+- (EXT_RECORDED_ALLOCATED >> 30))
++ err = inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset, &etype);
++ if (err <= 0 || etype != (EXT_RECORDED_ALLOCATED >> 30))
+ phyblock = 0xFFFFFFFF;
+ else {
+ map = &UDF_SB(sb)->s_partmaps[partition];
+diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
+index 399958f891d14..4f33a4a488861 100644
+--- a/fs/udf/truncate.c
++++ b/fs/udf/truncate.c
+@@ -214,10 +214,12 @@ int udf_truncate_extents(struct inode *inode)
+ else
+ BUG();
+
+- etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
++ ret = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset, &etype);
++ if (ret < 0)
++ return ret;
+ byte_offset = (offset << sb->s_blocksize_bits) +
+ (inode->i_size & (sb->s_blocksize - 1));
+- if (etype == -1) {
++ if (ret == 0) {
+ /* We should extend the file? */
+ WARN_ON(byte_offset);
+ return 0;
+diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
+index 5067ed68a8b45..d159f20d61e89 100644
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -157,8 +157,9 @@ extern struct buffer_head *udf_bread(struct inode *inode, udf_pblk_t block,
+ extern int udf_setsize(struct inode *, loff_t);
+ extern void udf_evict_inode(struct inode *);
+ extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
+-extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *,
+- struct kernel_lb_addr *, uint32_t *, sector_t *);
++extern int inode_bmap(struct inode *inode, sector_t block,
++ struct extent_position *pos, struct kernel_lb_addr *eloc,
++ uint32_t *elen, sector_t *offset, int8_t *etype);
+ int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
+ extern int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
+ struct extent_position *epos);
+--
+2.43.0
+
--- /dev/null
+From 0d84f8185338566f16a1178b4d06bd725ab2999e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 19:54:23 +0800
+Subject: udf: refactor udf_current_aext() to handle error
+
+From: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+
+[ Upstream commit ee703a7068f95764cfb62b57db1d36e465cb9b26 ]
+
+As Jan suggested in links below, refactor udf_current_aext() to
+differentiate between error, hit EOF and success, it now takes pointer to
+etype to store the extent type, return 1 when getting etype success,
+return 0 when hitting EOF and return -errno when err.
+
+Link: https://lore.kernel.org/all/20240912111235.6nr3wuqvktecy3vh@quack3/
+Signed-off-by: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20241001115425.266556-2-zhaomzhao@126.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/inode.c | 40 ++++++++++++++++++++++++++--------------
+ fs/udf/truncate.c | 10 ++++++++--
+ fs/udf/udfdecl.h | 5 +++--
+ 3 files changed, 37 insertions(+), 18 deletions(-)
+
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 4726a4d014b60..c64c2eff3399a 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -1955,6 +1955,7 @@ int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
+ struct extent_position nepos;
+ struct kernel_lb_addr neloc;
+ int ver, adsize;
++ int err = 0;
+
+ if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+ adsize = sizeof(struct short_ad);
+@@ -1999,10 +2000,12 @@ int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
+ if (epos->offset + adsize > sb->s_blocksize) {
+ struct kernel_lb_addr cp_loc;
+ uint32_t cp_len;
+- int cp_type;
++ int8_t cp_type;
+
+ epos->offset -= adsize;
+- cp_type = udf_current_aext(inode, epos, &cp_loc, &cp_len, 0);
++ err = udf_current_aext(inode, epos, &cp_loc, &cp_len, &cp_type, 0);
++ if (err <= 0)
++ goto err_out;
+ cp_len |= ((uint32_t)cp_type) << 30;
+
+ __udf_add_aext(inode, &nepos, &cp_loc, cp_len, 1);
+@@ -2017,6 +2020,9 @@ int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
+ *epos = nepos;
+
+ return 0;
++err_out:
++ brelse(bh);
++ return err;
+ }
+
+ /*
+@@ -2167,9 +2173,12 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
+ {
+ int8_t etype;
+ unsigned int indirections = 0;
++ int ret = 0;
+
+- while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
+- (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) {
++ while ((ret = udf_current_aext(inode, epos, eloc, elen,
++ &etype, inc)) > 0) {
++ if (etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30))
++ break;
+ udf_pblk_t block;
+
+ if (++indirections > UDF_MAX_INDIR_EXTS) {
+@@ -2190,14 +2199,17 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
+ }
+ }
+
+- return etype;
++ return ret > 0 ? etype : -1;
+ }
+
+-int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
+- struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
++/*
++ * Returns 1 on success, -errno on error, 0 on hit EOF.
++ */
++int udf_current_aext(struct inode *inode, struct extent_position *epos,
++ struct kernel_lb_addr *eloc, uint32_t *elen, int8_t *etype,
++ int inc)
+ {
+ int alen;
+- int8_t etype;
+ uint8_t *ptr;
+ struct short_ad *sad;
+ struct long_ad *lad;
+@@ -2224,8 +2236,8 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
+ case ICBTAG_FLAG_AD_SHORT:
+ sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc);
+ if (!sad)
+- return -1;
+- etype = le32_to_cpu(sad->extLength) >> 30;
++ return 0;
++ *etype = le32_to_cpu(sad->extLength) >> 30;
+ eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
+ eloc->partitionReferenceNum =
+ iinfo->i_location.partitionReferenceNum;
+@@ -2234,17 +2246,17 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
+ case ICBTAG_FLAG_AD_LONG:
+ lad = udf_get_filelongad(ptr, alen, &epos->offset, inc);
+ if (!lad)
+- return -1;
+- etype = le32_to_cpu(lad->extLength) >> 30;
++ return 0;
++ *etype = le32_to_cpu(lad->extLength) >> 30;
+ *eloc = lelb_to_cpu(lad->extLocation);
+ *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
+ break;
+ default:
+ udf_debug("alloc_type = %u unsupported\n", iinfo->i_alloc_type);
+- return -1;
++ return -EINVAL;
+ }
+
+- return etype;
++ return 1;
+ }
+
+ static int udf_insert_aext(struct inode *inode, struct extent_position epos,
+diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
+index a686c10fd709d..4758ba7b5f51c 100644
+--- a/fs/udf/truncate.c
++++ b/fs/udf/truncate.c
+@@ -188,6 +188,7 @@ int udf_truncate_extents(struct inode *inode)
+ loff_t byte_offset;
+ int adsize;
+ struct udf_inode_info *iinfo = UDF_I(inode);
++ int ret = 0;
+
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+ adsize = sizeof(struct short_ad);
+@@ -217,8 +218,8 @@ int udf_truncate_extents(struct inode *inode)
+ else
+ lenalloc -= sizeof(struct allocExtDesc);
+
+- while ((etype = udf_current_aext(inode, &epos, &eloc,
+- &elen, 0)) != -1) {
++ while ((ret = udf_current_aext(inode, &epos, &eloc,
++ &elen, &etype, 0)) > 0) {
+ if (etype == (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) {
+ udf_write_aext(inode, &epos, &neloc, nelen, 0);
+ if (indirect_ext_len) {
+@@ -253,6 +254,11 @@ int udf_truncate_extents(struct inode *inode)
+ }
+ }
+
++ if (ret < 0) {
++ brelse(epos.bh);
++ return ret;
++ }
++
+ if (indirect_ext_len) {
+ BUG_ON(!epos.bh);
+ udf_free_blocks(sb, NULL, &epos.block, 0, indirect_ext_len);
+diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
+index 88692512a4668..d893db95ac70e 100644
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -171,8 +171,9 @@ extern void udf_write_aext(struct inode *, struct extent_position *,
+ extern int8_t udf_delete_aext(struct inode *, struct extent_position);
+ extern int8_t udf_next_aext(struct inode *, struct extent_position *,
+ struct kernel_lb_addr *, uint32_t *, int);
+-extern int8_t udf_current_aext(struct inode *, struct extent_position *,
+- struct kernel_lb_addr *, uint32_t *, int);
++extern int udf_current_aext(struct inode *inode, struct extent_position *epos,
++ struct kernel_lb_addr *eloc, uint32_t *elen,
++ int8_t *etype, int inc);
+ extern void udf_update_extra_perms(struct inode *inode, umode_t mode);
+
+ /* misc.c */
+--
+2.43.0
+
--- /dev/null
+From c0545b47d2e0792d61de8e1fa88a83efbfc86b65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 19:54:24 +0800
+Subject: udf: refactor udf_next_aext() to handle error
+
+From: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+
+[ Upstream commit b405c1e58b73981da0f8df03b00666b22b9397ae ]
+
+Since udf_current_aext() has error handling, udf_next_aext() should have
+error handling too. Besides, when too many indirect extents found in one
+inode, return -EFSCORRUPTED; when reading block failed, return -EIO.
+
+Signed-off-by: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20241001115425.266556-3-zhaomzhao@126.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/balloc.c | 38 +++++++++-----
+ fs/udf/directory.c | 10 +++-
+ fs/udf/inode.c | 125 ++++++++++++++++++++++++++++++---------------
+ fs/udf/super.c | 3 +-
+ fs/udf/truncate.c | 27 ++++++++--
+ fs/udf/udfdecl.h | 5 +-
+ 6 files changed, 143 insertions(+), 65 deletions(-)
+
+diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
+index d8fc11765d612..807c493ed0cd5 100644
+--- a/fs/udf/balloc.c
++++ b/fs/udf/balloc.c
+@@ -370,6 +370,7 @@ static void udf_table_free_blocks(struct super_block *sb,
+ struct extent_position oepos, epos;
+ int8_t etype;
+ struct udf_inode_info *iinfo;
++ int ret = 0;
+
+ mutex_lock(&sbi->s_alloc_mutex);
+ iinfo = UDF_I(table);
+@@ -383,8 +384,12 @@ static void udf_table_free_blocks(struct super_block *sb,
+ epos.block = oepos.block = iinfo->i_location;
+ epos.bh = oepos.bh = NULL;
+
+- while (count &&
+- (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
++ while (count) {
++ ret = udf_next_aext(table, &epos, &eloc, &elen, &etype, 1);
++ if (ret < 0)
++ goto error_return;
++ if (ret == 0)
++ break;
+ if (((eloc.logicalBlockNum +
+ (elen >> sb->s_blocksize_bits)) == start)) {
+ if ((0x3FFFFFFF - elen) <
+@@ -459,11 +464,8 @@ static void udf_table_free_blocks(struct super_block *sb,
+ adsize = sizeof(struct short_ad);
+ else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
+ adsize = sizeof(struct long_ad);
+- else {
+- brelse(oepos.bh);
+- brelse(epos.bh);
++ else
+ goto error_return;
+- }
+
+ if (epos.offset + (2 * adsize) > sb->s_blocksize) {
+ /* Steal a block from the extent being free'd */
+@@ -479,10 +481,10 @@ static void udf_table_free_blocks(struct super_block *sb,
+ __udf_add_aext(table, &epos, &eloc, elen, 1);
+ }
+
++error_return:
+ brelse(epos.bh);
+ brelse(oepos.bh);
+
+-error_return:
+ mutex_unlock(&sbi->s_alloc_mutex);
+ return;
+ }
+@@ -498,6 +500,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
+ struct extent_position epos;
+ int8_t etype = -1;
+ struct udf_inode_info *iinfo;
++ int ret = 0;
+
+ if (first_block >= sbi->s_partmaps[partition].s_partition_len)
+ return 0;
+@@ -516,11 +519,14 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
+ epos.bh = NULL;
+ eloc.logicalBlockNum = 0xFFFFFFFF;
+
+- while (first_block != eloc.logicalBlockNum &&
+- (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
++ while (first_block != eloc.logicalBlockNum) {
++ ret = udf_next_aext(table, &epos, &eloc, &elen, &etype, 1);
++ if (ret < 0)
++ goto err_out;
++ if (ret == 0)
++ break;
+ udf_debug("eloc=%u, elen=%u, first_block=%u\n",
+ eloc.logicalBlockNum, elen, first_block);
+- ; /* empty loop body */
+ }
+
+ if (first_block == eloc.logicalBlockNum) {
+@@ -539,6 +545,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
+ alloc_count = 0;
+ }
+
++err_out:
+ brelse(epos.bh);
+
+ if (alloc_count)
+@@ -560,6 +567,7 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
+ struct extent_position epos, goal_epos;
+ int8_t etype;
+ struct udf_inode_info *iinfo = UDF_I(table);
++ int ret = 0;
+
+ *err = -ENOSPC;
+
+@@ -583,8 +591,10 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
+ epos.block = iinfo->i_location;
+ epos.bh = goal_epos.bh = NULL;
+
+- while (spread &&
+- (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {
++ while (spread) {
++ ret = udf_next_aext(table, &epos, &eloc, &elen, &etype, 1);
++ if (ret <= 0)
++ break;
+ if (goal >= eloc.logicalBlockNum) {
+ if (goal < eloc.logicalBlockNum +
+ (elen >> sb->s_blocksize_bits))
+@@ -612,9 +622,11 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
+
+ brelse(epos.bh);
+
+- if (spread == 0xFFFFFFFF) {
++ if (ret < 0 || spread == 0xFFFFFFFF) {
+ brelse(goal_epos.bh);
+ mutex_unlock(&sbi->s_alloc_mutex);
++ if (ret < 0)
++ *err = ret;
+ return 0;
+ }
+
+diff --git a/fs/udf/directory.c b/fs/udf/directory.c
+index 93153665eb374..c6950050e7aeb 100644
+--- a/fs/udf/directory.c
++++ b/fs/udf/directory.c
+@@ -166,13 +166,19 @@ static struct buffer_head *udf_fiiter_bread_blk(struct udf_fileident_iter *iter)
+ */
+ static int udf_fiiter_advance_blk(struct udf_fileident_iter *iter)
+ {
++ int8_t etype = -1;
++ int err = 0;
++
+ iter->loffset++;
+ if (iter->loffset < DIV_ROUND_UP(iter->elen, 1<<iter->dir->i_blkbits))
+ return 0;
+
+ iter->loffset = 0;
+- if (udf_next_aext(iter->dir, &iter->epos, &iter->eloc, &iter->elen, 1)
+- != (EXT_RECORDED_ALLOCATED >> 30)) {
++ err = udf_next_aext(iter->dir, &iter->epos, &iter->eloc,
++ &iter->elen, &etype, 1);
++ if (err < 0)
++ return err;
++ else if (err == 0 || etype != (EXT_RECORDED_ALLOCATED >> 30)) {
+ if (iter->pos == iter->dir->i_size) {
+ iter->elen = 0;
+ return 0;
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index c64c2eff3399a..0459a87d4c02a 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -545,6 +545,7 @@ static int udf_do_extend_file(struct inode *inode,
+ } else {
+ struct kernel_lb_addr tmploc;
+ uint32_t tmplen;
++ int8_t tmptype;
+
+ udf_write_aext(inode, last_pos, &last_ext->extLocation,
+ last_ext->extLength, 1);
+@@ -554,8 +555,12 @@ static int udf_do_extend_file(struct inode *inode,
+ * more extents, we may need to enter possible following
+ * empty indirect extent.
+ */
+- if (new_block_bytes)
+- udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0);
++ if (new_block_bytes) {
++ err = udf_next_aext(inode, last_pos, &tmploc, &tmplen,
++ &tmptype, 0);
++ if (err < 0)
++ goto out_err;
++ }
+ }
+ iinfo->i_lenExtents += add;
+
+@@ -674,8 +679,10 @@ static int udf_extend_file(struct inode *inode, loff_t newsize)
+ extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
+ } else {
+ epos.offset -= adsize;
+- etype = udf_next_aext(inode, &epos, &extent.extLocation,
+- &extent.extLength, 0);
++ err = udf_next_aext(inode, &epos, &extent.extLocation,
++ &extent.extLength, &etype, 0);
++ if (err <= 0)
++ goto out;
+ extent.extLength |= etype << 30;
+ }
+
+@@ -712,11 +719,11 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
+ loff_t lbcount = 0, b_off = 0;
+ udf_pblk_t newblocknum;
+ sector_t offset = 0;
+- int8_t etype;
++ int8_t etype, tmpetype;
+ struct udf_inode_info *iinfo = UDF_I(inode);
+ udf_pblk_t goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
+ int lastblock = 0;
+- bool isBeyondEOF;
++ bool isBeyondEOF = false;
+ int ret = 0;
+
+ prev_epos.offset = udf_file_entry_alloc_offset(inode);
+@@ -748,9 +755,13 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
+ prev_epos.offset = cur_epos.offset;
+ cur_epos.offset = next_epos.offset;
+
+- etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1);
+- if (etype == -1)
++ ret = udf_next_aext(inode, &next_epos, &eloc, &elen, &etype, 1);
++ if (ret < 0) {
++ goto out_free;
++ } else if (ret == 0) {
++ isBeyondEOF = true;
+ break;
++ }
+
+ c = !c;
+
+@@ -771,13 +782,17 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
+ * Move prev_epos and cur_epos into indirect extent if we are at
+ * the pointer to it
+ */
+- udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0);
+- udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0);
++ ret = udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, &tmpetype, 0);
++ if (ret < 0)
++ goto out_free;
++ ret = udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, &tmpetype, 0);
++ if (ret < 0)
++ goto out_free;
+
+ /* if the extent is allocated and recorded, return the block
+ if the extent is not a multiple of the blocksize, round up */
+
+- if (etype == (EXT_RECORDED_ALLOCATED >> 30)) {
++ if (!isBeyondEOF && etype == (EXT_RECORDED_ALLOCATED >> 30)) {
+ if (elen & (inode->i_sb->s_blocksize - 1)) {
+ elen = EXT_RECORDED_ALLOCATED |
+ ((elen + inode->i_sb->s_blocksize - 1) &
+@@ -793,10 +808,9 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
+ }
+
+ /* Are we beyond EOF and preallocated extent? */
+- if (etype == -1) {
++ if (isBeyondEOF) {
+ loff_t hole_len;
+
+- isBeyondEOF = true;
+ if (count) {
+ if (c)
+ laarr[0] = laarr[1];
+@@ -832,7 +846,6 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
+ endnum = c + 1;
+ lastblock = 1;
+ } else {
+- isBeyondEOF = false;
+ endnum = startnum = ((count > 2) ? 2 : count);
+
+ /* if the current extent is in position 0,
+@@ -846,15 +859,17 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map)
+
+ /* if the current block is located in an extent,
+ read the next extent */
+- etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0);
+- if (etype != -1) {
++ ret = udf_next_aext(inode, &next_epos, &eloc, &elen, &etype, 0);
++ if (ret > 0) {
+ laarr[c + 1].extLength = (etype << 30) | elen;
+ laarr[c + 1].extLocation = eloc;
+ count++;
+ startnum++;
+ endnum++;
+- } else
++ } else if (ret == 0)
+ lastblock = 1;
++ else
++ goto out_free;
+ }
+
+ /* if the current extent is not recorded but allocated, get the
+@@ -1172,6 +1187,7 @@ static int udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr,
+ int start = 0, i;
+ struct kernel_lb_addr tmploc;
+ uint32_t tmplen;
++ int8_t tmpetype;
+ int err;
+
+ if (startnum > endnum) {
+@@ -1189,14 +1205,19 @@ static int udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr,
+ */
+ if (err < 0)
+ return err;
+- udf_next_aext(inode, epos, &laarr[i].extLocation,
+- &laarr[i].extLength, 1);
++ err = udf_next_aext(inode, epos, &laarr[i].extLocation,
++ &laarr[i].extLength, &tmpetype, 1);
++ if (err < 0)
++ return err;
+ start++;
+ }
+ }
+
+ for (i = start; i < endnum; i++) {
+- udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
++ err = udf_next_aext(inode, epos, &tmploc, &tmplen, &tmpetype, 0);
++ if (err < 0)
++ return err;
++
+ udf_write_aext(inode, epos, &laarr[i].extLocation,
+ laarr[i].extLength, 1);
+ }
+@@ -2168,24 +2189,30 @@ void udf_write_aext(struct inode *inode, struct extent_position *epos,
+ */
+ #define UDF_MAX_INDIR_EXTS 16
+
+-int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
+- struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
++/*
++ * Returns 1 on success, -errno on error, 0 on hit EOF.
++ */
++int udf_next_aext(struct inode *inode, struct extent_position *epos,
++ struct kernel_lb_addr *eloc, uint32_t *elen, int8_t *etype,
++ int inc)
+ {
+- int8_t etype;
+ unsigned int indirections = 0;
+ int ret = 0;
++ udf_pblk_t block;
+
+- while ((ret = udf_current_aext(inode, epos, eloc, elen,
+- &etype, inc)) > 0) {
+- if (etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30))
+- break;
+- udf_pblk_t block;
++ while (1) {
++ ret = udf_current_aext(inode, epos, eloc, elen,
++ etype, inc);
++ if (ret <= 0)
++ return ret;
++ if (*etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30))
++ return ret;
+
+ if (++indirections > UDF_MAX_INDIR_EXTS) {
+ udf_err(inode->i_sb,
+ "too many indirect extents in inode %lu\n",
+ inode->i_ino);
+- return -1;
++ return -EFSCORRUPTED;
+ }
+
+ epos->block = *eloc;
+@@ -2195,11 +2222,9 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
+ epos->bh = sb_bread(inode->i_sb, block);
+ if (!epos->bh) {
+ udf_debug("reading block %u failed!\n", block);
+- return -1;
++ return -EIO;
+ }
+ }
+-
+- return ret > 0 ? etype : -1;
+ }
+
+ /*
+@@ -2265,20 +2290,24 @@ static int udf_insert_aext(struct inode *inode, struct extent_position epos,
+ struct kernel_lb_addr oeloc;
+ uint32_t oelen;
+ int8_t etype;
+- int err;
++ int ret;
+
+ if (epos.bh)
+ get_bh(epos.bh);
+
+- while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) {
++ while (1) {
++ ret = udf_next_aext(inode, &epos, &oeloc, &oelen, &etype, 0);
++ if (ret <= 0)
++ break;
+ udf_write_aext(inode, &epos, &neloc, nelen, 1);
+ neloc = oeloc;
+ nelen = (etype << 30) | oelen;
+ }
+- err = udf_add_aext(inode, &epos, &neloc, nelen, 1);
++ if (ret == 0)
++ ret = udf_add_aext(inode, &epos, &neloc, nelen, 1);
+ brelse(epos.bh);
+
+- return err;
++ return ret;
+ }
+
+ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
+@@ -2290,6 +2319,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
+ struct udf_inode_info *iinfo;
+ struct kernel_lb_addr eloc;
+ uint32_t elen;
++ int ret;
+
+ if (epos.bh) {
+ get_bh(epos.bh);
+@@ -2305,10 +2335,18 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
+ adsize = 0;
+
+ oepos = epos;
+- if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
++ if (udf_next_aext(inode, &epos, &eloc, &elen, &etype, 1) <= 0)
+ return -1;
+
+- while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
++ while (1) {
++ ret = udf_next_aext(inode, &epos, &eloc, &elen, &etype, 1);
++ if (ret < 0) {
++ brelse(epos.bh);
++ brelse(oepos.bh);
++ return -1;
++ }
++ if (ret == 0)
++ break;
+ udf_write_aext(inode, &oepos, &eloc, (etype << 30) | elen, 1);
+ if (oepos.bh != epos.bh) {
+ oepos.block = epos.block;
+@@ -2373,6 +2411,7 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
+ loff_t lbcount = 0, bcount = (loff_t) block << blocksize_bits;
+ int8_t etype;
+ struct udf_inode_info *iinfo;
++ int err = 0;
+
+ iinfo = UDF_I(inode);
+ if (!udf_read_extent_cache(inode, bcount, &lbcount, pos)) {
+@@ -2382,10 +2421,12 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
+ }
+ *elen = 0;
+ do {
+- etype = udf_next_aext(inode, pos, eloc, elen, 1);
+- if (etype == -1) {
+- *offset = (bcount - lbcount) >> blocksize_bits;
+- iinfo->i_lenExtents = lbcount;
++ err = udf_next_aext(inode, pos, eloc, elen, &etype, 1);
++ if (err <= 0) {
++ if (err == 0) {
++ *offset = (bcount - lbcount) >> blocksize_bits;
++ iinfo->i_lenExtents = lbcount;
++ }
+ return -1;
+ }
+ lbcount += *elen;
+diff --git a/fs/udf/super.c b/fs/udf/super.c
+index 3460ecc826d16..1c8a736b33097 100644
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -2482,13 +2482,14 @@ static unsigned int udf_count_free_table(struct super_block *sb,
+ uint32_t elen;
+ struct kernel_lb_addr eloc;
+ struct extent_position epos;
++ int8_t etype;
+
+ mutex_lock(&UDF_SB(sb)->s_alloc_mutex);
+ epos.block = UDF_I(table)->i_location;
+ epos.offset = sizeof(struct unallocSpaceEntry);
+ epos.bh = NULL;
+
+- while (udf_next_aext(table, &epos, &eloc, &elen, 1) != -1)
++ while (udf_next_aext(table, &epos, &eloc, &elen, &etype, 1) > 0)
+ accum += (elen >> table->i_sb->s_blocksize_bits);
+
+ brelse(epos.bh);
+diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
+index 4758ba7b5f51c..399958f891d14 100644
+--- a/fs/udf/truncate.c
++++ b/fs/udf/truncate.c
+@@ -69,6 +69,7 @@ void udf_truncate_tail_extent(struct inode *inode)
+ int8_t etype = -1, netype;
+ int adsize;
+ struct udf_inode_info *iinfo = UDF_I(inode);
++ int ret;
+
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ||
+ inode->i_size == iinfo->i_lenExtents)
+@@ -85,7 +86,10 @@ void udf_truncate_tail_extent(struct inode *inode)
+ BUG();
+
+ /* Find the last extent in the file */
+- while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
++ while (1) {
++ ret = udf_next_aext(inode, &epos, &eloc, &elen, &netype, 1);
++ if (ret <= 0)
++ break;
+ etype = netype;
+ lbcount += elen;
+ if (lbcount > inode->i_size) {
+@@ -101,7 +105,8 @@ void udf_truncate_tail_extent(struct inode *inode)
+ epos.offset -= adsize;
+ extent_trunc(inode, &epos, &eloc, etype, elen, nelen);
+ epos.offset += adsize;
+- if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1)
++ if (udf_next_aext(inode, &epos, &eloc, &elen,
++ &netype, 1) > 0)
+ udf_err(inode->i_sb,
+ "Extent after EOF in inode %u\n",
+ (unsigned)inode->i_ino);
+@@ -110,7 +115,8 @@ void udf_truncate_tail_extent(struct inode *inode)
+ }
+ /* This inode entry is in-memory only and thus we don't have to mark
+ * the inode dirty */
+- iinfo->i_lenExtents = inode->i_size;
++ if (ret == 0)
++ iinfo->i_lenExtents = inode->i_size;
+ brelse(epos.bh);
+ }
+
+@@ -124,6 +130,8 @@ void udf_discard_prealloc(struct inode *inode)
+ int8_t etype = -1;
+ struct udf_inode_info *iinfo = UDF_I(inode);
+ int bsize = i_blocksize(inode);
++ int8_t tmpetype = -1;
++ int ret;
+
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ||
+ ALIGN(inode->i_size, bsize) == ALIGN(iinfo->i_lenExtents, bsize))
+@@ -132,15 +140,23 @@ void udf_discard_prealloc(struct inode *inode)
+ epos.block = iinfo->i_location;
+
+ /* Find the last extent in the file */
+- while (udf_next_aext(inode, &epos, &eloc, &elen, 0) != -1) {
++ while (1) {
++ ret = udf_next_aext(inode, &epos, &eloc, &elen, &tmpetype, 0);
++ if (ret < 0)
++ goto out;
++ if (ret == 0)
++ break;
+ brelse(prev_epos.bh);
+ prev_epos = epos;
+ if (prev_epos.bh)
+ get_bh(prev_epos.bh);
+
+- etype = udf_next_aext(inode, &epos, &eloc, &elen, 1);
++ ret = udf_next_aext(inode, &epos, &eloc, &elen, &etype, 1);
++ if (ret < 0)
++ goto out;
+ lbcount += elen;
+ }
++
+ if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
+ lbcount -= elen;
+ udf_delete_aext(inode, prev_epos);
+@@ -150,6 +166,7 @@ void udf_discard_prealloc(struct inode *inode)
+ /* This inode entry is in-memory only and thus we don't have to mark
+ * the inode dirty */
+ iinfo->i_lenExtents = lbcount;
++out:
+ brelse(epos.bh);
+ brelse(prev_epos.bh);
+ }
+diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
+index d893db95ac70e..5067ed68a8b45 100644
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -169,8 +169,9 @@ extern int udf_add_aext(struct inode *, struct extent_position *,
+ extern void udf_write_aext(struct inode *, struct extent_position *,
+ struct kernel_lb_addr *, uint32_t, int);
+ extern int8_t udf_delete_aext(struct inode *, struct extent_position);
+-extern int8_t udf_next_aext(struct inode *, struct extent_position *,
+- struct kernel_lb_addr *, uint32_t *, int);
++extern int udf_next_aext(struct inode *inode, struct extent_position *epos,
++ struct kernel_lb_addr *eloc, uint32_t *elen,
++ int8_t *etype, int inc);
+ extern int udf_current_aext(struct inode *inode, struct extent_position *epos,
+ struct kernel_lb_addr *eloc, uint32_t *elen,
+ int8_t *etype, int inc);
+--
+2.43.0
+
--- /dev/null
+From 8a1a4501a7d01e4007b776292b971da0851153bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 14:01:48 +0800
+Subject: uprobe: avoid out-of-bounds memory access of fetching args
+
+From: Qiao Ma <mqaio@linux.alibaba.com>
+
+[ Upstream commit 373b9338c9722a368925d83bc622c596896b328e ]
+
+Uprobe needs to fetch args into a percpu buffer, and then copy to ring
+buffer to avoid non-atomic context problem.
+
+Sometimes user-space strings, arrays can be very large, but the size of
+percpu buffer is only page size. And store_trace_args() won't check
+whether these data exceeds a single page or not, caused out-of-bounds
+memory access.
+
+It could be reproduced by following steps:
+1. build kernel with CONFIG_KASAN enabled
+2. save follow program as test.c
+
+```
+\#include <stdio.h>
+\#include <stdlib.h>
+\#include <string.h>
+
+// If string length large than MAX_STRING_SIZE, the fetch_store_strlen()
+// will return 0, cause __get_data_size() return shorter size, and
+// store_trace_args() will not trigger out-of-bounds access.
+// So make string length less than 4096.
+\#define STRLEN 4093
+
+void generate_string(char *str, int n)
+{
+ int i;
+ for (i = 0; i < n; ++i)
+ {
+ char c = i % 26 + 'a';
+ str[i] = c;
+ }
+ str[n-1] = '\0';
+}
+
+void print_string(char *str)
+{
+ printf("%s\n", str);
+}
+
+int main()
+{
+ char tmp[STRLEN];
+
+ generate_string(tmp, STRLEN);
+ print_string(tmp);
+
+ return 0;
+}
+```
+3. compile program
+`gcc -o test test.c`
+
+4. get the offset of `print_string()`
+```
+objdump -t test | grep -w print_string
+0000000000401199 g F .text 000000000000001b print_string
+```
+
+5. configure uprobe with offset 0x1199
+```
+off=0x1199
+
+cd /sys/kernel/debug/tracing/
+echo "p /root/test:${off} arg1=+0(%di):ustring arg2=\$comm arg3=+0(%di):ustring"
+ > uprobe_events
+echo 1 > events/uprobes/enable
+echo 1 > tracing_on
+```
+
+6. run `test`, and kasan will report error.
+==================================================================
+BUG: KASAN: use-after-free in strncpy_from_user+0x1d6/0x1f0
+Write of size 8 at addr ffff88812311c004 by task test/499CPU: 0 UID: 0 PID: 499 Comm: test Not tainted 6.12.0-rc3+ #18
+Hardware name: Red Hat KVM, BIOS 1.16.0-4.al8 04/01/2014
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x55/0x70
+ print_address_description.constprop.0+0x27/0x310
+ kasan_report+0x10f/0x120
+ ? strncpy_from_user+0x1d6/0x1f0
+ strncpy_from_user+0x1d6/0x1f0
+ ? rmqueue.constprop.0+0x70d/0x2ad0
+ process_fetch_insn+0xb26/0x1470
+ ? __pfx_process_fetch_insn+0x10/0x10
+ ? _raw_spin_lock+0x85/0xe0
+ ? __pfx__raw_spin_lock+0x10/0x10
+ ? __pte_offset_map+0x1f/0x2d0
+ ? unwind_next_frame+0xc5f/0x1f80
+ ? arch_stack_walk+0x68/0xf0
+ ? is_bpf_text_address+0x23/0x30
+ ? kernel_text_address.part.0+0xbb/0xd0
+ ? __kernel_text_address+0x66/0xb0
+ ? unwind_get_return_address+0x5e/0xa0
+ ? __pfx_stack_trace_consume_entry+0x10/0x10
+ ? arch_stack_walk+0xa2/0xf0
+ ? _raw_spin_lock_irqsave+0x8b/0xf0
+ ? __pfx__raw_spin_lock_irqsave+0x10/0x10
+ ? depot_alloc_stack+0x4c/0x1f0
+ ? _raw_spin_unlock_irqrestore+0xe/0x30
+ ? stack_depot_save_flags+0x35d/0x4f0
+ ? kasan_save_stack+0x34/0x50
+ ? kasan_save_stack+0x24/0x50
+ ? mutex_lock+0x91/0xe0
+ ? __pfx_mutex_lock+0x10/0x10
+ prepare_uprobe_buffer.part.0+0x2cd/0x500
+ uprobe_dispatcher+0x2c3/0x6a0
+ ? __pfx_uprobe_dispatcher+0x10/0x10
+ ? __kasan_slab_alloc+0x4d/0x90
+ handler_chain+0xdd/0x3e0
+ handle_swbp+0x26e/0x3d0
+ ? __pfx_handle_swbp+0x10/0x10
+ ? uprobe_pre_sstep_notifier+0x151/0x1b0
+ irqentry_exit_to_user_mode+0xe2/0x1b0
+ asm_exc_int3+0x39/0x40
+RIP: 0033:0x401199
+Code: 01 c2 0f b6 45 fb 88 02 83 45 fc 01 8b 45 fc 3b 45 e4 7c b7 8b 45 e4 48 98 48 8d 50 ff 48 8b 45 e8 48 01 d0 ce
+RSP: 002b:00007ffdf00576a8 EFLAGS: 00000206
+RAX: 00007ffdf00576b0 RBX: 0000000000000000 RCX: 0000000000000ff2
+RDX: 0000000000000ffc RSI: 0000000000000ffd RDI: 00007ffdf00576b0
+RBP: 00007ffdf00586b0 R08: 00007feb2f9c0d20 R09: 00007feb2f9c0d20
+R10: 0000000000000001 R11: 0000000000000202 R12: 0000000000401040
+R13: 00007ffdf0058780 R14: 0000000000000000 R15: 0000000000000000
+ </TASK>
+
+This commit enforces the buffer's maxlen less than a page-size to avoid
+store_trace_args() out-of-memory access.
+
+Link: https://lore.kernel.org/all/20241015060148.1108331-1-mqaio@linux.alibaba.com/
+
+Fixes: dcad1a204f72 ("tracing/uprobes: Fetch args before reserving a ring buffer")
+Signed-off-by: Qiao Ma <mqaio@linux.alibaba.com>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_uprobe.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
+index c98e3b3386bad..2c30d948e733c 100644
+--- a/kernel/trace/trace_uprobe.c
++++ b/kernel/trace/trace_uprobe.c
+@@ -858,6 +858,7 @@ struct uprobe_cpu_buffer {
+ };
+ static struct uprobe_cpu_buffer __percpu *uprobe_cpu_buffer;
+ static int uprobe_buffer_refcnt;
++#define MAX_UCB_BUFFER_SIZE PAGE_SIZE
+
+ static int uprobe_buffer_init(void)
+ {
+@@ -962,6 +963,11 @@ static struct uprobe_cpu_buffer *prepare_uprobe_buffer(struct trace_uprobe *tu,
+ ucb = uprobe_buffer_get();
+ ucb->dsize = tu->tp.size + dsize;
+
++ if (WARN_ON_ONCE(ucb->dsize > MAX_UCB_BUFFER_SIZE)) {
++ ucb->dsize = MAX_UCB_BUFFER_SIZE;
++ dsize = MAX_UCB_BUFFER_SIZE - tu->tp.size;
++ }
++
+ store_trace_args(ucb->buf, &tu->tp, regs, NULL, esize, dsize);
+
+ *ucbp = ucb;
+@@ -981,9 +987,6 @@ static void __uprobe_trace_func(struct trace_uprobe *tu,
+
+ WARN_ON(call != trace_file->event_call);
+
+- if (WARN_ON_ONCE(ucb->dsize > PAGE_SIZE))
+- return;
+-
+ if (trace_trigger_soft_disabled(trace_file))
+ return;
+
+--
+2.43.0
+