From: Sasha Levin Date: Thu, 15 Aug 2024 12:20:06 +0000 (-0400) Subject: Fixes for 6.10 X-Git-Tag: v4.19.320~31 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c17b20fe3e5409035cd1aba306ac3c0a13548c09;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.10 Signed-off-by: Sasha Levin --- diff --git a/queue-6.10/alsa-usb-fix-ubsan-warning-in-parse_audio_unit.patch b/queue-6.10/alsa-usb-fix-ubsan-warning-in-parse_audio_unit.patch new file mode 100644 index 00000000000..6ea0981d841 --- /dev/null +++ b/queue-6.10/alsa-usb-fix-ubsan-warning-in-parse_audio_unit.patch @@ -0,0 +1,47 @@ +From a447cb43aea510ec7f711ec1a13033f7f6ec80f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jul 2024 14:35:54 +0200 +Subject: ALSA: usb: Fix UBSAN warning in parse_audio_unit() + +From: Takashi Iwai + +[ Upstream commit 2f38cf730caedaeacdefb7ff35b0a3c1168117f9 ] + +A malformed USB descriptor may pass the lengthy mixer description with +a lot of channels, and this may overflow the 32bit integer shift +size, as caught by syzbot UBSAN test. Although this won't cause any +real trouble, it's better to address. + +This patch introduces a sanity check of the number of channels to bail +out the parsing when too many channels are found. + +Reported-by: syzbot+78d5b129a762182225aa@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/0000000000000adac5061d3c7355@google.com +Link: https://patch.msgid.link/20240715123619.26612-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/mixer.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index d1bdb0b93bda0..8cc2d4937f340 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -2021,6 +2021,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, + bmaControls = ftr->bmaControls; + } + ++ if (channels > 32) { ++ usb_audio_info(state->chip, ++ "usbmixer: too many channels (%d) in unit %d\n", ++ channels, unitid); ++ return -EINVAL; ++ } ++ + /* parse the source unit */ + err = parse_audio_unit(state, hdr->bSourceID); + if (err < 0) +-- +2.43.0 + diff --git a/queue-6.10/binfmt_flat-fix-corruption-when-not-offsetting-data-.patch b/queue-6.10/binfmt_flat-fix-corruption-when-not-offsetting-data-.patch new file mode 100644 index 00000000000..cf4d8e18c37 --- /dev/null +++ b/queue-6.10/binfmt_flat-fix-corruption-when-not-offsetting-data-.patch @@ -0,0 +1,60 @@ +From 1612dd4b10b05d4a6a2a3d680d773f3c526f739f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Aug 2024 12:51:23 -0700 +Subject: binfmt_flat: Fix corruption when not offsetting data start + +From: Kees Cook + +[ Upstream commit 3eb3cd5992f7a0c37edc8d05b4c38c98758d8671 ] + +Commit 04d82a6d0881 ("binfmt_flat: allow not offsetting data start") +introduced a RISC-V specific variant of the FLAT format which does +not allocate any space for the (obsolete) array of shared library +pointers. However, it did not disable the code which initializes the +array, resulting in the corruption of sizeof(long) bytes before the DATA +segment, generally the end of the TEXT segment. + +Introduce MAX_SHARED_LIBS_UPDATE which depends on the state of +CONFIG_BINFMT_FLAT_NO_DATA_START_OFFSET to guard the initialization of +the shared library pointer region so that it will only be initialized +if space is reserved for it. + +Fixes: 04d82a6d0881 ("binfmt_flat: allow not offsetting data start") +Co-developed-by: Stefan O'Rear +Signed-off-by: Stefan O'Rear +Reviewed-by: Damien Le Moal +Acked-by: Greg Ungerer +Link: https://lore.kernel.org/r/20240807195119.it.782-kees@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + fs/binfmt_flat.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c +index c26545d71d39a..cd6d5bbb4b9df 100644 +--- a/fs/binfmt_flat.c ++++ b/fs/binfmt_flat.c +@@ -72,8 +72,10 @@ + + #ifdef CONFIG_BINFMT_FLAT_NO_DATA_START_OFFSET + #define DATA_START_OFFSET_WORDS (0) ++#define MAX_SHARED_LIBS_UPDATE (0) + #else + #define DATA_START_OFFSET_WORDS (MAX_SHARED_LIBS) ++#define MAX_SHARED_LIBS_UPDATE (MAX_SHARED_LIBS) + #endif + + struct lib_info { +@@ -880,7 +882,7 @@ static int load_flat_binary(struct linux_binprm *bprm) + return res; + + /* Update data segment pointers for all libraries */ +- for (i = 0; i < MAX_SHARED_LIBS; i++) { ++ for (i = 0; i < MAX_SHARED_LIBS_UPDATE; i++) { + if (!libinfo.lib_list[i].loaded) + continue; + for (j = 0; j < MAX_SHARED_LIBS; j++) { +-- +2.43.0 + diff --git a/queue-6.10/bpf-net-use-dev_stat_inc.patch b/queue-6.10/bpf-net-use-dev_stat_inc.patch new file mode 100644 index 00000000000..b84cb64af6d --- /dev/null +++ b/queue-6.10/bpf-net-use-dev_stat_inc.patch @@ -0,0 +1,59 @@ +From 51aa39d0cb00ec1e0ad99eb91336707219092827 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 May 2024 11:35:20 +0800 +Subject: bpf, net: Use DEV_STAT_INC() + +From: yunshui + +[ Upstream commit d9cbd8343b010016fcaabc361c37720dcafddcbe ] + +syzbot/KCSAN reported that races happen when multiple CPUs updating +dev->stats.tx_error concurrently. Adopt SMP safe DEV_STATS_INC() to +update the dev->stats fields. + +Reported-by: syzbot +Signed-off-by: yunshui +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20240523033520.4029314-1-jiangyunshui@kylinos.cn +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 110692c1dd95a..ab0455c64e49a 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2279,12 +2279,12 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev, + + err = bpf_out_neigh_v6(net, skb, dev, nh); + if (unlikely(net_xmit_eval(err))) +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + else + ret = NET_XMIT_SUCCESS; + goto out_xmit; + out_drop: +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + kfree_skb(skb); + out_xmit: + return ret; +@@ -2385,12 +2385,12 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev, + + err = bpf_out_neigh_v4(net, skb, dev, nh); + if (unlikely(net_xmit_eval(err))) +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + else + ret = NET_XMIT_SUCCESS; + goto out_xmit; + out_drop: +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + kfree_skb(skb); + out_xmit: + return ret; +-- +2.43.0 + diff --git a/queue-6.10/f2fs-fix-to-cover-read-extent-cache-access-with-lock.patch b/queue-6.10/f2fs-fix-to-cover-read-extent-cache-access-with-lock.patch new file mode 100644 index 00000000000..22724aa1d2d --- /dev/null +++ b/queue-6.10/f2fs-fix-to-cover-read-extent-cache-access-with-lock.patch @@ -0,0 +1,202 @@ +From 78caa2d7a15821eb2a8a35c482d6ea174cbe777d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 May 2024 10:00:32 +0800 +Subject: f2fs: fix to cover read extent cache access with lock + +From: Chao Yu + +[ Upstream commit d7409b05a64f212735f0d33f5f1602051a886eab ] + +syzbot reports a f2fs bug as below: + +BUG: KASAN: slab-use-after-free in sanity_check_extent_cache+0x370/0x410 fs/f2fs/extent_cache.c:46 +Read of size 4 at addr ffff8880739ab220 by task syz-executor200/5097 + +CPU: 0 PID: 5097 Comm: syz-executor200 Not tainted 6.9.0-rc6-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x241/0x360 lib/dump_stack.c:114 + print_address_description mm/kasan/report.c:377 [inline] + print_report+0x169/0x550 mm/kasan/report.c:488 + kasan_report+0x143/0x180 mm/kasan/report.c:601 + sanity_check_extent_cache+0x370/0x410 fs/f2fs/extent_cache.c:46 + do_read_inode fs/f2fs/inode.c:509 [inline] + f2fs_iget+0x33e1/0x46e0 fs/f2fs/inode.c:560 + f2fs_nfs_get_inode+0x74/0x100 fs/f2fs/super.c:3237 + generic_fh_to_dentry+0x9f/0xf0 fs/libfs.c:1413 + exportfs_decode_fh_raw+0x152/0x5f0 fs/exportfs/expfs.c:444 + exportfs_decode_fh+0x3c/0x80 fs/exportfs/expfs.c:584 + do_handle_to_path fs/fhandle.c:155 [inline] + handle_to_path fs/fhandle.c:210 [inline] + do_handle_open+0x495/0x650 fs/fhandle.c:226 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf5/0x240 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +We missed to cover sanity_check_extent_cache() w/ extent cache lock, +so, below race case may happen, result in use after free issue. + +- f2fs_iget + - do_read_inode + - f2fs_init_read_extent_tree + : add largest extent entry in to cache + - shrink + - f2fs_shrink_read_extent_tree + - __shrink_extent_tree + - __detach_extent_node + : drop largest extent entry + - sanity_check_extent_cache + : access et->largest w/o lock + +let's refactor sanity_check_extent_cache() to avoid extent cache access +and call it before f2fs_init_read_extent_tree() to fix this issue. + +Reported-by: syzbot+74ebe2104433e9dc610d@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-f2fs-devel/00000000000009beea061740a531@google.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/extent_cache.c | 48 +++++++++++++++++------------------------- + fs/f2fs/f2fs.h | 2 +- + fs/f2fs/inode.c | 10 ++++----- + 3 files changed, 25 insertions(+), 35 deletions(-) + +diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c +index 48048fa364276..fd1fc06359eea 100644 +--- a/fs/f2fs/extent_cache.c ++++ b/fs/f2fs/extent_cache.c +@@ -19,33 +19,23 @@ + #include "node.h" + #include + +-bool sanity_check_extent_cache(struct inode *inode) ++bool sanity_check_extent_cache(struct inode *inode, struct page *ipage) + { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); +- struct f2fs_inode_info *fi = F2FS_I(inode); +- struct extent_tree *et = fi->extent_tree[EX_READ]; +- struct extent_info *ei; +- +- if (!et) +- return true; ++ struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext; ++ struct extent_info ei; + +- ei = &et->largest; +- if (!ei->len) +- return true; ++ get_read_extent_info(&ei, i_ext); + +- /* Let's drop, if checkpoint got corrupted. */ +- if (is_set_ckpt_flags(sbi, CP_ERROR_FLAG)) { +- ei->len = 0; +- et->largest_updated = true; ++ if (!ei.len) + return true; +- } + +- if (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC_ENHANCE) || +- !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1, ++ if (!f2fs_is_valid_blkaddr(sbi, ei.blk, DATA_GENERIC_ENHANCE) || ++ !f2fs_is_valid_blkaddr(sbi, ei.blk + ei.len - 1, + DATA_GENERIC_ENHANCE)) { + f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix", + __func__, inode->i_ino, +- ei->blk, ei->fofs, ei->len); ++ ei.blk, ei.fofs, ei.len); + return false; + } + return true; +@@ -394,24 +384,22 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) + + if (!__may_extent_tree(inode, EX_READ)) { + /* drop largest read extent */ +- if (i_ext && i_ext->len) { ++ if (i_ext->len) { + f2fs_wait_on_page_writeback(ipage, NODE, true, true); + i_ext->len = 0; + set_page_dirty(ipage); + } +- goto out; ++ set_inode_flag(inode, FI_NO_EXTENT); ++ return; + } + + et = __grab_extent_tree(inode, EX_READ); + +- if (!i_ext || !i_ext->len) +- goto out; +- + get_read_extent_info(&ei, i_ext); + + write_lock(&et->lock); +- if (atomic_read(&et->node_cnt)) +- goto unlock_out; ++ if (atomic_read(&et->node_cnt) || !ei.len) ++ goto skip; + + en = __attach_extent_node(sbi, et, &ei, NULL, + &et->root.rb_root.rb_node, true); +@@ -423,11 +411,13 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) + list_add_tail(&en->list, &eti->extent_list); + spin_unlock(&eti->extent_lock); + } +-unlock_out: ++skip: ++ /* Let's drop, if checkpoint got corrupted. */ ++ if (f2fs_cp_error(sbi)) { ++ et->largest.len = 0; ++ et->largest_updated = true; ++ } + write_unlock(&et->lock); +-out: +- if (!F2FS_I(inode)->extent_tree[EX_READ]) +- set_inode_flag(inode, FI_NO_EXTENT); + } + + void f2fs_init_age_extent_tree(struct inode *inode) +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 66680159a2968..5556ab491368d 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -4195,7 +4195,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); + /* + * extent_cache.c + */ +-bool sanity_check_extent_cache(struct inode *inode); ++bool sanity_check_extent_cache(struct inode *inode, struct page *ipage); + void f2fs_init_extent_tree(struct inode *inode); + void f2fs_drop_extent_tree(struct inode *inode); + void f2fs_destroy_extent_node(struct inode *inode); +diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c +index c6b55aedc2762..ed629dabbfda4 100644 +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -511,16 +511,16 @@ static int do_read_inode(struct inode *inode) + + init_idisk_time(inode); + +- /* Need all the flag bits */ +- f2fs_init_read_extent_tree(inode, node_page); +- f2fs_init_age_extent_tree(inode); +- +- if (!sanity_check_extent_cache(inode)) { ++ if (!sanity_check_extent_cache(inode, node_page)) { + f2fs_put_page(node_page, 1); + f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE); + return -EFSCORRUPTED; + } + ++ /* Need all the flag bits */ ++ f2fs_init_read_extent_tree(inode, node_page); ++ f2fs_init_age_extent_tree(inode); ++ + f2fs_put_page(node_page, 1); + + stat_inc_inline_xattr(inode); +-- +2.43.0 + diff --git a/queue-6.10/f2fs-fix-to-do-sanity-check-on-f2fs_inline_data-flag.patch b/queue-6.10/f2fs-fix-to-do-sanity-check-on-f2fs_inline_data-flag.patch new file mode 100644 index 00000000000..dfe035073ed --- /dev/null +++ b/queue-6.10/f2fs-fix-to-do-sanity-check-on-f2fs_inline_data-flag.patch @@ -0,0 +1,76 @@ +From 42c0cc4157cc98d33a138d48f61ead55a56f0e61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 14:23:17 +0800 +Subject: f2fs: fix to do sanity check on F2FS_INLINE_DATA flag in inode during + GC + +From: Chao Yu + +[ Upstream commit fc01008c92f40015aeeced94750855a7111b6929 ] + +syzbot reports a f2fs bug as below: + +------------[ cut here ]------------ +kernel BUG at fs/f2fs/inline.c:258! +CPU: 1 PID: 34 Comm: kworker/u8:2 Not tainted 6.9.0-rc6-syzkaller-00012-g9e4bc4bcae01 #0 +RIP: 0010:f2fs_write_inline_data+0x781/0x790 fs/f2fs/inline.c:258 +Call Trace: + f2fs_write_single_data_page+0xb65/0x1d60 fs/f2fs/data.c:2834 + f2fs_write_cache_pages fs/f2fs/data.c:3133 [inline] + __f2fs_write_data_pages fs/f2fs/data.c:3288 [inline] + f2fs_write_data_pages+0x1efe/0x3a90 fs/f2fs/data.c:3315 + do_writepages+0x35b/0x870 mm/page-writeback.c:2612 + __writeback_single_inode+0x165/0x10b0 fs/fs-writeback.c:1650 + writeback_sb_inodes+0x905/0x1260 fs/fs-writeback.c:1941 + wb_writeback+0x457/0xce0 fs/fs-writeback.c:2117 + wb_do_writeback fs/fs-writeback.c:2264 [inline] + wb_workfn+0x410/0x1090 fs/fs-writeback.c:2304 + process_one_work kernel/workqueue.c:3254 [inline] + process_scheduled_works+0xa12/0x17c0 kernel/workqueue.c:3335 + worker_thread+0x86d/0xd70 kernel/workqueue.c:3416 + kthread+0x2f2/0x390 kernel/kthread.c:388 + ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + +The root cause is: inline_data inode can be fuzzed, so that there may +be valid blkaddr in its direct node, once f2fs triggers background GC +to migrate the block, it will hit f2fs_bug_on() during dirty page +writeback. + +Let's add sanity check on F2FS_INLINE_DATA flag in inode during GC, +so that, it can forbid migrating inline_data inode's data block for +fixing. + +Reported-by: syzbot+848062ba19c8782ca5c8@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-f2fs-devel/000000000000d103ce06174d7ec3@google.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/gc.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index b2951cd930d80..448c75e80b89e 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1566,6 +1566,16 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + continue; + } + ++ if (f2fs_has_inline_data(inode)) { ++ iput(inode); ++ set_sbi_flag(sbi, SBI_NEED_FSCK); ++ f2fs_err_ratelimited(sbi, ++ "inode %lx has both inline_data flag and " ++ "data block, nid=%u, ofs_in_node=%u", ++ inode->i_ino, dni.nid, ofs_in_node); ++ continue; ++ } ++ + err = f2fs_gc_pinned_control(inode, gc_type, segno); + if (err == -EAGAIN) { + iput(inode); +-- +2.43.0 + diff --git a/queue-6.10/fou-remove-warn-in-gue_gro_receive-on-unsupported-pr.patch b/queue-6.10/fou-remove-warn-in-gue_gro_receive-on-unsupported-pr.patch new file mode 100644 index 00000000000..73ac69e19f9 --- /dev/null +++ b/queue-6.10/fou-remove-warn-in-gue_gro_receive-on-unsupported-pr.patch @@ -0,0 +1,46 @@ +From f3766b6c12b0073b87f3ef4b3c6be9690df4160b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Jun 2024 08:25:18 -0400 +Subject: fou: remove warn in gue_gro_receive on unsupported protocol + +From: Willem de Bruijn + +[ Upstream commit dd89a81d850fa9a65f67b4527c0e420d15bf836c ] + +Drop the WARN_ON_ONCE inn gue_gro_receive if the encapsulated type is +not known or does not have a GRO handler. + +Such a packet is easily constructed. Syzbot generates them and sets +off this warning. + +Remove the warning as it is expected and not actionable. + +The warning was previously reduced from WARN_ON to WARN_ON_ONCE in +commit 270136613bf7 ("fou: Do WARN_ON_ONCE in gue_gro_receive for bad +proto callbacks"). + +Signed-off-by: Willem de Bruijn +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20240614122552.1649044-1-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/fou_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/fou_core.c b/net/ipv4/fou_core.c +index a8494f796dca3..0abbc413e0fe5 100644 +--- a/net/ipv4/fou_core.c ++++ b/net/ipv4/fou_core.c +@@ -433,7 +433,7 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, + + offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; + ops = rcu_dereference(offloads[proto]); +- if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) ++ if (!ops || !ops->callbacks.gro_receive) + goto out; + + pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); +-- +2.43.0 + diff --git a/queue-6.10/fs-ntfs3-do-copy_to_user-out-of-run_lock.patch b/queue-6.10/fs-ntfs3-do-copy_to_user-out-of-run_lock.patch new file mode 100644 index 00000000000..8abd4a98d3d --- /dev/null +++ b/queue-6.10/fs-ntfs3-do-copy_to_user-out-of-run_lock.patch @@ -0,0 +1,145 @@ +From 710c1ae591558dfd8f8c3728e8165fa0040ac5d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Jun 2024 15:14:07 +0300 +Subject: fs/ntfs3: Do copy_to_user out of run_lock + +From: Konstantin Komarov + +[ Upstream commit d57431c6f511bf020e474026d9f3123d7bfbea8c ] + +In order not to call copy_to_user (from fiemap_fill_next_extent) +we allocate memory in the kernel, fill it and copy it to user memory +after up_read(run_lock). + +Reported-by: syzbot+36bb70085ef6edc2ebb9@syzkaller.appspotmail.com +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/frecord.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 72 insertions(+), 3 deletions(-) + +diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c +index 4822cfd6351c2..ded451a84b773 100644 +--- a/fs/ntfs3/frecord.c ++++ b/fs/ntfs3/frecord.c +@@ -1896,6 +1896,47 @@ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr, + return REPARSE_LINK; + } + ++/* ++ * fiemap_fill_next_extent_k - a copy of fiemap_fill_next_extent ++ * but it accepts kernel address for fi_extents_start ++ */ ++static int fiemap_fill_next_extent_k(struct fiemap_extent_info *fieinfo, ++ u64 logical, u64 phys, u64 len, u32 flags) ++{ ++ struct fiemap_extent extent; ++ struct fiemap_extent __user *dest = fieinfo->fi_extents_start; ++ ++ /* only count the extents */ ++ if (fieinfo->fi_extents_max == 0) { ++ fieinfo->fi_extents_mapped++; ++ return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0; ++ } ++ ++ if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max) ++ return 1; ++ ++ if (flags & FIEMAP_EXTENT_DELALLOC) ++ flags |= FIEMAP_EXTENT_UNKNOWN; ++ if (flags & FIEMAP_EXTENT_DATA_ENCRYPTED) ++ flags |= FIEMAP_EXTENT_ENCODED; ++ if (flags & (FIEMAP_EXTENT_DATA_TAIL | FIEMAP_EXTENT_DATA_INLINE)) ++ flags |= FIEMAP_EXTENT_NOT_ALIGNED; ++ ++ memset(&extent, 0, sizeof(extent)); ++ extent.fe_logical = logical; ++ extent.fe_physical = phys; ++ extent.fe_length = len; ++ extent.fe_flags = flags; ++ ++ dest += fieinfo->fi_extents_mapped; ++ memcpy(dest, &extent, sizeof(extent)); ++ ++ fieinfo->fi_extents_mapped++; ++ if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max) ++ return 1; ++ return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0; ++} ++ + /* + * ni_fiemap - Helper for file_fiemap(). + * +@@ -1906,6 +1947,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + __u64 vbo, __u64 len) + { + int err = 0; ++ struct fiemap_extent __user *fe_u = fieinfo->fi_extents_start; ++ struct fiemap_extent *fe_k = NULL; + struct ntfs_sb_info *sbi = ni->mi.sbi; + u8 cluster_bits = sbi->cluster_bits; + struct runs_tree *run; +@@ -1953,6 +1996,18 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + goto out; + } + ++ /* ++ * To avoid lock problems replace pointer to user memory by pointer to kernel memory. ++ */ ++ fe_k = kmalloc_array(fieinfo->fi_extents_max, ++ sizeof(struct fiemap_extent), ++ GFP_NOFS | __GFP_ZERO); ++ if (!fe_k) { ++ err = -ENOMEM; ++ goto out; ++ } ++ fieinfo->fi_extents_start = fe_k; ++ + end = vbo + len; + alloc_size = le64_to_cpu(attr->nres.alloc_size); + if (end > alloc_size) +@@ -2041,8 +2096,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + if (vbo + dlen >= end) + flags |= FIEMAP_EXTENT_LAST; + +- err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen, +- flags); ++ err = fiemap_fill_next_extent_k(fieinfo, vbo, lbo, dlen, ++ flags); ++ + if (err < 0) + break; + if (err == 1) { +@@ -2062,7 +2118,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + if (vbo + bytes >= end) + flags |= FIEMAP_EXTENT_LAST; + +- err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags); ++ err = fiemap_fill_next_extent_k(fieinfo, vbo, lbo, bytes, ++ flags); + if (err < 0) + break; + if (err == 1) { +@@ -2075,7 +2132,19 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + + up_read(run_lock); + ++ /* ++ * Copy to user memory out of lock ++ */ ++ if (copy_to_user(fe_u, fe_k, ++ fieinfo->fi_extents_max * ++ sizeof(struct fiemap_extent))) { ++ err = -EFAULT; ++ } ++ + out: ++ /* Restore original pointer. */ ++ fieinfo->fi_extents_start = fe_u; ++ kfree(fe_k); + return err; + } + +-- +2.43.0 + diff --git a/queue-6.10/jfs-fix-null-ptr-deref-in-dtinsertentry.patch b/queue-6.10/jfs-fix-null-ptr-deref-in-dtinsertentry.patch new file mode 100644 index 00000000000..9f3a0c60316 --- /dev/null +++ b/queue-6.10/jfs-fix-null-ptr-deref-in-dtinsertentry.patch @@ -0,0 +1,51 @@ +From 15cc64095bcbdf6a8e92248a8b6a679495b295ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Apr 2024 20:05:28 +0800 +Subject: jfs: fix null ptr deref in dtInsertEntry + +From: Edward Adam Davis + +[ Upstream commit ce6dede912f064a855acf6f04a04cbb2c25b8c8c ] + +[syzbot reported] +general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN PTI +KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] +CPU: 0 PID: 5061 Comm: syz-executor404 Not tainted 6.8.0-syzkaller-08951-gfe46a7dd189e #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 +RIP: 0010:dtInsertEntry+0xd0c/0x1780 fs/jfs/jfs_dtree.c:3713 +... +[Analyze] +In dtInsertEntry(), when the pointer h has the same value as p, after writing +name in UniStrncpy_to_le(), p->header.flag will be cleared. This will cause the +previously true judgment "p->header.flag & BT-LEAF" to change to no after writing +the name operation, this leads to entering an incorrect branch and accessing the +uninitialized object ih when judging this condition for the second time. + +[Fix] +After got the page, check freelist first, if freelist == 0 then exit dtInsert() +and return -EINVAL. + +Reported-by: syzbot+bba84aef3a26fb93deb9@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/jfs_dtree.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c +index 031d8f570f581..5d3127ca68a42 100644 +--- a/fs/jfs/jfs_dtree.c ++++ b/fs/jfs/jfs_dtree.c +@@ -834,6 +834,8 @@ int dtInsert(tid_t tid, struct inode *ip, + * the full page. + */ + DT_GETSEARCH(ip, btstack->top, bn, mp, p, index); ++ if (p->header.freelist == 0) ++ return -EINVAL; + + /* + * insert entry for new key +-- +2.43.0 + diff --git a/queue-6.10/jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch b/queue-6.10/jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch new file mode 100644 index 00000000000..b2c56f3a944 --- /dev/null +++ b/queue-6.10/jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch @@ -0,0 +1,40 @@ +From 3c75936d660549f159306ab0b06ede433bb4ad7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jun 2024 09:42:05 -0700 +Subject: jfs: Fix shift-out-of-bounds in dbDiscardAG + +From: Pei Li + +[ Upstream commit 7063b80268e2593e58bee8a8d709c2f3ff93e2f2 ] + +When searching for the next smaller log2 block, BLKSTOL2() returned 0, +causing shift exponent -1 to be negative. + +This patch fixes the issue by exiting the loop directly when negative +shift is found. + +Reported-by: syzbot+61be3359d2ee3467e7e4@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=61be3359d2ee3467e7e4 +Signed-off-by: Pei Li +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/jfs_dmap.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c +index cb3cda1390adb..5713994328cbc 100644 +--- a/fs/jfs/jfs_dmap.c ++++ b/fs/jfs/jfs_dmap.c +@@ -1626,6 +1626,8 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) + } else if (rc == -ENOSPC) { + /* search for next smaller log2 block */ + l2nb = BLKSTOL2(nblocks) - 1; ++ if (unlikely(l2nb < 0)) ++ break; + nblocks = 1LL << l2nb; + } else { + /* Trim any already allocated blocks */ +-- +2.43.0 + diff --git a/queue-6.10/platform-x86-amd-pmf-fix-to-update-hpd-data-when-als.patch b/queue-6.10/platform-x86-amd-pmf-fix-to-update-hpd-data-when-als.patch new file mode 100644 index 00000000000..04aa76cbab4 --- /dev/null +++ b/queue-6.10/platform-x86-amd-pmf-fix-to-update-hpd-data-when-als.patch @@ -0,0 +1,95 @@ +From 51a857f342d92fef3fdf3f43e0c302985c82c24d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jul 2024 19:53:16 +0530 +Subject: platform/x86/amd/pmf: Fix to Update HPD Data When ALS is Disabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shyam Sundar S K + +[ Upstream commit 78296429e20052b029211b0aca64aadc5052d581 ] + +If the Ambient Light Sensor (ALS) is disabled, the current code in the PMF +driver does not query for Human Presence Detection (HPD) data in +amd_pmf_get_sensor_info(). As a result, stale HPD data is used by PMF-TA +to evaluate policy conditions, leading to unexpected behavior in the policy +output actions. + +To resolve this issue, modify the PMF driver to query HPD data +independently of ALS. + +Since user_present is a boolean, modify the current code to return true if +the user is present and false if the user is away or if the sensor is not +detected, and report this status to the PMF TA firmware accordingly. + +With this change, amd_pmf_get_sensor_info() now returns void instead of +int. + +Fixes: cedecdba60f4 ("platform/x86/amd/pmf: Get ambient light information from AMD SFH driver") +Co-developed-by: Patil Rajesh Reddy +Signed-off-by: Patil Rajesh Reddy +Signed-off-by: Shyam Sundar S K +Link: https://lore.kernel.org/r/20240730142316.3846259-1-Shyam-sundar.S-k@amd.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/amd/pmf/spc.c | 32 ++++++++++-------------------- + 1 file changed, 11 insertions(+), 21 deletions(-) + +diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c +index a3dec14c30043..3c153fb1425e9 100644 +--- a/drivers/platform/x86/amd/pmf/spc.c ++++ b/drivers/platform/x86/amd/pmf/spc.c +@@ -150,36 +150,26 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_ + return 0; + } + +-static int amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) ++static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) + { + struct amd_sfh_info sfh_info; +- int ret; ++ ++ /* Get the latest information from SFH */ ++ in->ev_info.user_present = false; + + /* Get ALS data */ +- ret = amd_get_sfh_info(&sfh_info, MT_ALS); +- if (!ret) ++ if (!amd_get_sfh_info(&sfh_info, MT_ALS)) + in->ev_info.ambient_light = sfh_info.ambient_light; + else +- return ret; ++ dev_dbg(dev->dev, "ALS is not enabled/detected\n"); + + /* get HPD data */ +- ret = amd_get_sfh_info(&sfh_info, MT_HPD); +- if (ret) +- return ret; +- +- switch (sfh_info.user_present) { +- case SFH_NOT_DETECTED: +- in->ev_info.user_present = 0xff; /* assume no sensors connected */ +- break; +- case SFH_USER_PRESENT: +- in->ev_info.user_present = 1; +- break; +- case SFH_USER_AWAY: +- in->ev_info.user_present = 0; +- break; ++ if (!amd_get_sfh_info(&sfh_info, MT_HPD)) { ++ if (sfh_info.user_present == SFH_USER_PRESENT) ++ in->ev_info.user_present = true; ++ } else { ++ dev_dbg(dev->dev, "HPD is not enabled/detected\n"); + } +- +- return 0; + } + + void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) +-- +2.43.0 + diff --git a/queue-6.10/platform-x86-ideapad-laptop-add-a-mutex-to-synchroni.patch b/queue-6.10/platform-x86-ideapad-laptop-add-a-mutex-to-synchroni.patch new file mode 100644 index 00000000000..f42def5ca56 --- /dev/null +++ b/queue-6.10/platform-x86-ideapad-laptop-add-a-mutex-to-synchroni.patch @@ -0,0 +1,246 @@ +From e915634e5e0ead064ceae61a58a064cd7a7426fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jul 2024 11:21:10 +0200 +Subject: platform/x86: ideapad-laptop: add a mutex to synchronize VPC commands +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Gergo Koteles + +[ Upstream commit 7cc06e729460a209b84d3db4db56c9f85f048cc2 ] + +Calling VPC commands consists of several VPCW and VPCR ACPI calls. +These calls and their results can get mixed up if they are called +simultaneously from different threads, like acpi notify handler, +sysfs, debugfs, notification chain. + +The commit e2ffcda16290 ("ACPI: OSL: Allow Notify () handlers to run on +all CPUs") made the race issues much worse than before it but some +races were possible even before that commit. + +Add a mutex to synchronize VPC commands. + +Fixes: e2ffcda16290 ("ACPI: OSL: Allow Notify () handlers to run on all CPUs") +Fixes: e82882cdd241 ("platform/x86: Add driver for Yoga Tablet Mode switch") +Signed-off-by: Gergo Koteles +Link: https://lore.kernel.org/r/f26782fa1194ad11ed5d9ba121a804e59b58b026.1721898747.git.soyer@irl.hu +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/ideapad-laptop.c | 64 ++++++++++++++++++++------- + 1 file changed, 47 insertions(+), 17 deletions(-) + +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 96e1caf549c43..490815917adec 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -125,6 +125,7 @@ struct ideapad_rfk_priv { + + struct ideapad_private { + struct acpi_device *adev; ++ struct mutex vpc_mutex; /* protects the VPC calls */ + struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; + struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM]; + struct platform_device *platform_device; +@@ -304,6 +305,8 @@ static int debugfs_status_show(struct seq_file *s, void *data) + struct ideapad_private *priv = s->private; + unsigned long value; + ++ guard(mutex)(&priv->vpc_mutex); ++ + if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value)) + seq_printf(s, "Backlight max: %lu\n", value); + if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value)) +@@ -422,7 +425,8 @@ static ssize_t camera_power_show(struct device *dev, + unsigned long result; + int err; + +- err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result); + if (err) + return err; + +@@ -441,7 +445,8 @@ static ssize_t camera_power_store(struct device *dev, + if (err) + return err; + +- err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); + if (err) + return err; + +@@ -494,7 +499,8 @@ static ssize_t fan_mode_show(struct device *dev, + unsigned long result; + int err; + +- err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result); + if (err) + return err; + +@@ -516,7 +522,8 @@ static ssize_t fan_mode_store(struct device *dev, + if (state > 4 || state == 3) + return -EINVAL; + +- err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); + if (err) + return err; + +@@ -601,7 +608,8 @@ static ssize_t touchpad_show(struct device *dev, + unsigned long result; + int err; + +- err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result); + if (err) + return err; + +@@ -622,7 +630,8 @@ static ssize_t touchpad_store(struct device *dev, + if (err) + return err; + +- err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state); + if (err) + return err; + +@@ -1019,6 +1028,8 @@ static int ideapad_rfk_set(void *data, bool blocked) + struct ideapad_rfk_priv *priv = data; + int opcode = ideapad_rfk_data[priv->dev].opcode; + ++ guard(mutex)(&priv->priv->vpc_mutex); ++ + return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked); + } + +@@ -1032,6 +1043,8 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) + int i; + + if (priv->features.hw_rfkill_switch) { ++ guard(mutex)(&priv->vpc_mutex); ++ + if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) + return; + hw_blocked = !hw_blocked; +@@ -1205,8 +1218,9 @@ static void ideapad_input_novokey(struct ideapad_private *priv) + { + unsigned long long_pressed; + +- if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed)) +- return; ++ scoped_guard(mutex, &priv->vpc_mutex) ++ if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed)) ++ return; + + if (long_pressed) + ideapad_input_report(priv, 17); +@@ -1218,8 +1232,9 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) + { + unsigned long bit, value; + +- if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value)) +- return; ++ scoped_guard(mutex, &priv->vpc_mutex) ++ if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value)) ++ return; + + for_each_set_bit (bit, &value, 16) { + switch (bit) { +@@ -1252,6 +1267,8 @@ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) + unsigned long now; + int err; + ++ guard(mutex)(&priv->vpc_mutex); ++ + err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); + if (err) + return err; +@@ -1264,6 +1281,8 @@ static int ideapad_backlight_update_status(struct backlight_device *blightdev) + struct ideapad_private *priv = bl_get_data(blightdev); + int err; + ++ guard(mutex)(&priv->vpc_mutex); ++ + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL, + blightdev->props.brightness); + if (err) +@@ -1341,6 +1360,8 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) + if (!blightdev) + return; + ++ guard(mutex)(&priv->vpc_mutex); ++ + if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power)) + return; + +@@ -1353,7 +1374,8 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) + + /* if we control brightness via acpi video driver */ + if (!priv->blightdev) +- read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); + else + backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY); + } +@@ -1578,7 +1600,8 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_ + int ret; + + /* Without reading from EC touchpad LED doesn't switch state */ +- ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value); + if (ret) + return; + +@@ -1638,7 +1661,8 @@ static void ideapad_laptop_trigger_ec(void) + if (!priv->features.ymc_ec_trigger) + return; + +- ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_YMC, 1); ++ scoped_guard(mutex, &priv->vpc_mutex) ++ ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_YMC, 1); + if (ret) + dev_warn(&priv->platform_device->dev, "Could not write YMC: %d\n", ret); + } +@@ -1684,11 +1708,13 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) + struct ideapad_private *priv = data; + unsigned long vpc1, vpc2, bit; + +- if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) +- return; ++ scoped_guard(mutex, &priv->vpc_mutex) { ++ if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) ++ return; + +- if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) +- return; ++ if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) ++ return; ++ } + + vpc1 = (vpc2 << 8) | vpc1; + +@@ -1997,6 +2023,10 @@ static int ideapad_acpi_add(struct platform_device *pdev) + priv->adev = adev; + priv->platform_device = pdev; + ++ err = devm_mutex_init(&pdev->dev, &priv->vpc_mutex); ++ if (err) ++ return err; ++ + ideapad_check_features(priv); + + err = ideapad_sysfs_init(priv); +-- +2.43.0 + diff --git a/queue-6.10/platform-x86-ideapad-laptop-introduce-a-generic-noti.patch b/queue-6.10/platform-x86-ideapad-laptop-introduce-a-generic-noti.patch new file mode 100644 index 00000000000..f8e983e28f1 --- /dev/null +++ b/queue-6.10/platform-x86-ideapad-laptop-introduce-a-generic-noti.patch @@ -0,0 +1,109 @@ +From e20de6a808688b6802b00d2180a71ac767b90726 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jul 2024 11:21:07 +0200 +Subject: platform/x86: ideapad-laptop: introduce a generic notification chain +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Gergo Koteles + +[ Upstream commit 613e3900c24bb1379d994f44d75d31c3223cc263 ] + +There are several cases where a notification chain can simplify Lenovo +WMI drivers. + +Add a generic notification chain into ideapad-laptop. + +Signed-off-by: Gergo Koteles +Link: https://lore.kernel.org/r/c5a43efae8a32bd034c3d19c0a686941347575a7.1721898747.git.soyer@irl.hu +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Stable-dep-of: 7cc06e729460 ("platform/x86: ideapad-laptop: add a mutex to synchronize VPC commands") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/ideapad-laptop.c | 37 +++++++++++++++++++++++++++ + drivers/platform/x86/ideapad-laptop.h | 5 ++++ + 2 files changed, 42 insertions(+) + +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index fcf13d88fd6ed..38d98ee558d32 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -1599,6 +1599,39 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_ + priv->r_touchpad_val = value; + } + ++static int ideapad_laptop_nb_notify(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ switch (action) { ++ } ++ ++ return 0; ++} ++ ++static struct notifier_block ideapad_laptop_notifier = { ++ .notifier_call = ideapad_laptop_nb_notify, ++}; ++ ++static BLOCKING_NOTIFIER_HEAD(ideapad_laptop_chain_head); ++ ++int ideapad_laptop_register_notifier(struct notifier_block *nb) ++{ ++ return blocking_notifier_chain_register(&ideapad_laptop_chain_head, nb); ++} ++EXPORT_SYMBOL_NS_GPL(ideapad_laptop_register_notifier, IDEAPAD_LAPTOP); ++ ++int ideapad_laptop_unregister_notifier(struct notifier_block *nb) ++{ ++ return blocking_notifier_chain_unregister(&ideapad_laptop_chain_head, nb); ++} ++EXPORT_SYMBOL_NS_GPL(ideapad_laptop_unregister_notifier, IDEAPAD_LAPTOP); ++ ++void ideapad_laptop_call_notifier(unsigned long action, void *data) ++{ ++ blocking_notifier_call_chain(&ideapad_laptop_chain_head, action, data); ++} ++EXPORT_SYMBOL_NS_GPL(ideapad_laptop_call_notifier, IDEAPAD_LAPTOP); ++ + static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) + { + struct ideapad_private *priv = data; +@@ -1983,6 +2016,8 @@ static int ideapad_acpi_add(struct platform_device *pdev) + if (err) + goto shared_init_failed; + ++ ideapad_laptop_register_notifier(&ideapad_laptop_notifier); ++ + return 0; + + shared_init_failed: +@@ -2015,6 +2050,8 @@ static void ideapad_acpi_remove(struct platform_device *pdev) + struct ideapad_private *priv = dev_get_drvdata(&pdev->dev); + int i; + ++ ideapad_laptop_unregister_notifier(&ideapad_laptop_notifier); ++ + ideapad_shared_exit(priv); + + acpi_remove_notify_handler(priv->adev->handle, +diff --git a/drivers/platform/x86/ideapad-laptop.h b/drivers/platform/x86/ideapad-laptop.h +index 4498a96de5976..3eb0dcd6bf7ba 100644 +--- a/drivers/platform/x86/ideapad-laptop.h ++++ b/drivers/platform/x86/ideapad-laptop.h +@@ -12,6 +12,11 @@ + #include + #include + #include ++#include ++ ++int ideapad_laptop_register_notifier(struct notifier_block *nb); ++int ideapad_laptop_unregister_notifier(struct notifier_block *nb); ++void ideapad_laptop_call_notifier(unsigned long action, void *data); + + enum { + VPCCMD_R_VPC1 = 0x10, +-- +2.43.0 + diff --git a/queue-6.10/platform-x86-ideapad-laptop-move-ymc_trigger_ec-from.patch b/queue-6.10/platform-x86-ideapad-laptop-move-ymc_trigger_ec-from.patch new file mode 100644 index 00000000000..a2dbf0ff75f --- /dev/null +++ b/queue-6.10/platform-x86-ideapad-laptop-move-ymc_trigger_ec-from.patch @@ -0,0 +1,270 @@ +From 5d67d83dfdd1efd44eaada0eb80c29f5f31d8a0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jul 2024 11:21:08 +0200 +Subject: platform/x86: ideapad-laptop: move ymc_trigger_ec from lenovo-ymc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Gergo Koteles + +[ Upstream commit cde7886b35176d56e72bfc68dc104fa08e7b072c ] + +Some models need to trigger the EC after each YMC event for the yoga +mode control to work properly. EC triggering consist of a VPC call from +the lenovo-ymc module. Except for this, all VPC calls are in the +ideapad-laptop module. + +Since ideapad-laptop has a notification chain, a new YMC_EVENT action +can be added and triggered from the lenovo-ymc module. Then the +ideapad-laptop can trigger the EC. + +If the triggering is in the ideapad-laptop module, then the ec_trigger +module parameter should be there as well. + +Move the ymc_trigger_ec functionality and the ec_trigger module +parameter to the ideapad-laptop module. + +Signed-off-by: Gergo Koteles +Reviewed-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/d980ab3ac32b5e554f456b0ff17279bfdbe2a203.1721898747.git.soyer@irl.hu +Signed-off-by: Ilpo Järvinen +Stable-dep-of: 7cc06e729460 ("platform/x86: ideapad-laptop: add a mutex to synchronize VPC commands") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/Kconfig | 1 + + drivers/platform/x86/ideapad-laptop.c | 49 ++++++++++++++++++++++ + drivers/platform/x86/ideapad-laptop.h | 4 ++ + drivers/platform/x86/lenovo-ymc.c | 60 +-------------------------- + 4 files changed, 56 insertions(+), 58 deletions(-) + +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index 665fa95249865..ddfccc226751f 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -477,6 +477,7 @@ config LENOVO_YMC + tristate "Lenovo Yoga Tablet Mode Control" + depends on ACPI_WMI + depends on INPUT ++ depends on IDEAPAD_LAPTOP + select INPUT_SPARSEKMAP + help + This driver maps the Tablet Mode Control switch to SW_TABLET_MODE input +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 38d98ee558d32..96e1caf549c43 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -145,6 +145,7 @@ struct ideapad_private { + bool touchpad_ctrl_via_ec : 1; + bool ctrl_ps2_aux_port : 1; + bool usb_charging : 1; ++ bool ymc_ec_trigger : 1; + } features; + struct { + bool initialized; +@@ -193,6 +194,12 @@ MODULE_PARM_DESC(touchpad_ctrl_via_ec, + "Enable registering a 'touchpad' sysfs-attribute which can be used to manually " + "tell the EC to enable/disable the touchpad. This may not work on all models."); + ++static bool ymc_ec_trigger __read_mostly; ++module_param(ymc_ec_trigger, bool, 0444); ++MODULE_PARM_DESC(ymc_ec_trigger, ++ "Enable EC triggering work-around to force emitting tablet mode events. " ++ "If you need this please report this to: platform-driver-x86@vger.kernel.org"); ++ + /* + * shared data + */ +@@ -1599,10 +1606,50 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_ + priv->r_touchpad_val = value; + } + ++static const struct dmi_system_id ymc_ec_trigger_quirk_dmi_table[] = { ++ { ++ /* Lenovo Yoga 7 14ARB7 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "82QF"), ++ }, ++ }, ++ { ++ /* Lenovo Yoga 7 14ACN6 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "82N7"), ++ }, ++ }, ++ { } ++}; ++ ++static void ideapad_laptop_trigger_ec(void) ++{ ++ struct ideapad_private *priv; ++ int ret; ++ ++ guard(mutex)(&ideapad_shared_mutex); ++ ++ priv = ideapad_shared; ++ if (!priv) ++ return; ++ ++ if (!priv->features.ymc_ec_trigger) ++ return; ++ ++ ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_YMC, 1); ++ if (ret) ++ dev_warn(&priv->platform_device->dev, "Could not write YMC: %d\n", ret); ++} ++ + static int ideapad_laptop_nb_notify(struct notifier_block *nb, + unsigned long action, void *data) + { + switch (action) { ++ case IDEAPAD_LAPTOP_YMC_EVENT: ++ ideapad_laptop_trigger_ec(); ++ break; + } + + return 0; +@@ -1768,6 +1815,8 @@ static void ideapad_check_features(struct ideapad_private *priv) + priv->features.ctrl_ps2_aux_port = + ctrl_ps2_aux_port || dmi_check_system(ctrl_ps2_aux_port_list); + priv->features.touchpad_ctrl_via_ec = touchpad_ctrl_via_ec; ++ priv->features.ymc_ec_trigger = ++ ymc_ec_trigger || dmi_check_system(ymc_ec_trigger_quirk_dmi_table); + + if (!read_ec_data(handle, VPCCMD_R_FAN, &val)) + priv->features.fan_mode = true; +diff --git a/drivers/platform/x86/ideapad-laptop.h b/drivers/platform/x86/ideapad-laptop.h +index 3eb0dcd6bf7ba..948cc61800a95 100644 +--- a/drivers/platform/x86/ideapad-laptop.h ++++ b/drivers/platform/x86/ideapad-laptop.h +@@ -14,6 +14,10 @@ + #include + #include + ++enum ideapad_laptop_notifier_actions { ++ IDEAPAD_LAPTOP_YMC_EVENT, ++}; ++ + int ideapad_laptop_register_notifier(struct notifier_block *nb); + int ideapad_laptop_unregister_notifier(struct notifier_block *nb); + void ideapad_laptop_call_notifier(unsigned long action, void *data); +diff --git a/drivers/platform/x86/lenovo-ymc.c b/drivers/platform/x86/lenovo-ymc.c +index e1fbc35504d49..e0bbd6a14a89c 100644 +--- a/drivers/platform/x86/lenovo-ymc.c ++++ b/drivers/platform/x86/lenovo-ymc.c +@@ -20,32 +20,10 @@ + #define LENOVO_YMC_QUERY_INSTANCE 0 + #define LENOVO_YMC_QUERY_METHOD 0x01 + +-static bool ec_trigger __read_mostly; +-module_param(ec_trigger, bool, 0444); +-MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events"); +- + static bool force; + module_param(force, bool, 0444); + MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type"); + +-static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = { +- { +- /* Lenovo Yoga 7 14ARB7 */ +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +- DMI_MATCH(DMI_PRODUCT_NAME, "82QF"), +- }, +- }, +- { +- /* Lenovo Yoga 7 14ACN6 */ +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +- DMI_MATCH(DMI_PRODUCT_NAME, "82N7"), +- }, +- }, +- { } +-}; +- + static const struct dmi_system_id allowed_chasis_types_dmi_table[] = { + { + .matches = { +@@ -62,21 +40,8 @@ static const struct dmi_system_id allowed_chasis_types_dmi_table[] = { + + struct lenovo_ymc_private { + struct input_dev *input_dev; +- struct acpi_device *ec_acpi_dev; + }; + +-static void lenovo_ymc_trigger_ec(struct wmi_device *wdev, struct lenovo_ymc_private *priv) +-{ +- int err; +- +- if (!priv->ec_acpi_dev) +- return; +- +- err = write_ec_cmd(priv->ec_acpi_dev->handle, VPCCMD_W_YMC, 1); +- if (err) +- dev_warn(&wdev->dev, "Could not write YMC: %d\n", err); +-} +- + static const struct key_entry lenovo_ymc_keymap[] = { + /* Laptop */ + { KE_SW, 0x01, { .sw = { SW_TABLET_MODE, 0 } } }, +@@ -125,11 +90,9 @@ static void lenovo_ymc_notify(struct wmi_device *wdev, union acpi_object *data) + + free_obj: + kfree(obj); +- lenovo_ymc_trigger_ec(wdev, priv); ++ ideapad_laptop_call_notifier(IDEAPAD_LAPTOP_YMC_EVENT, &code); + } + +-static void acpi_dev_put_helper(void *p) { acpi_dev_put(p); } +- + static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx) + { + struct lenovo_ymc_private *priv; +@@ -143,29 +106,10 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx) + return -ENODEV; + } + +- ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table); +- + priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + +- if (ec_trigger) { +- pr_debug("Lenovo YMC enable EC triggering.\n"); +- priv->ec_acpi_dev = acpi_dev_get_first_match_dev("VPC2004", NULL, -1); +- +- if (!priv->ec_acpi_dev) { +- dev_err(&wdev->dev, "Could not find EC ACPI device.\n"); +- return -ENODEV; +- } +- err = devm_add_action_or_reset(&wdev->dev, +- acpi_dev_put_helper, priv->ec_acpi_dev); +- if (err) { +- dev_err(&wdev->dev, +- "Could not clean up EC ACPI device: %d\n", err); +- return err; +- } +- } +- + input_dev = devm_input_allocate_device(&wdev->dev); + if (!input_dev) + return -ENOMEM; +@@ -192,7 +136,6 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx) + dev_set_drvdata(&wdev->dev, priv); + + /* Report the state for the first time on probe */ +- lenovo_ymc_trigger_ec(wdev, priv); + lenovo_ymc_notify(wdev, NULL); + return 0; + } +@@ -217,3 +160,4 @@ module_wmi_driver(lenovo_ymc_driver); + MODULE_AUTHOR("Gergo Koteles "); + MODULE_DESCRIPTION("Lenovo Yoga Mode Control driver"); + MODULE_LICENSE("GPL"); ++MODULE_IMPORT_NS(IDEAPAD_LAPTOP); +-- +2.43.0 + diff --git a/queue-6.10/series b/queue-6.10/series index 020b15a7024..cf00b48dc41 100644 --- a/queue-6.10/series +++ b/queue-6.10/series @@ -5,3 +5,16 @@ drm-amd-display-prevent-ipx-from-link-detect-and-set-mode.patch loongarch-define-__arch_want_new_stat-in-unistd.h.patch nvme-pci-add-apst-quirk-for-lenovo-n60z-laptop.patch asoc-cs35l56-patch-cs35l56_irq1_mask_18-to-the-default-value.patch +bpf-net-use-dev_stat_inc.patch +f2fs-fix-to-do-sanity-check-on-f2fs_inline_data-flag.patch +f2fs-fix-to-cover-read-extent-cache-access-with-lock.patch +fou-remove-warn-in-gue_gro_receive-on-unsupported-pr.patch +jfs-fix-null-ptr-deref-in-dtinsertentry.patch +jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch +fs-ntfs3-do-copy_to_user-out-of-run_lock.patch +alsa-usb-fix-ubsan-warning-in-parse_audio_unit.patch +platform-x86-amd-pmf-fix-to-update-hpd-data-when-als.patch +platform-x86-ideapad-laptop-introduce-a-generic-noti.patch +platform-x86-ideapad-laptop-move-ymc_trigger_ec-from.patch +platform-x86-ideapad-laptop-add-a-mutex-to-synchroni.patch +binfmt_flat-fix-corruption-when-not-offsetting-data-.patch