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-hdegoed... 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 */
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@yaho... 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 = {
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 },
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... 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)
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
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; }
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 */
From: Jaroslav Kysela perex@perex.cz
[ Upstream commit df5215618fbe425875336d3a2d31bd599ae8c401 ]
When the trigger_tstamp_latched flag is set, the PCM core code assumes that the low-level driver handles the trigger timestamping itself. Ensure that runtime->trigger_tstamp is always updated.
Buglink: https://github.com/alsa-project/alsa-lib/issues/387 Reported-by: Zeno Endemann zeno.endemann@mailbox.org Signed-off-by: Jaroslav Kysela perex@perex.cz Link: https://patch.msgid.link/20241002081306.1788405-1-perex@perex.cz Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- include/sound/hdaudio.h | 2 +- sound/hda/hdac_stream.c | 6 +++++- sound/pci/hda/hda_controller.c | 3 +-- 3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 7e39d486374a6..b098ceadbe74b 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -590,7 +590,7 @@ void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, unsigned int streams); void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, - unsigned int streams); + unsigned int streams, bool start); int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, struct snd_pcm_substream *substream);
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index b53de020309f2..0411a8fe9d6f1 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -664,7 +664,7 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev, * updated accordingly, too. */ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, - unsigned int streams) + unsigned int streams, bool start) { struct hdac_bus *bus = azx_dev->bus; struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; @@ -672,6 +672,9 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, bool inited = false; u64 cycle_last = 0;
+ if (!start) + goto skip; + list_for_each_entry(s, &bus->stream_list, list) { if ((streams & (1 << s->index))) { azx_timecounter_init(s, inited, cycle_last); @@ -682,6 +685,7 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, } }
+skip: snd_pcm_gettime(runtime, &runtime->trigger_tstamp); runtime->trigger_tstamp_latched = true; } diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 5d86e5a9c814a..f3330b7e0fcfc 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -275,8 +275,7 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock(&bus->reg_lock); /* reset SYNC bits */ snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg); - if (start) - snd_hdac_stream_timecounter_init(hstr, sbits); + snd_hdac_stream_timecounter_init(hstr, sbits, start); spin_unlock(&bus->reg_lock); return 0; }
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);
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);
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) {
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"}, {} };
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=UuamXczr1mKBD6xtj2dyYK... 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); }
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-gustav... (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 {
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",
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;
linux-stable-mirror@lists.linaro.org