From: Sasha Levin Date: Thu, 23 Apr 2026 00:00:57 +0000 (-0400) Subject: Fixes for all trees X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;ds=sidebyside;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/alsa-usb-audio-fix-null-pointer-dereference-on-point.patch b/queue-5.10/alsa-usb-audio-fix-null-pointer-dereference-on-point.patch new file mode 100644 index 0000000000..1606c1ab0b --- /dev/null +++ b/queue-5.10/alsa-usb-audio-fix-null-pointer-dereference-on-point.patch @@ -0,0 +1,53 @@ +From d8e3fbedb617d8fdb48d015c523938560b1fc86c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:20:47 +0300 +Subject: ALSA: usb-audio: fix null pointer dereference on pointer cs_desc + +From: Chengfeng Ye + +commit b97053df0f04747c3c1e021ecbe99db675342954 upstream. + +The pointer cs_desc return from snd_usb_find_clock_source could +be null, so there is a potential null pointer dereference issue. +Fix this by adding a null check before dereference. + +Signed-off-by: Chengfeng Ye +Link: https://lore.kernel.org/r/20211024111736.11342-1-cyeaa@connect.ust.hk +Signed-off-by: Takashi Iwai +Fixes: 1dc669fed61a ("ALSA: usb-audio: UAC2: support read-only freq control") +[ kovalev: bp to fix CVE-2021-47211; added Fixes tag; the null + check was added into both UAC2 and UAC3 branches since the + older kernel still has the clock source lookup split between + snd_usb_find_clock_source() and snd_usb_find_clock_source_v3() + (see upstream commit 9ec730052fa2) ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + sound/usb/clock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sound/usb/clock.c b/sound/usb/clock.c +index 197a6b7d8ad6f..3d5d4f3aafce4 100644 +--- a/sound/usb/clock.c ++++ b/sound/usb/clock.c +@@ -646,11 +646,17 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, + struct uac3_clock_source_descriptor *cs_desc; + + cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock); ++ ++ if (!cs_desc) ++ return 0; + bmControls = le32_to_cpu(cs_desc->bmControls); + } else { + struct uac_clock_source_descriptor *cs_desc; + + cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock); ++ ++ if (!cs_desc) ++ return 0; + bmControls = cs_desc->bmControls; + } + +-- +2.53.0 + diff --git a/queue-5.10/blk-cgroup-reinit-blkg_iostat_set-after-clearing-in-.patch b/queue-5.10/blk-cgroup-reinit-blkg_iostat_set-after-clearing-in-.patch new file mode 100644 index 0000000000..76fa8bccf7 --- /dev/null +++ b/queue-5.10/blk-cgroup-reinit-blkg_iostat_set-after-clearing-in-.patch @@ -0,0 +1,65 @@ +From 262eae4b70b0206378b6253e40a1842433117160 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:29:20 +0300 +Subject: blk-cgroup: Reinit blkg_iostat_set after clearing in + blkcg_reset_stats() + +From: Waiman Long + +[ Upstream commit 3d2af77e31ade05ff7ccc3658c3635ec1bea0979 ] + +When blkg_alloc() is called to allocate a blkcg_gq structure +with the associated blkg_iostat_set's, there are 2 fields within +blkg_iostat_set that requires proper initialization - blkg & sync. +The former field was introduced by commit 3b8cc6298724 ("blk-cgroup: +Optimize blkcg_rstat_flush()") while the later one was introduced by +commit f73316482977 ("blk-cgroup: reimplement basic IO stats using +cgroup rstat"). + +Unfortunately those fields in the blkg_iostat_set's are not properly +re-initialized when they are cleared in v1's blkcg_reset_stats(). This +can lead to a kernel panic due to NULL pointer access of the blkg +pointer. The missing initialization of sync is less problematic and +can be a problem in a debug kernel due to missing lockdep initialization. + +Fix these problems by re-initializing them after memory clearing. + +Fixes: 3b8cc6298724 ("blk-cgroup: Optimize blkcg_rstat_flush()") +Fixes: f73316482977 ("blk-cgroup: reimplement basic IO stats using cgroup rstat") +Signed-off-by: Waiman Long +Reviewed-by: Ming Lei +Acked-by: Tejun Heo +Link: https://lore.kernel.org/r/20230606180724.2455066-1-longman@redhat.com +Signed-off-by: Jens Axboe +[ Remove this line: bis -> blkg = blkg for blkg was introduced by commit + 3b8cc6298724 ("blk-cgroup: Optimize blkcg_rstat_flush()") since v6.2. ] +Signed-off-by: Alva Lan +Signed-off-by: Greg Kroah-Hartman +(cherry picked from commit 0561aa6033dd181594116d705c41fc16e97161a2) +[ kovalev: bp to fix CVE-2023-53421 ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + block/blk-cgroup.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index dbd18b75ec915..7ffdc3360a6c2 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -464,8 +464,12 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css, + struct blkg_iostat_set *bis = + per_cpu_ptr(blkg->iostat_cpu, cpu); + memset(bis, 0, sizeof(*bis)); ++ ++ /* Re-initialize the cleared blkg_iostat_set */ ++ u64_stats_init(&bis->sync); + } + memset(&blkg->iostat, 0, sizeof(blkg->iostat)); ++ u64_stats_init(&blkg->iostat.sync); + + for (i = 0; i < BLKCG_MAX_POLS; i++) { + struct blkcg_policy *pol = blkcg_policy[i]; +-- +2.53.0 + diff --git a/queue-5.10/bpf-sockmap-fix-an-infinite-loop-error-when-len-is-0.patch b/queue-5.10/bpf-sockmap-fix-an-infinite-loop-error-when-len-is-0.patch new file mode 100644 index 0000000000..765db5be55 --- /dev/null +++ b/queue-5.10/bpf-sockmap-fix-an-infinite-loop-error-when-len-is-0.patch @@ -0,0 +1,92 @@ +From 28397a96d39224baf431d8752747d3cbba94dfea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:28:39 +0300 +Subject: bpf, sockmap: Fix an infinite loop error when len is 0 in + tcp_bpf_recvmsg_parser() + +From: Liu Jian + +commit d900f3d20cc3169ce42ec72acc850e662a4d4db2 upstream. + +When the buffer length of the recvmsg system call is 0, we got the +flollowing soft lockup problem: + +watchdog: BUG: soft lockup - CPU#3 stuck for 27s! [a.out:6149] +CPU: 3 PID: 6149 Comm: a.out Kdump: loaded Not tainted 6.2.0+ #30 +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 +RIP: 0010:remove_wait_queue+0xb/0xc0 +Code: 5e 41 5f c3 cc cc cc cc 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 0f 1f 44 00 00 41 57 <41> 56 41 55 41 54 55 48 89 fd 53 48 89 f3 4c 8d 6b 18 4c 8d 73 20 +RSP: 0018:ffff88811b5978b8 EFLAGS: 00000246 +RAX: 0000000000000000 RBX: ffff88811a7d3780 RCX: ffffffffb7a4d768 +RDX: dffffc0000000000 RSI: ffff88811b597908 RDI: ffff888115408040 +RBP: 1ffff110236b2f1b R08: 0000000000000000 R09: ffff88811a7d37e7 +R10: ffffed10234fa6fc R11: 0000000000000001 R12: ffff88811179b800 +R13: 0000000000000001 R14: ffff88811a7d38a8 R15: ffff88811a7d37e0 +FS: 00007f6fb5398740(0000) GS:ffff888237180000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000020000000 CR3: 000000010b6ba002 CR4: 0000000000370ee0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + tcp_msg_wait_data+0x279/0x2f0 + tcp_bpf_recvmsg_parser+0x3c6/0x490 + inet_recvmsg+0x280/0x290 + sock_recvmsg+0xfc/0x120 + ____sys_recvmsg+0x160/0x3d0 + ___sys_recvmsg+0xf0/0x180 + __sys_recvmsg+0xea/0x1a0 + do_syscall_64+0x3f/0x90 + entry_SYSCALL_64_after_hwframe+0x72/0xdc + +The logic in tcp_bpf_recvmsg_parser is as follows: + +msg_bytes_ready: + copied = sk_msg_recvmsg(sk, psock, msg, len, flags); + if (!copied) { + wait data; + goto msg_bytes_ready; + } + +In this case, "copied" always is 0, the infinite loop occurs. + +According to the Linux system call man page, 0 should be returned in this +case. Therefore, in tcp_bpf_recvmsg_parser(), if the length is 0, directly +return. Also modify several other functions with the same problem. + +Fixes: 1f5be6b3b063 ("udp: Implement udp_bpf_recvmsg() for sockmap") +Fixes: 9825d866ce0d ("af_unix: Implement unix_dgram_bpf_recvmsg()") +Fixes: c5d2177a72a1 ("bpf, sockmap: Fix race in ingress receive verdict with redirect to self") +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Liu Jian +Signed-off-by: Daniel Borkmann +Acked-by: John Fastabend +Cc: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/20230303080946.1146638-1-liujian56@huawei.com +[ kovalev: bp to fix CVE-2023-53133; applied only to tcp_bpf_recvmsg as the + older kernel lacks tcp_bpf_recvmsg_parser, udp_bpf_recvmsg and + unix_bpf_recvmsg (see upstream commits c5d2177a72a1, 1f5be6b3b063 and + 9825d866ce0d) ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index bcd5fc484f777..76cd974887774 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -277,6 +277,9 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + if (unlikely(flags & MSG_ERRQUEUE)) + return inet_recv_error(sk, msg, len, addr_len); + ++ if (!len) ++ return 0; ++ + psock = sk_psock_get(sk); + if (unlikely(!psock)) + return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len); +-- +2.53.0 + diff --git a/queue-5.10/cifs-fix-connections-leak-when-tlink-setup-failed.patch b/queue-5.10/cifs-fix-connections-leak-when-tlink-setup-failed.patch new file mode 100644 index 0000000000..1b5a7d3059 --- /dev/null +++ b/queue-5.10/cifs-fix-connections-leak-when-tlink-setup-failed.patch @@ -0,0 +1,70 @@ +From a673f9695413a4ee877ef4500501e432670259a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:26:12 +0300 +Subject: cifs: Fix connections leak when tlink setup failed + +From: Zhang Xiaoxu + +commit 1dcdf5f5b2137185cbdd5385f29949ab3da4f00c upstream. + +If the tlink setup failed, lost to put the connections, then +the module refcnt leak since the cifsd kthread not exit. + +Also leak the fscache info, and for next mount with fsc, it will +print the follow errors: + CIFS: Cache volume key already in use (cifs,127.0.0.1:445,TEST) + +Let's check the result of tlink setup, and do some cleanup. + +Fixes: 56c762eb9bee ("cifs: Refactor out cifs_mount()") +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Steve French +[ kovalev: bp to fix CVE-2022-49822; adapted to use direct xid/ses/tcon + variables instead of mnt_ctx struct fields due to the older kernel not + having the corresponding cifs_mount() refactoring (see upstream commit + c88f7dcd6d64) ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + fs/cifs/connect.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 769c7759601db..3161155fd069b 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -4786,9 +4786,13 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) + vol->prepath = NULL; + + out: +- free_xid(xid); + cifs_try_adding_channels(ses); +- return mount_setup_tlink(cifs_sb, ses, tcon); ++ rc = mount_setup_tlink(cifs_sb, ses, tcon); ++ if (rc) ++ goto error; ++ ++ free_xid(xid); ++ return rc; + + error: + kfree(ref_path); +@@ -4820,9 +4824,12 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) + goto error; + } + +- free_xid(xid); ++ rc = mount_setup_tlink(cifs_sb, ses, tcon); ++ if (rc) ++ goto error; + +- return mount_setup_tlink(cifs_sb, ses, tcon); ++ free_xid(xid); ++ return rc; + + error: + mount_put_conns(cifs_sb, xid, server, ses, tcon); +-- +2.53.0 + diff --git a/queue-5.10/drm-amd-display-add-null-checker-before-passing-vari.patch b/queue-5.10/drm-amd-display-add-null-checker-before-passing-vari.patch new file mode 100644 index 0000000000..f00ef0eacb --- /dev/null +++ b/queue-5.10/drm-amd-display-add-null-checker-before-passing-vari.patch @@ -0,0 +1,64 @@ +From 7d242d657edfd9dc6b5ff8c3d01d6401fbd6e346 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:30:02 +0300 +Subject: drm/amd/display: Add null checker before passing variables + +From: Alex Hung + +commit 8092aa3ab8f7b737a34b71f91492c676a843043a upstream. + +Checks null pointer before passing variables to functions. + +This fixes 3 NULL_RETURNS issues reported by Coverity. + +Reviewed-by: Harry Wentland +Acked-by: Hamza Mahfooz +Signed-off-by: Alex Hung +Signed-off-by: Alex Deucher +Fixes: cdaae8371aa9 ("drm/amd/display: Handle GPU reset for DC block") +Fixes: dcd5fb82ffb4 ("drm/amd/display: Fix reference counting for struct dc_sink.") +Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)") +[ kovalev: bp to fix CVE-2024-43902; added Fixes tags ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index c22783b882067..bd15de4dee75e 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1778,7 +1778,8 @@ static int dm_suspend(void *handle) + mutex_lock(&dm->dc_lock); + dm->cached_dc_state = dc_copy_state(dm->dc->current_state); + +- dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false); ++ if (dm->cached_dc_state) ++ dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false); + + amdgpu_dm_commit_zero_streams(dm->dc); + +@@ -5396,7 +5397,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) + aconnector->dc_sink = aconnector->dc_link->local_sink ? + aconnector->dc_link->local_sink : + aconnector->dc_em_sink; +- dc_sink_retain(aconnector->dc_sink); ++ if (aconnector->dc_sink) ++ dc_sink_retain(aconnector->dc_sink); + } + } + +@@ -6575,7 +6577,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) + drm_add_modes_noedid(connector, 640, 480); + } else { + amdgpu_dm_connector_ddc_get_modes(connector, edid); +- amdgpu_dm_connector_add_common_modes(encoder, connector); ++ if (encoder) ++ amdgpu_dm_connector_add_common_modes(encoder, connector); + } + amdgpu_dm_fbc_init(connector); + +-- +2.53.0 + diff --git a/queue-5.10/drm-amd-display-fix-memory-leak.patch b/queue-5.10/drm-amd-display-fix-memory-leak.patch new file mode 100644 index 0000000000..c91293f7b6 --- /dev/null +++ b/queue-5.10/drm-amd-display-fix-memory-leak.patch @@ -0,0 +1,251 @@ +From d76e99b1f3bd524a34fe3905d019c4dc437821cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:22:10 +0300 +Subject: drm/amd/display: Fix memory leak + +From: Yongzhi Liu + +commit 5d5c6dba2b43e28845d7d7ed32a36802329a5f52 upstream. + +[why] +Resource release is needed on the error handling path +to prevent memory leak. + +[how] +Fix this by adding kfree on the error handling path. + +Reviewed-by: Harry Wentland +Signed-off-by: Yongzhi Liu +Signed-off-by: Alex Deucher +Fixes: f8ac2cf78f27 ("drm/amd/display: Linux set/read lane settings through debugfs") +Fixes: c06e09b76639 ("drm/amd/display: Add DSC parameters logging to debugfs") +[ kovalev: bp to fix CVE-2022-49135; added Fixes tags ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 72 ++++++++++++++----- + 1 file changed, 54 insertions(+), 18 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +index 6914738f0275a..f4a1ad8959b7d 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +@@ -229,8 +229,10 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -388,8 +390,10 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf, + break; + + r = put_user((*(rd_buf + result)), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -1195,8 +1199,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -1212,8 +1218,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -1351,8 +1359,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -1368,8 +1378,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -1505,8 +1517,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -1522,8 +1536,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -1655,8 +1671,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -1672,8 +1690,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -1800,8 +1820,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -1817,8 +1839,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -1857,8 +1881,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -1874,8 +1900,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -1929,8 +1957,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -1946,8 +1976,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +@@ -2001,8 +2033,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, + break; + } + +- if (!pipe_ctx) ++ if (!pipe_ctx) { ++ kfree(rd_buf); + return -ENXIO; ++ } + + dsc = pipe_ctx->stream_res.dsc; + if (dsc) +@@ -2018,8 +2052,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, + break; + + r = put_user(*(rd_buf + result), buf); +- if (r) ++ if (r) { ++ kfree(rd_buf); + return r; /* r = -EFAULT */ ++ } + + buf += 1; + size -= 1; +-- +2.53.0 + diff --git a/queue-5.10/ib-mad-don-t-call-to-function-that-might-sleep-while.patch b/queue-5.10/ib-mad-don-t-call-to-function-that-might-sleep-while.patch new file mode 100644 index 0000000000..4f281aa976 --- /dev/null +++ b/queue-5.10/ib-mad-don-t-call-to-function-that-might-sleep-while.patch @@ -0,0 +1,149 @@ +From e0ef7f5827eb4e7de8eabf099b10bc8e61db1c00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:28:08 +0300 +Subject: IB/mad: Don't call to function that might sleep while in atomic + context + +From: Leonid Ravich + +commit 5c20311d76cbaeb7ed2ecf9c8b8322f8fc4a7ae3 upstream. + +Tracepoints are not allowed to sleep, as such the following splat is +generated due to call to ib_query_pkey() in atomic context. + +WARNING: CPU: 0 PID: 1888000 at kernel/trace/ring_buffer.c:2492 rb_commit+0xc1/0x220 +CPU: 0 PID: 1888000 Comm: kworker/u9:0 Kdump: loaded Tainted: G OE --------- - - 4.18.0-305.3.1.el8.x86_64 #1 + Hardware name: Red Hat KVM, BIOS 1.13.0-2.module_el8.3.0+555+a55c8938 04/01/2014 + Workqueue: ib-comp-unb-wq ib_cq_poll_work [ib_core] + RIP: 0010:rb_commit+0xc1/0x220 + RSP: 0000:ffffa8ac80f9bca0 EFLAGS: 00010202 + RAX: ffff8951c7c01300 RBX: ffff8951c7c14a00 RCX: 0000000000000246 + RDX: ffff8951c707c000 RSI: ffff8951c707c57c RDI: ffff8951c7c14a00 + RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 + R10: ffff8951c7c01300 R11: 0000000000000001 R12: 0000000000000246 + R13: 0000000000000000 R14: ffffffff964c70c0 R15: 0000000000000000 + FS: 0000000000000000(0000) GS:ffff8951fbc00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f20e8f39010 CR3: 000000002ca10005 CR4: 0000000000170ef0 + Call Trace: + ring_buffer_unlock_commit+0x1d/0xa0 + trace_buffer_unlock_commit_regs+0x3b/0x1b0 + trace_event_buffer_commit+0x67/0x1d0 + trace_event_raw_event_ib_mad_recv_done_handler+0x11c/0x160 [ib_core] + ib_mad_recv_done+0x48b/0xc10 [ib_core] + ? trace_event_raw_event_cq_poll+0x6f/0xb0 [ib_core] + __ib_process_cq+0x91/0x1c0 [ib_core] + ib_cq_poll_work+0x26/0x80 [ib_core] + process_one_work+0x1a7/0x360 + ? create_worker+0x1a0/0x1a0 + worker_thread+0x30/0x390 + ? create_worker+0x1a0/0x1a0 + kthread+0x116/0x130 + ? kthread_flush_work_fn+0x10/0x10 + ret_from_fork+0x35/0x40 + ---[ end trace 78ba8509d3830a16 ]--- + +Fixes: 821bf1de45a1 ("IB/MAD: Add recv path trace point") +Signed-off-by: Leonid Ravich +Link: https://lore.kernel.org/r/Y2t5feomyznrVj7V@leonid-Inspiron-3421 +Signed-off-by: Leon Romanovsky +[ kovalev: bp to fix CVE-2022-50472 ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 5 ----- + include/trace/events/ib_mad.h | 13 ++++--------- + 2 files changed, 4 insertions(+), 14 deletions(-) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 19540a13cb84d..e38ae4ac454f6 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -59,9 +59,6 @@ static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr, + struct ib_mad_qp_info *qp_info, + struct trace_event_raw_ib_mad_send_template *entry) + { +- u16 pkey; +- struct ib_device *dev = qp_info->port_priv->device; +- u8 pnum = qp_info->port_priv->port_num; + struct ib_ud_wr *wr = &mad_send_wr->send_wr; + struct rdma_ah_attr attr = {}; + +@@ -69,8 +66,6 @@ static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr, + + /* These are common */ + entry->sl = attr.sl; +- ib_query_pkey(dev, pnum, wr->pkey_index, &pkey); +- entry->pkey = pkey; + entry->rqpn = wr->remote_qpn; + entry->rqkey = wr->remote_qkey; + entry->dlid = rdma_ah_get_dlid(&attr); +diff --git a/include/trace/events/ib_mad.h b/include/trace/events/ib_mad.h +index 59363a083ecb9..d92691c78cff6 100644 +--- a/include/trace/events/ib_mad.h ++++ b/include/trace/events/ib_mad.h +@@ -49,7 +49,6 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + __field(int, retries_left) + __field(int, max_retries) + __field(int, retry) +- __field(u16, pkey) + ), + + TP_fast_assign( +@@ -89,7 +88,7 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + "hdr : base_ver 0x%x class 0x%x class_ver 0x%x " \ + "method 0x%x status 0x%x class_specific 0x%x tid 0x%llx " \ + "attr_id 0x%x attr_mod 0x%x => dlid 0x%08x sl %d "\ +- "pkey 0x%x rpqn 0x%x rqpkey 0x%x", ++ "rpqn 0x%x rqpkey 0x%x", + __entry->dev_index, __entry->port_num, __entry->qp_num, + __entry->agent_priv, be64_to_cpu(__entry->wrtid), + __entry->retries_left, __entry->max_retries, +@@ -100,7 +99,7 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + be16_to_cpu(__entry->class_specific), + be64_to_cpu(__entry->tid), be16_to_cpu(__entry->attr_id), + be32_to_cpu(__entry->attr_mod), +- be32_to_cpu(__entry->dlid), __entry->sl, __entry->pkey, ++ be32_to_cpu(__entry->dlid), __entry->sl, + __entry->rqpn, __entry->rqkey + ) + ); +@@ -204,7 +203,6 @@ TRACE_EVENT(ib_mad_recv_done_handler, + __field(u16, wc_status) + __field(u32, slid) + __field(u32, dev_index) +- __field(u16, pkey) + ), + + TP_fast_assign( +@@ -224,9 +222,6 @@ TRACE_EVENT(ib_mad_recv_done_handler, + __entry->slid = wc->slid; + __entry->src_qp = wc->src_qp; + __entry->sl = wc->sl; +- ib_query_pkey(qp_info->port_priv->device, +- qp_info->port_priv->port_num, +- wc->pkey_index, &__entry->pkey); + __entry->wc_status = wc->status; + ), + +@@ -234,7 +229,7 @@ TRACE_EVENT(ib_mad_recv_done_handler, + "base_ver 0x%02x class 0x%02x class_ver 0x%02x " \ + "method 0x%02x status 0x%04x class_specific 0x%04x " \ + "tid 0x%016llx attr_id 0x%04x attr_mod 0x%08x " \ +- "slid 0x%08x src QP%d, sl %d pkey 0x%04x", ++ "slid 0x%08x src QP%d, sl %d", + __entry->dev_index, __entry->port_num, __entry->qp_num, + __entry->wc_status, + __entry->length, +@@ -244,7 +239,7 @@ TRACE_EVENT(ib_mad_recv_done_handler, + be16_to_cpu(__entry->class_specific), + be64_to_cpu(__entry->tid), be16_to_cpu(__entry->attr_id), + be32_to_cpu(__entry->attr_mod), +- __entry->slid, __entry->src_qp, __entry->sl, __entry->pkey ++ __entry->slid, __entry->src_qp, __entry->sl + ) + ); + +-- +2.53.0 + diff --git a/queue-5.10/ipv6-add-null-checks-for-idev-in-srv6-paths.patch b/queue-5.10/ipv6-add-null-checks-for-idev-in-srv6-paths.patch new file mode 100644 index 0000000000..f0b501ab17 --- /dev/null +++ b/queue-5.10/ipv6-add-null-checks-for-idev-in-srv6-paths.patch @@ -0,0 +1,60 @@ +From 2874b2e897dbd331c8790ce67932ed9916f68984 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 13:43:34 +0800 +Subject: ipv6: add NULL checks for idev in SRv6 paths + +From: Minhong He + +[ Upstream commit 06413793526251870e20402c39930804f14d59c0 ] + +__in6_dev_get() can return NULL when the device has no IPv6 configuration +(e.g. MTU < IPV6_MIN_MTU or after NETDEV_UNREGISTER). + +Add NULL checks for idev returned by __in6_dev_get() in both +seg6_hmac_validate_skb() and ipv6_srh_rcv() to prevent potential NULL +pointer dereferences. + +Fixes: 1ababeba4a21 ("ipv6: implement dataplane support for rthdr type 4 (Segment Routing Header)") +Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") +Signed-off-by: Minhong He +Reviewed-by: Andrea Mayer +Link: https://patch.msgid.link/20260316073301.106643-1-heminhong@kylinos.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + net/ipv6/exthdrs.c | 4 ++++ + net/ipv6/seg6_hmac.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index cdad9019c77c4..dfa0fb3d6c35f 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -361,6 +361,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) + hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); + + idev = __in6_dev_get(skb->dev); ++ if (!idev) { ++ kfree_skb(skb); ++ return -1; ++ } + + accept_seg6 = net->ipv6.devconf_all->seg6_enabled; + if (accept_seg6 > idev->cnf.seg6_enabled) +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index f82fcd8908e14..b52985c867c29 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -245,6 +245,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) + struct inet6_dev *idev; + + idev = __in6_dev_get(skb->dev); ++ if (!idev) ++ return false; + + srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); + +-- +2.53.0 + diff --git a/queue-5.10/net-sched-act_ct-fix-ref-leak-when-switching-zones.patch b/queue-5.10/net-sched-act_ct-fix-ref-leak-when-switching-zones.patch new file mode 100644 index 0000000000..88523886fa --- /dev/null +++ b/queue-5.10/net-sched-act_ct-fix-ref-leak-when-switching-zones.patch @@ -0,0 +1,69 @@ +From f025eecbed345ba9801b7a92dc364b173500ae9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:24:47 +0300 +Subject: net/sched: act_ct: fix ref leak when switching zones + +From: Marcelo Ricardo Leitner + +commit bcb74e132a76ce0502bb33d5b65533a4ed72d159 upstream. + +When switching zones or network namespaces without doing a ct clear in +between, it is now leaking a reference to the old ct entry. That's +because tcf_ct_skb_nfct_cached() returns false and +tcf_ct_flow_table_lookup() may simply overwrite it. + +The fix is to, as the ct entry is not reusable, free it already at +tcf_ct_skb_nfct_cached(). + +Reported-by: Florian Westphal +Fixes: 2f131de361f6 ("net/sched: act_ct: Fix flow table lookup after ct clear or switching zones") +Signed-off-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +[ kovalev: bp to fix CVE-2022-49183; used nf_conntrack_put(&ct->ct_general) + instead of nf_ct_put(ct) due to the older kernel not yet having the + conversion from the indirect call (see upstream commit 408bdcfce8df) ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + net/sched/act_ct.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c +index d9748c917a503..d75f4b2b97daa 100644 +--- a/net/sched/act_ct.c ++++ b/net/sched/act_ct.c +@@ -589,22 +589,25 @@ static bool tcf_ct_skb_nfct_cached(struct net *net, struct sk_buff *skb, + if (!ct) + return false; + if (!net_eq(net, read_pnet(&ct->ct_net))) +- return false; ++ goto drop_ct; + if (nf_ct_zone(ct)->id != zone_id) +- return false; ++ goto drop_ct; + + /* Force conntrack entry direction. */ + if (force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) { + if (nf_ct_is_confirmed(ct)) + nf_ct_kill(ct); + +- nf_conntrack_put(&ct->ct_general); +- nf_ct_set(skb, NULL, IP_CT_UNTRACKED); +- +- return false; ++ goto drop_ct; + } + + return true; ++ ++drop_ct: ++ nf_conntrack_put(&ct->ct_general); ++ nf_ct_set(skb, NULL, IP_CT_UNTRACKED); ++ ++ return false; + } + + /* Trim the skb to the length specified by the IP/IPv6 header, +-- +2.53.0 + diff --git a/queue-5.10/net-tap-null-pointer-derefence-in-dev_parse_header_p.patch b/queue-5.10/net-tap-null-pointer-derefence-in-dev_parse_header_p.patch new file mode 100644 index 0000000000..084331e64f --- /dev/null +++ b/queue-5.10/net-tap-null-pointer-derefence-in-dev_parse_header_p.patch @@ -0,0 +1,116 @@ +From f4e132dea25274f9899ddd27026c2334ae0a2ce7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:27:29 +0300 +Subject: net: tap: NULL pointer derefence in dev_parse_header_protocol when + skb->dev is null + +From: Cezar Bulinaru + +commit 4f61f133f354853bc394ec7d6028adb9b02dd701 upstream. + +Fixes a NULL pointer derefence bug triggered from tap driver. +When tap_get_user calls virtio_net_hdr_to_skb the skb->dev is null +(in tap.c skb->dev is set after the call to virtio_net_hdr_to_skb) +virtio_net_hdr_to_skb calls dev_parse_header_protocol which +needs skb->dev field to be valid. + +The line that trigers the bug is in dev_parse_header_protocol +(dev is at offset 0x10 from skb and is stored in RAX register) + if (!dev->header_ops || !dev->header_ops->parse_protocol) + 22e1: mov 0x10(%rbx),%rax + 22e5: mov 0x230(%rax),%rax + +Setting skb->dev before the call in tap.c fixes the issue. + +BUG: kernel NULL pointer dereference, address: 0000000000000230 +RIP: 0010:virtio_net_hdr_to_skb.constprop.0+0x335/0x410 [tap] +Code: c0 0f 85 b7 fd ff ff eb d4 41 39 c6 77 cf 29 c6 48 89 df 44 01 f6 e8 7a 79 83 c1 48 85 c0 0f 85 d9 fd ff ff eb b7 48 8b 43 10 <48> 8b 80 30 02 00 00 48 85 c0 74 55 48 8b 40 28 48 85 c0 74 4c 48 +RSP: 0018:ffffc90005c27c38 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: ffff888298f25300 RCX: 0000000000000010 +RDX: 0000000000000005 RSI: ffffc90005c27cb6 RDI: ffff888298f25300 +RBP: ffffc90005c27c80 R08: 00000000ffffffea R09: 00000000000007e8 +R10: ffff88858ec77458 R11: 0000000000000000 R12: 0000000000000001 +R13: 0000000000000014 R14: ffffc90005c27e08 R15: ffffc90005c27cb6 +FS: 0000000000000000(0000) GS:ffff88858ec40000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000230 CR3: 0000000281408006 CR4: 00000000003706e0 +Call Trace: + tap_get_user+0x3f1/0x540 [tap] + tap_sendmsg+0x56/0x362 [tap] + ? get_tx_bufs+0xc2/0x1e0 [vhost_net] + handle_tx_copy+0x114/0x670 [vhost_net] + handle_tx+0xb0/0xe0 [vhost_net] + handle_tx_kick+0x15/0x20 [vhost_net] + vhost_worker+0x7b/0xc0 [vhost] + ? vhost_vring_call_reset+0x40/0x40 [vhost] + kthread+0xfa/0x120 + ? kthread_complete_and_exit+0x20/0x20 + ret_from_fork+0x1f/0x30 + +Fixes: 924a9bc362a5 ("net: check if protocol extracted by virtio_net_hdr_set_proto is correct") +Signed-off-by: Cezar Bulinaru +Reviewed-by: Willem de Bruijn +Signed-off-by: David S. Miller +[ kovalev: bp to fix CVE-2022-50073 ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/net/tap.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/tap.c b/drivers/net/tap.c +index 16fa0e3e752ab..18f19fc66c64f 100644 +--- a/drivers/net/tap.c ++++ b/drivers/net/tap.c +@@ -703,11 +703,22 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, + skb_reset_mac_header(skb); + skb->protocol = eth_hdr(skb)->h_proto; + ++ rcu_read_lock(); ++ tap = rcu_dereference(q->tap); ++ if (!tap) { ++ kfree_skb(skb); ++ rcu_read_unlock(); ++ return total_len; ++ } ++ skb->dev = tap->dev; ++ + if (vnet_hdr_len) { + err = virtio_net_hdr_to_skb(skb, &vnet_hdr, + tap_is_little_endian(q)); +- if (err) ++ if (err) { ++ rcu_read_unlock(); + goto err_kfree; ++ } + } + + skb_probe_transport_header(skb); +@@ -717,8 +728,6 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, + vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0) + skb_set_network_header(skb, depth); + +- rcu_read_lock(); +- tap = rcu_dereference(q->tap); + /* copy skb_ubuf_info for callback when skb has no error */ + if (zerocopy) { + skb_shinfo(skb)->destructor_arg = msg_control; +@@ -729,14 +738,8 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, + uarg->callback(uarg, false); + } + +- if (tap) { +- skb->dev = tap->dev; +- dev_queue_xmit(skb); +- } else { +- kfree_skb(skb); +- } ++ dev_queue_xmit(skb); + rcu_read_unlock(); +- + return total_len; + + err_kfree: +-- +2.53.0 + diff --git a/queue-5.10/scsi-qla2xxx-fix-crash-when-i-o-abort-times-out.patch b/queue-5.10/scsi-qla2xxx-fix-crash-when-i-o-abort-times-out.patch new file mode 100644 index 0000000000..5477632322 --- /dev/null +++ b/queue-5.10/scsi-qla2xxx-fix-crash-when-i-o-abort-times-out.patch @@ -0,0 +1,96 @@ +From 286424098d655ba449dac91350c21ebc2f791cbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:23:27 +0300 +Subject: scsi: qla2xxx: Fix crash when I/O abort times out + +From: Arun Easi + +commit 68ad83188d782b2ecef2e41ac245d27e0710fe8e upstream. + +While performing CPU hotplug, a crash with the following stack was seen: + +Call Trace: + qla24xx_process_response_queue+0x42a/0x970 [qla2xxx] + qla2x00_start_nvme_mq+0x3a2/0x4b0 [qla2xxx] + qla_nvme_post_cmd+0x166/0x240 [qla2xxx] + nvme_fc_start_fcp_op.part.0+0x119/0x2e0 [nvme_fc] + blk_mq_dispatch_rq_list+0x17b/0x610 + __blk_mq_sched_dispatch_requests+0xb0/0x140 + blk_mq_sched_dispatch_requests+0x30/0x60 + __blk_mq_run_hw_queue+0x35/0x90 + __blk_mq_delay_run_hw_queue+0x161/0x180 + blk_execute_rq+0xbe/0x160 + __nvme_submit_sync_cmd+0x16f/0x220 [nvme_core] + nvmf_connect_admin_queue+0x11a/0x170 [nvme_fabrics] + nvme_fc_create_association.cold+0x50/0x3dc [nvme_fc] + nvme_fc_connect_ctrl_work+0x19/0x30 [nvme_fc] + process_one_work+0x1e8/0x3c0 + +On abort timeout, completion was called without checking if the I/O was +already completed. + +Verify that I/O and abort request are indeed outstanding before attempting +completion. + +Fixes: 71c80b75ce8f ("scsi: qla2xxx: Do command completion on abort timeout") +Reported-by: Marco Patalano +Tested-by: Marco Patalano +Cc: stable@vger.kernel.org +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Link: https://lore.kernel.org/r/20221129092634.15347-1-njavali@marvell.com +Signed-off-by: Martin K. Petersen +[ kovalev: bp to fix CVE-2022-50493 ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_init.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 79b9571f63508..4a057748ba175 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -101,6 +101,7 @@ static void qla24xx_abort_iocb_timeout(void *data) + struct qla_qpair *qpair = sp->qpair; + u32 handle; + unsigned long flags; ++ int sp_found = 0, cmdsp_found = 0; + + if (sp->cmd_sp) + ql_dbg(ql_dbg_async, sp->vha, 0x507c, +@@ -115,22 +116,27 @@ static void qla24xx_abort_iocb_timeout(void *data) + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) { + if (sp->cmd_sp && (qpair->req->outstanding_cmds[handle] == +- sp->cmd_sp)) ++ sp->cmd_sp)) { + qpair->req->outstanding_cmds[handle] = NULL; ++ cmdsp_found = 1; ++ } + + /* removing the abort */ + if (qpair->req->outstanding_cmds[handle] == sp) { + qpair->req->outstanding_cmds[handle] = NULL; ++ sp_found = 1; + break; + } + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + +- if (sp->cmd_sp) ++ if (cmdsp_found && sp->cmd_sp) + sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED); + +- abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT); +- sp->done(sp, QLA_OS_TIMER_EXPIRED); ++ if (sp_found) { ++ abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT); ++ sp->done(sp, QLA_OS_TIMER_EXPIRED); ++ } + } + + static void qla24xx_abort_sp_done(srb_t *sp, int res) +-- +2.53.0 + diff --git a/queue-5.10/scsi-qla2xxx-fix-warning-message-due-to-adisc-being-.patch b/queue-5.10/scsi-qla2xxx-fix-warning-message-due-to-adisc-being-.patch new file mode 100644 index 0000000000..ca2ff7a5ab --- /dev/null +++ b/queue-5.10/scsi-qla2xxx-fix-warning-message-due-to-adisc-being-.patch @@ -0,0 +1,93 @@ +From 74b20bde9cca494db3cf5a277eaf41d393fe0318 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:23:26 +0300 +Subject: scsi: qla2xxx: Fix warning message due to adisc being flushed + +From: Quinn Tran + +commit 64f24af75b79cba3b86b0760e27e0fa904db570f upstream. + +Fix warning message due to adisc being flushed. Linux kernel triggered a +warning message where a different error code type is not matching up with +the expected type. Add additional translation of one error code type to +another. + +WARNING: CPU: 2 PID: 1131623 at drivers/scsi/qla2xxx/qla_init.c:498 +qla2x00_async_adisc_sp_done+0x294/0x2b0 [qla2xxx] +CPU: 2 PID: 1131623 Comm: drmgr Not tainted 5.13.0-rc1-autotest #1 +.. +GPR28: c000000aaa9c8890 c0080000079ab678 c00000140a104800 c00000002bd19000 +NIP [c00800000790857c] qla2x00_async_adisc_sp_done+0x294/0x2b0 [qla2xxx] +LR [c008000007908578] qla2x00_async_adisc_sp_done+0x290/0x2b0 [qla2xxx] +Call Trace: +[c00000001cdc3620] [c008000007908578] qla2x00_async_adisc_sp_done+0x290/0x2b0 [qla2xxx] (unreliable) +[c00000001cdc3710] [c0080000078f3080] __qla2x00_abort_all_cmds+0x1b8/0x580 [qla2xxx] +[c00000001cdc3840] [c0080000078f589c] qla2x00_abort_all_cmds+0x34/0xd0 [qla2xxx] +[c00000001cdc3880] [c0080000079153d8] qla2x00_abort_isp_cleanup+0x3f0/0x570 [qla2xxx] +[c00000001cdc3920] [c0080000078fb7e8] qla2x00_remove_one+0x3d0/0x480 [qla2xxx] +[c00000001cdc39b0] [c00000000071c274] pci_device_remove+0x64/0x120 +[c00000001cdc39f0] [c0000000007fb818] device_release_driver_internal+0x168/0x2a0 +[c00000001cdc3a30] [c00000000070e304] pci_stop_bus_device+0xb4/0x100 +[c00000001cdc3a70] [c00000000070e4f0] pci_stop_and_remove_bus_device+0x20/0x40 +[c00000001cdc3aa0] [c000000000073940] pci_hp_remove_devices+0x90/0x130 +[c00000001cdc3b30] [c0080000070704d0] disable_slot+0x38/0x90 [rpaphp] [ +c00000001cdc3b60] [c00000000073eb4c] power_write_file+0xcc/0x180 +[c00000001cdc3be0] [c0000000007354bc] pci_slot_attr_store+0x3c/0x60 +[c00000001cdc3c00] [c00000000055f820] sysfs_kf_write+0x60/0x80 [c00000001cdc3c20] +[c00000000055df10] kernfs_fop_write_iter+0x1a0/0x290 +[c00000001cdc3c70] [c000000000447c4c] new_sync_write+0x14c/0x1d0 +[c00000001cdc3d10] [c00000000044b134] vfs_write+0x224/0x330 +[c00000001cdc3d60] [c00000000044b3f4] ksys_write+0x74/0x130 +[c00000001cdc3db0] [c00000000002df70] system_call_exception+0x150/0x2d0 +[c00000001cdc3e10] [c00000000000d45c] system_call_common+0xec/0x278 + +Link: https://lore.kernel.org/r/20220110050218.3958-5-njavali@marvell.com +Cc: stable@vger.kernel.org +Reported-by: Abdul Haleem +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +[ kovalev: bp to fix CVE-2022-49158; in qla2x00_async_prli_sp_done used + 'if (res)' instead of 'else if (res)' due to the older kernel not having + the preceding QLA_OS_TIMER_EXPIRED check (see upstream commit 4de067e5df12) ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 7b6227fde7beb..79b9571f63508 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -283,6 +283,8 @@ static void qla2x00_async_login_sp_done(srb_t *sp, int res) + ea.iop[0] = lio->u.logio.iop[0]; + ea.iop[1] = lio->u.logio.iop[1]; + ea.sp = sp; ++ if (res) ++ ea.data[0] = MBS_COMMAND_ERROR; + qla24xx_handle_plogi_done_event(vha, &ea); + } + +@@ -563,6 +565,8 @@ static void qla2x00_async_adisc_sp_done(srb_t *sp, int res) + ea.iop[1] = lio->u.logio.iop[1]; + ea.fcport = sp->fcport; + ea.sp = sp; ++ if (res) ++ ea.data[0] = MBS_COMMAND_ERROR; + + qla24xx_handle_adisc_event(vha, &ea); + +@@ -1238,6 +1242,8 @@ static void qla2x00_async_prli_sp_done(srb_t *sp, int res) + ea.iop[0] = lio->u.logio.iop[0]; + ea.iop[1] = lio->u.logio.iop[1]; + ea.sp = sp; ++ if (res) ++ ea.data[0] = MBS_COMMAND_ERROR; + + qla24xx_handle_prli_done_event(vha, &ea); + } +-- +2.53.0 + diff --git a/queue-5.10/scsi-ufs-core-improve-scsi-abort-handling.patch b/queue-5.10/scsi-ufs-core-improve-scsi-abort-handling.patch new file mode 100644 index 0000000000..f31056aba7 --- /dev/null +++ b/queue-5.10/scsi-ufs-core-improve-scsi-abort-handling.patch @@ -0,0 +1,56 @@ +From 5a2afeda3b653b526b28333764e532c5cd1f929e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:19:41 +0300 +Subject: scsi: ufs: core: Improve SCSI abort handling + +From: Bart Van Assche + +commit 3ff1f6b6ba6f97f50862aa50e79959cc8ddc2566 upstream. + +The following has been observed on a test setup: + +WARNING: CPU: 4 PID: 250 at drivers/scsi/ufs/ufshcd.c:2737 ufshcd_queuecommand+0x468/0x65c +Call trace: + ufshcd_queuecommand+0x468/0x65c + scsi_send_eh_cmnd+0x224/0x6a0 + scsi_eh_test_devices+0x248/0x418 + scsi_eh_ready_devs+0xc34/0xe58 + scsi_error_handler+0x204/0x80c + kthread+0x150/0x1b4 + ret_from_fork+0x10/0x30 + +That warning is triggered by the following statement: + + WARN_ON(lrbp->cmd); + +Fix this warning by clearing lrbp->cmd from the abort handler. + +Link: https://lore.kernel.org/r/20211104181059.4129537-1-bvanassche@acm.org +Fixes: 7a3e97b0dc4b ("[SCSI] ufshcd: UFS Host controller driver") +Reviewed-by: Bean Huo +Reviewed-by: Stanley Chu +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +[ kovalev: bp to fix CVE-2021-47188; adapted placement of + lrbp->cmd = NULL for 5.10 function structure ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/scsi/ufs/ufshcd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index c7bf0e6bc303d..1b8072f47e7e8 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -6788,6 +6788,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) + __ufshcd_transfer_req_compl(hba, (1UL << tag)); + spin_unlock_irqrestore(host->host_lock, flags); + out: ++ lrbp->cmd = NULL; + err = SUCCESS; + } else { + dev_err(hba->dev, "%s: failed with err %d\n", __func__, err); +-- +2.53.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 74c1b215db..296a6bc7b2 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -82,3 +82,18 @@ media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_p nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch +net-tap-null-pointer-derefence-in-dev_parse_header_p.patch +scsi-qla2xxx-fix-warning-message-due-to-adisc-being-.patch +scsi-qla2xxx-fix-crash-when-i-o-abort-times-out.patch +net-sched-act_ct-fix-ref-leak-when-switching-zones.patch +bpf-sockmap-fix-an-infinite-loop-error-when-len-is-0.patch +ipv6-add-null-checks-for-idev-in-srv6-paths.patch +drm-amd-display-add-null-checker-before-passing-vari.patch +wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch +cifs-fix-connections-leak-when-tlink-setup-failed.patch +drm-amd-display-fix-memory-leak.patch +thermal-int340x_thermal-handle-data_vault-when-the-v.patch +blk-cgroup-reinit-blkg_iostat_set-after-clearing-in-.patch +alsa-usb-audio-fix-null-pointer-dereference-on-point.patch +scsi-ufs-core-improve-scsi-abort-handling.patch +ib-mad-don-t-call-to-function-that-might-sleep-while.patch diff --git a/queue-5.10/thermal-int340x_thermal-handle-data_vault-when-the-v.patch b/queue-5.10/thermal-int340x_thermal-handle-data_vault-when-the-v.patch new file mode 100644 index 0000000000..53ba33f78e --- /dev/null +++ b/queue-5.10/thermal-int340x_thermal-handle-data_vault-when-the-v.patch @@ -0,0 +1,75 @@ +From ab20b150597d6322a7e833c42ea1a23d70673a13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:21:30 +0300 +Subject: thermal/int340x_thermal: handle data_vault when the value is + ZERO_SIZE_PTR + +From: Lee, Chun-Yi + +commit 7931e28098a4c1a2a6802510b0cbe57546d2049d upstream. + +In some case, the GDDV returns a package with a buffer which has +zero length. It causes that kmemdup() returns ZERO_SIZE_PTR (0x10). + +Then the data_vault_read() got NULL point dereference problem when +accessing the 0x10 value in data_vault. + +[ 71.024560] BUG: kernel NULL pointer dereference, address: +0000000000000010 + +This patch uses ZERO_OR_NULL_PTR() for checking ZERO_SIZE_PTR or +NULL value in data_vault. + +Signed-off-by: "Lee, Chun-Yi" +Signed-off-by: Rafael J. Wysocki +[ kovalev: bp to fix CVE-2022-48703 ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/thermal/intel/int340x_thermal/int3400_thermal.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +index 28913867cd4bc..a064a4eb31fba 100644 +--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c ++++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +@@ -466,7 +466,7 @@ static void int3400_setup_gddv(struct int3400_thermal_priv *priv) + priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer, + obj->package.elements[0].buffer.length, + GFP_KERNEL); +- if (!priv->data_vault) { ++ if (ZERO_OR_NULL_PTR(priv->data_vault)) { + kfree(buffer.pointer); + return; + } +@@ -531,7 +531,7 @@ static int int3400_thermal_probe(struct platform_device *pdev) + if (result) + goto free_rel_misc; + +- if (priv->data_vault) { ++ if (!ZERO_OR_NULL_PTR(priv->data_vault)) { + result = sysfs_create_group(&pdev->dev.kobj, + &data_attribute_group); + if (result) +@@ -549,7 +549,8 @@ static int int3400_thermal_probe(struct platform_device *pdev) + free_sysfs: + cleanup_odvp(priv); + if (priv->data_vault) { +- sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group); ++ if (!ZERO_OR_NULL_PTR(priv->data_vault)) ++ sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group); + kfree(priv->data_vault); + } + free_uuid: +@@ -579,7 +580,7 @@ static int int3400_thermal_remove(struct platform_device *pdev) + if (!priv->rel_misc_dev_res) + acpi_thermal_rel_misc_device_remove(priv->adev->handle); + +- if (priv->data_vault) ++ if (!ZERO_OR_NULL_PTR(priv->data_vault)) + sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group); + sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group); + thermal_zone_device_unregister(priv->thermal); +-- +2.53.0 + diff --git a/queue-5.10/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch b/queue-5.10/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch new file mode 100644 index 0000000000..3c5224b31f --- /dev/null +++ b/queue-5.10/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch @@ -0,0 +1,107 @@ +From 105fafbfdf62b72afad64d3ab58d103540cb5273 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 10:44:25 +0800 +Subject: wifi: mac80211: always free skb on ieee80211_tx_prepare_skb() failure + +From: Felix Fietkau + +[ Upstream commit d5ad6ab61cbd89afdb60881f6274f74328af3ee9 ] + +ieee80211_tx_prepare_skb() has three error paths, but only two of them +free the skb. The first error path (ieee80211_tx_prepare() returning +TX_DROP) does not free it, while invoke_tx_handlers() failure and the +fragmentation check both do. + +Add kfree_skb() to the first error path so all three are consistent, +and remove the now-redundant frees in callers (ath9k, mt76, +mac80211_hwsim) to avoid double-free. + +Document the skb ownership guarantee in the function's kdoc. + +Signed-off-by: Felix Fietkau +Link: https://patch.msgid.link/20260314065455.2462900-1-nbd@nbd.name +Fixes: 06be6b149f7e ("mac80211: add ieee80211_tx_prepare_skb() helper function") +Signed-off-by: Johannes Berg +[ Exclude changes to drivers/net/wireless/mediatek/mt76/scan.c as this file is first + introduced by commit 31083e38548f("wifi: mt76: add code for emulating hardware scanning") + after linux-6.14.] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/channel.c | 6 ++---- + drivers/net/wireless/mac80211_hwsim.c | 1 - + include/net/mac80211.h | 4 ++++ + net/mac80211/tx.c | 4 +++- + 4 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c +index 6cf0875221572..31b7921bf34f3 100644 +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -1011,7 +1011,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + + if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) +- goto error; ++ return; + + txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; + if (ath_tx_start(sc->hw, skb, &txctl)) +@@ -1124,10 +1124,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, + + skb->priority = 7; + skb_set_queue_mapping(skb, IEEE80211_AC_VO); +- if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { +- dev_kfree_skb_any(skb); ++ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) + return false; +- } + break; + default: + return false; +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 037358606a51a..865bbe0293436 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2275,7 +2275,6 @@ static void hw_scan_work(struct work_struct *work) + hwsim->tmp_chan->band, + NULL)) { + rcu_read_unlock(); +- kfree_skb(probe); + continue; + } + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 8f91609f928c1..70ee982f08d9d 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6337,6 +6337,10 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, + * @band: the band to transmit on + * @sta: optional pointer to get the station to send the frame to + * ++ * Return: %true if the skb was prepared, %false otherwise. ++ * On failure, the skb is freed by this function; callers must not ++ * free it again. ++ * + * Note: must be called under RCU lock + */ + bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 30ad46cfcad86..b923cd755a68c 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1869,8 +1869,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, + struct ieee80211_tx_data tx; + struct sk_buff *skb2; + +- if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) ++ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) { ++ kfree_skb(skb); + return false; ++ } + + info->band = band; + info->control.vif = vif; +-- +2.53.0 + diff --git a/queue-5.15/gfs2-improve-gfs2_consist_inode-usage.patch b/queue-5.15/gfs2-improve-gfs2_consist_inode-usage.patch new file mode 100644 index 0000000000..9ef9464346 --- /dev/null +++ b/queue-5.15/gfs2-improve-gfs2_consist_inode-usage.patch @@ -0,0 +1,213 @@ +From cd5479151b7db88bc636e9e58835cd4b3514dd75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 18:40:20 +0800 +Subject: gfs2: Improve gfs2_consist_inode() usage + +From: Andrew Price + +[ Upstream commit 10398ef57aa189153406c110f5957145030f08fe ] + +gfs2_consist_inode() logs an error message with the source file and line +number. When we jump before calling it, the line number becomes less +useful as it no longer relates to the source of the error. To aid +troubleshooting, replace the gotos with the gfs2_consist_inode() calls +so that the error messages are more informative. + +Signed-off-by: Andrew Price +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Ruohan Lan +Signed-off-by: Sasha Levin +--- + fs/gfs2/dir.c | 31 +++++++++++++++++-------------- + fs/gfs2/glops.c | 34 ++++++++++++++++++++-------------- + fs/gfs2/xattr.c | 28 ++++++++++++++++------------ + 3 files changed, 53 insertions(+), 40 deletions(-) + +diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c +index 42b7dfffb5e7e..e1bdc4b0608c2 100644 +--- a/fs/gfs2/dir.c ++++ b/fs/gfs2/dir.c +@@ -562,15 +562,18 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, + int ret = 0; + + ret = gfs2_dirent_offset(GFS2_SB(inode), buf); +- if (ret < 0) +- goto consist_inode; +- ++ if (ret < 0) { ++ gfs2_consist_inode(GFS2_I(inode)); ++ return ERR_PTR(-EIO); ++ } + offset = ret; + prev = NULL; + dent = buf + offset; + size = be16_to_cpu(dent->de_rec_len); +- if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1)) +- goto consist_inode; ++ if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1)) { ++ gfs2_consist_inode(GFS2_I(inode)); ++ return ERR_PTR(-EIO); ++ } + do { + ret = scan(dent, name, opaque); + if (ret) +@@ -582,8 +585,10 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, + dent = buf + offset; + size = be16_to_cpu(dent->de_rec_len); + if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, +- len, 0)) +- goto consist_inode; ++ len, 0)) { ++ gfs2_consist_inode(GFS2_I(inode)); ++ return ERR_PTR(-EIO); ++ } + } while(1); + + switch(ret) { +@@ -597,10 +602,6 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, + BUG_ON(ret > 0); + return ERR_PTR(ret); + } +- +-consist_inode: +- gfs2_consist_inode(GFS2_I(inode)); +- return ERR_PTR(-EIO); + } + + static int dirent_check_reclen(struct gfs2_inode *dip, +@@ -609,14 +610,16 @@ static int dirent_check_reclen(struct gfs2_inode *dip, + const void *ptr = d; + u16 rec_len = be16_to_cpu(d->de_rec_len); + +- if (unlikely(rec_len < sizeof(struct gfs2_dirent))) +- goto broken; ++ if (unlikely(rec_len < sizeof(struct gfs2_dirent))) { ++ gfs2_consist_inode(dip); ++ return -EIO; ++ } + ptr += rec_len; + if (ptr < end_p) + return rec_len; + if (ptr == end_p) + return -ENOENT; +-broken: ++ + gfs2_consist_inode(dip); + return -EIO; + } +diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c +index 5a4b3550d833f..fdbae357727b2 100644 +--- a/fs/gfs2/glops.c ++++ b/fs/gfs2/glops.c +@@ -405,10 +405,14 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) + struct inode *inode = &ip->i_inode; + bool is_new = inode->i_state & I_NEW; + +- if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) +- goto corrupt; +- if (unlikely(!is_new && inode_wrong_type(inode, mode))) +- goto corrupt; ++ if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } ++ if (unlikely(!is_new && inode_wrong_type(inode, mode))) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); + inode->i_mode = mode; + if (is_new) { +@@ -444,26 +448,28 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) + /* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */ + gfs2_set_inode_flags(inode); + height = be16_to_cpu(str->di_height); +- if (unlikely(height > sdp->sd_max_height)) +- goto corrupt; ++ if (unlikely(height > sdp->sd_max_height)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_height = (u8)height; + + depth = be16_to_cpu(str->di_depth); +- if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) +- goto corrupt; ++ if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_depth = (u8)depth; + ip->i_entries = be32_to_cpu(str->di_entries); + +- if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) +- goto corrupt; +- ++ if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + if (S_ISREG(inode->i_mode)) + gfs2_set_aops(inode); + + return 0; +-corrupt: +- gfs2_consist_inode(ip); +- return -EIO; + } + + /** +diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c +index 0c5650fe1fd18..2b0fe8cf2173a 100644 +--- a/fs/gfs2/xattr.c ++++ b/fs/gfs2/xattr.c +@@ -96,30 +96,34 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh, + return -EIO; + + for (ea = GFS2_EA_BH2FIRST(bh);; prev = ea, ea = GFS2_EA2NEXT(ea)) { +- if (!GFS2_EA_REC_LEN(ea)) +- goto fail; ++ if (!GFS2_EA_REC_LEN(ea)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <= +- bh->b_data + bh->b_size)) +- goto fail; +- if (!gfs2_eatype_valid(sdp, ea->ea_type)) +- goto fail; ++ bh->b_data + bh->b_size)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } ++ if (!gfs2_eatype_valid(sdp, ea->ea_type)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + error = ea_call(ip, bh, ea, prev, data); + if (error) + return error; + + if (GFS2_EA_IS_LAST(ea)) { + if ((char *)GFS2_EA2NEXT(ea) != +- bh->b_data + bh->b_size) +- goto fail; ++ bh->b_data + bh->b_size) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + break; + } + } + + return error; +- +-fail: +- gfs2_consist_inode(ip); +- return -EIO; + } + + static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data) +-- +2.53.0 + diff --git a/queue-5.15/gfs2-validate-i_depth-for-exhash-directories.patch b/queue-5.15/gfs2-validate-i_depth-for-exhash-directories.patch new file mode 100644 index 0000000000..d0c74b0e14 --- /dev/null +++ b/queue-5.15/gfs2-validate-i_depth-for-exhash-directories.patch @@ -0,0 +1,95 @@ +From d8ebb52ffe41a26abae6c8b3c697b6da0646e6d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 18:40:21 +0800 +Subject: gfs2: Validate i_depth for exhash directories + +From: Andrew Price + +[ Upstream commit 557c024ca7250bb65ae60f16c02074106c2f197b ] + +A fuzzer test introduced corruption that ends up with a depth of 0 in +dir_e_read(), causing an undefined shift by 32 at: + + index = hash >> (32 - dip->i_depth); + +As calculated in an open-coded way in dir_make_exhash(), the minimum +depth for an exhash directory is ilog2(sdp->sd_hash_ptrs) and 0 is +invalid as sdp->sd_hash_ptrs is fixed as sdp->bsize / 16 at mount time. + +So we can avoid the undefined behaviour by checking for depth values +lower than the minimum in gfs2_dinode_in(). Values greater than the +maximum are already being checked for there. + +Also switch the calculation in dir_make_exhash() to use ilog2() to +clarify how the depth is calculated. + +Tested with the syzkaller repro.c and xfstests '-g quick'. + +Reported-by: syzbot+4708579bb230a0582a57@syzkaller.appspotmail.com +Signed-off-by: Andrew Price +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Ruohan Lan +Signed-off-by: Sasha Levin +--- + fs/gfs2/dir.c | 6 ++---- + fs/gfs2/glops.c | 6 ++++++ + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c +index e1bdc4b0608c2..559cad553db62 100644 +--- a/fs/gfs2/dir.c ++++ b/fs/gfs2/dir.c +@@ -60,6 +60,7 @@ + #include + #include + #include ++#include + + #include "gfs2.h" + #include "incore.h" +@@ -912,7 +913,6 @@ static int dir_make_exhash(struct inode *inode) + struct qstr args; + struct buffer_head *bh, *dibh; + struct gfs2_leaf *leaf; +- int y; + u32 x; + __be64 *lp; + u64 bn; +@@ -979,9 +979,7 @@ static int dir_make_exhash(struct inode *inode) + i_size_write(inode, sdp->sd_sb.sb_bsize / 2); + gfs2_add_inode_blocks(&dip->i_inode, 1); + dip->i_diskflags |= GFS2_DIF_EXHASH; +- +- for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; +- dip->i_depth = y; ++ dip->i_depth = ilog2(sdp->sd_hash_ptrs); + + gfs2_dinode_out(dip, dibh->b_data); + +diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c +index fdbae357727b2..8a077de9ee0a4 100644 +--- a/fs/gfs2/glops.c ++++ b/fs/gfs2/glops.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "gfs2.h" + #include "incore.h" +@@ -459,6 +460,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) + gfs2_consist_inode(ip); + return -EIO; + } ++ if ((ip->i_diskflags & GFS2_DIF_EXHASH) && ++ depth < ilog2(sdp->sd_hash_ptrs)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_depth = (u8)depth; + ip->i_entries = be32_to_cpu(str->di_entries); + +-- +2.53.0 + diff --git a/queue-5.15/ipv6-add-null-checks-for-idev-in-srv6-paths.patch b/queue-5.15/ipv6-add-null-checks-for-idev-in-srv6-paths.patch new file mode 100644 index 0000000000..473c34d32b --- /dev/null +++ b/queue-5.15/ipv6-add-null-checks-for-idev-in-srv6-paths.patch @@ -0,0 +1,60 @@ +From d2c76cfe8401165b523489f1af820b690190108c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 13:43:21 +0800 +Subject: ipv6: add NULL checks for idev in SRv6 paths + +From: Minhong He + +[ Upstream commit 06413793526251870e20402c39930804f14d59c0 ] + +__in6_dev_get() can return NULL when the device has no IPv6 configuration +(e.g. MTU < IPV6_MIN_MTU or after NETDEV_UNREGISTER). + +Add NULL checks for idev returned by __in6_dev_get() in both +seg6_hmac_validate_skb() and ipv6_srh_rcv() to prevent potential NULL +pointer dereferences. + +Fixes: 1ababeba4a21 ("ipv6: implement dataplane support for rthdr type 4 (Segment Routing Header)") +Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") +Signed-off-by: Minhong He +Reviewed-by: Andrea Mayer +Link: https://patch.msgid.link/20260316073301.106643-1-heminhong@kylinos.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + net/ipv6/exthdrs.c | 4 ++++ + net/ipv6/seg6_hmac.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 10772dab66bbd..3d249c10e3e9b 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -373,6 +373,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) + hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); + + idev = __in6_dev_get(skb->dev); ++ if (!idev) { ++ kfree_skb(skb); ++ return -1; ++ } + + accept_seg6 = net->ipv6.devconf_all->seg6_enabled; + if (accept_seg6 > idev->cnf.seg6_enabled) +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index 7e3a857699322..68acff337e414 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -244,6 +244,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) + struct inet6_dev *idev; + + idev = __in6_dev_get(skb->dev); ++ if (!idev) ++ return false; + + srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); + +-- +2.53.0 + diff --git a/queue-5.15/net-tap-null-pointer-derefence-in-dev_parse_header_p.patch b/queue-5.15/net-tap-null-pointer-derefence-in-dev_parse_header_p.patch new file mode 100644 index 0000000000..dd7b4480a7 --- /dev/null +++ b/queue-5.15/net-tap-null-pointer-derefence-in-dev_parse_header_p.patch @@ -0,0 +1,116 @@ +From b66b87094b3ac935c867c707736562d16a66605b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:27:02 +0300 +Subject: net: tap: NULL pointer derefence in dev_parse_header_protocol when + skb->dev is null + +From: Cezar Bulinaru + +commit 4f61f133f354853bc394ec7d6028adb9b02dd701 upstream. + +Fixes a NULL pointer derefence bug triggered from tap driver. +When tap_get_user calls virtio_net_hdr_to_skb the skb->dev is null +(in tap.c skb->dev is set after the call to virtio_net_hdr_to_skb) +virtio_net_hdr_to_skb calls dev_parse_header_protocol which +needs skb->dev field to be valid. + +The line that trigers the bug is in dev_parse_header_protocol +(dev is at offset 0x10 from skb and is stored in RAX register) + if (!dev->header_ops || !dev->header_ops->parse_protocol) + 22e1: mov 0x10(%rbx),%rax + 22e5: mov 0x230(%rax),%rax + +Setting skb->dev before the call in tap.c fixes the issue. + +BUG: kernel NULL pointer dereference, address: 0000000000000230 +RIP: 0010:virtio_net_hdr_to_skb.constprop.0+0x335/0x410 [tap] +Code: c0 0f 85 b7 fd ff ff eb d4 41 39 c6 77 cf 29 c6 48 89 df 44 01 f6 e8 7a 79 83 c1 48 85 c0 0f 85 d9 fd ff ff eb b7 48 8b 43 10 <48> 8b 80 30 02 00 00 48 85 c0 74 55 48 8b 40 28 48 85 c0 74 4c 48 +RSP: 0018:ffffc90005c27c38 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: ffff888298f25300 RCX: 0000000000000010 +RDX: 0000000000000005 RSI: ffffc90005c27cb6 RDI: ffff888298f25300 +RBP: ffffc90005c27c80 R08: 00000000ffffffea R09: 00000000000007e8 +R10: ffff88858ec77458 R11: 0000000000000000 R12: 0000000000000001 +R13: 0000000000000014 R14: ffffc90005c27e08 R15: ffffc90005c27cb6 +FS: 0000000000000000(0000) GS:ffff88858ec40000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000230 CR3: 0000000281408006 CR4: 00000000003706e0 +Call Trace: + tap_get_user+0x3f1/0x540 [tap] + tap_sendmsg+0x56/0x362 [tap] + ? get_tx_bufs+0xc2/0x1e0 [vhost_net] + handle_tx_copy+0x114/0x670 [vhost_net] + handle_tx+0xb0/0xe0 [vhost_net] + handle_tx_kick+0x15/0x20 [vhost_net] + vhost_worker+0x7b/0xc0 [vhost] + ? vhost_vring_call_reset+0x40/0x40 [vhost] + kthread+0xfa/0x120 + ? kthread_complete_and_exit+0x20/0x20 + ret_from_fork+0x1f/0x30 + +Fixes: 924a9bc362a5 ("net: check if protocol extracted by virtio_net_hdr_set_proto is correct") +Signed-off-by: Cezar Bulinaru +Reviewed-by: Willem de Bruijn +Signed-off-by: David S. Miller +[ kovalev: bp to fix CVE-2022-50073 ] +Signed-off-by: Vasiliy Kovalev +Signed-off-by: Sasha Levin +--- + drivers/net/tap.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/tap.c b/drivers/net/tap.c +index 53eadd82f9b8c..a08adca412b41 100644 +--- a/drivers/net/tap.c ++++ b/drivers/net/tap.c +@@ -703,11 +703,22 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, + skb_reset_mac_header(skb); + skb->protocol = eth_hdr(skb)->h_proto; + ++ rcu_read_lock(); ++ tap = rcu_dereference(q->tap); ++ if (!tap) { ++ kfree_skb(skb); ++ rcu_read_unlock(); ++ return total_len; ++ } ++ skb->dev = tap->dev; ++ + if (vnet_hdr_len) { + err = virtio_net_hdr_to_skb(skb, &vnet_hdr, + tap_is_little_endian(q)); +- if (err) ++ if (err) { ++ rcu_read_unlock(); + goto err_kfree; ++ } + } + + skb_probe_transport_header(skb); +@@ -717,8 +728,6 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, + vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0) + skb_set_network_header(skb, depth); + +- rcu_read_lock(); +- tap = rcu_dereference(q->tap); + /* copy skb_ubuf_info for callback when skb has no error */ + if (zerocopy) { + skb_zcopy_init(skb, msg_control); +@@ -727,14 +736,8 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, + uarg->callback(NULL, uarg, false); + } + +- if (tap) { +- skb->dev = tap->dev; +- dev_queue_xmit(skb); +- } else { +- kfree_skb(skb); +- } ++ dev_queue_xmit(skb); + rcu_read_unlock(); +- + return total_len; + + err_kfree: +-- +2.53.0 + diff --git a/queue-5.15/pci-acpi-restrict-program_hpx_type2-to-aer-bits.patch b/queue-5.15/pci-acpi-restrict-program_hpx_type2-to-aer-bits.patch new file mode 100644 index 0000000000..4a143eee3b --- /dev/null +++ b/queue-5.15/pci-acpi-restrict-program_hpx_type2-to-aer-bits.patch @@ -0,0 +1,202 @@ +From 46496c852cbf7eee54bc5356b906b829003f1f47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Mar 2026 18:17:36 +0100 +Subject: PCI/ACPI: Restrict program_hpx_type2() to AER bits +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HÃ¥kon Bugge + +commit 9abf79c8d7b40db0e5a34aa8c744ea60ff9a3fcf upstream. + +Previously program_hpx_type2() applied PCIe settings unconditionally, +which could incorrectly change bits like Extended Tag Field Enable and +Enable Relaxed Ordering. + +When _HPX was added to ACPI r3.0, the intent of the PCIe Setting +Record (Type 2) in sec 6.2.7.3 was to configure AER registers when the +OS does not own the AER Capability: + + The PCI Express setting record contains ... [the AER] Uncorrectable + Error Mask, Uncorrectable Error Severity, Correctable Error Mask + ... to be used when configuring registers in the Advanced Error + Reporting Extended Capability Structure ... + + OSPM [1] will only evaluate _HPX with Setting Record – Type 2 if + OSPM is not controlling the PCI Express Advanced Error Reporting + capability. + +ACPI r3.0b, sec 6.2.7.3, added more AER registers, including registers +in the PCIe Capability with AER-related bits, and the restriction that +the OS use this only when it owns PCIe native hotplug: + + ... when configuring PCI Express registers in the Advanced Error + Reporting Extended Capability Structure *or PCI Express Capability + Structure* ... + + An OS that has assumed ownership of native hot plug but does not + ... have ownership of the AER register set must use ... the Type 2 + record to program the AER registers ... + + However, since the Type 2 record also includes register bits that + have functions other than AER, the OS must ignore values ... that + are not applicable. + +Restrict program_hpx_type2() to only the intended purpose: + + - Apply settings only when OS owns PCIe native hotplug but not AER, + + - Only touch the AER-related bits (Error Reporting Enables) in Device + Control + + - Don't touch Link Control at all, since nothing there seems AER-related, + but log _HPX settings for debugging purposes + +Note that Read Completion Boundary is now configured elsewhere, since it is +unrelated to _HPX. + +[1] Operating System-directed configuration and Power Management + +Fixes: 40abb96c51bb ("[PATCH] pciehp: Fix programming hotplug parameters") +Signed-off-by: HÃ¥kon Bugge +Signed-off-by: Bjorn Helgaas +Link: https://patch.msgid.link/20260129175237.727059-3-haakon.bugge@oracle.com +[ Conflict in drivers/pci.h because the context has changed. ] +Signed-off-by: HÃ¥kon Bugge +Signed-off-by: Sasha Levin +--- + drivers/pci/pci-acpi.c | 59 +++++++++++++++++------------------------- + drivers/pci/pci.h | 3 +++ + drivers/pci/pcie/aer.c | 3 --- + 3 files changed, 27 insertions(+), 38 deletions(-) + +diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c +index 268ca998443af..5e86038f2ea5f 100644 +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -245,21 +245,6 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record, + return AE_OK; + } + +-static bool pcie_root_rcb_set(struct pci_dev *dev) +-{ +- struct pci_dev *rp = pcie_find_root_port(dev); +- u16 lnkctl; +- +- if (!rp) +- return false; +- +- pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl); +- if (lnkctl & PCI_EXP_LNKCTL_RCB) +- return true; +- +- return false; +-} +- + /* _HPX PCI Express Setting Record (Type 2) */ + struct hpx_type2 { + u32 revision; +@@ -285,6 +270,7 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx) + { + int pos; + u32 reg32; ++ const struct pci_host_bridge *host; + + if (!hpx) + return; +@@ -292,6 +278,15 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx) + if (!pci_is_pcie(dev)) + return; + ++ host = pci_find_host_bridge(dev->bus); ++ ++ /* ++ * Only do the _HPX Type 2 programming if OS owns PCIe native ++ * hotplug but not AER. ++ */ ++ if (!host->native_pcie_hotplug || host->native_aer) ++ return; ++ + if (hpx->revision > 1) { + pci_warn(dev, "PCIe settings rev %d not supported\n", + hpx->revision); +@@ -299,33 +294,27 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx) + } + + /* +- * Don't allow _HPX to change MPS or MRRS settings. We manage +- * those to make sure they're consistent with the rest of the +- * platform. ++ * We only allow _HPX to program DEVCTL bits related to AER, namely ++ * PCI_EXP_DEVCTL_CERE, PCI_EXP_DEVCTL_NFERE, PCI_EXP_DEVCTL_FERE, ++ * and PCI_EXP_DEVCTL_URRE. ++ * ++ * The rest of DEVCTL is managed by the OS to make sure it's ++ * consistent with the rest of the platform. + */ +- hpx->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD | +- PCI_EXP_DEVCTL_READRQ; +- hpx->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD | +- PCI_EXP_DEVCTL_READRQ); ++ hpx->pci_exp_devctl_and |= ~PCI_EXP_AER_FLAGS; ++ hpx->pci_exp_devctl_or &= PCI_EXP_AER_FLAGS; + + /* Initialize Device Control Register */ + pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, + ~hpx->pci_exp_devctl_and, hpx->pci_exp_devctl_or); + +- /* Initialize Link Control Register */ ++ /* Log if _HPX attempts to modify Link Control Register */ + if (pcie_cap_has_lnkctl(dev)) { +- +- /* +- * If the Root Port supports Read Completion Boundary of +- * 128, set RCB to 128. Otherwise, clear it. +- */ +- hpx->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB; +- hpx->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB; +- if (pcie_root_rcb_set(dev)) +- hpx->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB; +- +- pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, +- ~hpx->pci_exp_lnkctl_and, hpx->pci_exp_lnkctl_or); ++ if (hpx->pci_exp_lnkctl_and != 0xffff || ++ hpx->pci_exp_lnkctl_or != 0) ++ pci_info(dev, "_HPX attempts Link Control setting (AND %#06x OR %#06x)\n", ++ hpx->pci_exp_lnkctl_and, ++ hpx->pci_exp_lnkctl_or); + } + + /* Find Advanced Error Reporting Enhanced Capability */ +diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h +index 4a8f499d278be..adae3e04c8c30 100644 +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -11,6 +11,9 @@ + + #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ + ++#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ ++ PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) ++ + extern const unsigned char pcie_link_speed[]; + extern bool pci_early_dump; + +diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c +index a8bec1c3c769a..9b86df5b82359 100644 +--- a/drivers/pci/pcie/aer.c ++++ b/drivers/pci/pcie/aer.c +@@ -214,9 +214,6 @@ void pcie_ecrc_get_policy(char *str) + } + #endif /* CONFIG_PCIE_ECRC */ + +-#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ +- PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) +- + int pcie_aer_is_native(struct pci_dev *dev) + { + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); +-- +2.53.0 + diff --git a/queue-5.15/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch b/queue-5.15/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch new file mode 100644 index 0000000000..b94bad2dfe --- /dev/null +++ b/queue-5.15/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch @@ -0,0 +1,97 @@ +From b42d9f6bff33b62ab3fe5bb81ced69dc7fcd2319 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 12:06:45 -0400 +Subject: PCI: endpoint: pci-epf-vntb: Remove duplicate resource teardown + +From: Koichiro Den + +[ Upstream commit 0da63230d3ec1ec5fcc443a2314233e95bfece54 ] + +epf_ntb_epc_destroy() duplicates the teardown that the caller is +supposed to perform later. This leads to an oops when .allow_link fails +or when .drop_link is performed. The following is an example oops of the +former case: + + Unable to handle kernel paging request at virtual address dead000000000108 + [...] + [dead000000000108] address between user and kernel address ranges + Internal error: Oops: 0000000096000044 [#1] SMP + [...] + Call trace: + pci_epc_remove_epf+0x78/0xe0 (P) + pci_primary_epc_epf_link+0x88/0xa8 + configfs_symlink+0x1f4/0x5a0 + vfs_symlink+0x134/0x1d8 + do_symlinkat+0x88/0x138 + __arm64_sys_symlinkat+0x74/0xe0 + [...] + +Remove the helper, and drop pci_epc_put(). EPC device refcounting is +tied to the configfs EPC group lifetime, and pci_epc_put() in the +.drop_link path is sufficient. + +Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP") +Signed-off-by: Koichiro Den +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Frank Li +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260226084142.2226875-2-den@valinux.co.jp +[ context mismatch in deletion hunk ] +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-vntb.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c +index 45530bca50fb8..e9402b5dc8359 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c ++++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c +@@ -650,18 +650,6 @@ static void epf_ntb_mw_bar_clear(struct epf_ntb *ntb) + } + } + +-/** +- * epf_ntb_epc_destroy() - Cleanup NTB EPC interface +- * @ntb: NTB device that facilitates communication between HOST and vHOST +- * +- * Wrapper for epf_ntb_epc_destroy_interface() to cleanup all the NTB interfaces +- */ +-static void epf_ntb_epc_destroy(struct epf_ntb *ntb) +-{ +- pci_epc_remove_epf(ntb->epf->epc, ntb->epf, 0); +- pci_epc_put(ntb->epf->epc); +-} +- + /** + * epf_ntb_init_epc_bar() - Identify BARs to be used for each of the NTB + * constructs (scratchpad region, doorbell, memorywindow) +@@ -1289,7 +1277,7 @@ static int epf_ntb_bind(struct pci_epf *epf) + ret = epf_ntb_init_epc_bar(ntb); + if (ret) { + dev_err(dev, "Failed to create NTB EPC\n"); +- goto err_bar_init; ++ return ret; + } + + ret = epf_ntb_config_spad_bar_alloc(ntb); +@@ -1326,9 +1314,6 @@ static int epf_ntb_bind(struct pci_epf *epf) + err_bar_alloc: + epf_ntb_config_spad_bar_free(ntb); + +-err_bar_init: +- epf_ntb_epc_destroy(ntb); +- + return ret; + } + +@@ -1344,7 +1329,6 @@ static void epf_ntb_unbind(struct pci_epf *epf) + + epf_ntb_epc_cleanup(ntb); + epf_ntb_config_spad_bar_free(ntb); +- epf_ntb_epc_destroy(ntb); + + pci_unregister_driver(&vntb_pci_driver); + } +-- +2.53.0 + diff --git a/queue-5.15/revert-net-ethernet-xscale-check-for-ptp-support-pro.patch b/queue-5.15/revert-net-ethernet-xscale-check-for-ptp-support-pro.patch new file mode 100644 index 0000000000..f9f3a4faad --- /dev/null +++ b/queue-5.15/revert-net-ethernet-xscale-check-for-ptp-support-pro.patch @@ -0,0 +1,53 @@ +From aca3e71aad71148dfc040f9eaa5c5d168f0607f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 13:17:31 -0400 +Subject: Revert "net: ethernet: xscale: Check for PTP support properly" + +This reverts commit 144dde3146985b25fa84d4e4b7c3d11e0f5fc5a4. + +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xscale/ixp4xx_eth.c | 5 ++++- + drivers/net/ethernet/xscale/ptp_ixp46x.c | 3 --- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c +index ad6384a1e6b21..9951006f1bc77 100644 +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -380,6 +380,9 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev, + int ret; + int ch; + ++ if (!cpu_is_ixp46x()) ++ return -EOPNOTSUPP; ++ + if (!netif_running(netdev)) + return -EINVAL; + +@@ -388,7 +391,7 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev, + + ret = ixp46x_ptp_find(&port->timesync_regs, &port->phc_index); + if (ret) +- return -EOPNOTSUPP; ++ return ret; + + ch = PORT2CHANNEL(port); + regs = port->timesync_regs; +diff --git a/drivers/net/ethernet/xscale/ptp_ixp46x.c b/drivers/net/ethernet/xscale/ptp_ixp46x.c +index 422946c1e65b7..20f6aa508003b 100644 +--- a/drivers/net/ethernet/xscale/ptp_ixp46x.c ++++ b/drivers/net/ethernet/xscale/ptp_ixp46x.c +@@ -244,9 +244,6 @@ static struct ixp_clock ixp_clock; + + int ixp46x_ptp_find(struct ixp46x_ts_regs *__iomem *regs, int *phc_index) + { +- if (!cpu_is_ixp46x()) +- return -ENODEV; +- + *regs = ixp_clock.regs; + *phc_index = ptp_clock_index(ixp_clock.ptp_clock); + +-- +2.53.0 + diff --git a/queue-5.15/revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch b/queue-5.15/revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch new file mode 100644 index 0000000000..2b1e8a5561 --- /dev/null +++ b/queue-5.15/revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch @@ -0,0 +1,149 @@ +From fc659850e3d20ec10c0737bfb2efdd0f381a17de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 13:17:38 -0400 +Subject: Revert "net: ixp4xx_eth: convert to ndo_hwtstamp_get() and + ndo_hwtstamp_set()" + +This reverts commit 612c622ab8efe9033a33eaad874ae69c090a53e1. + +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xscale/ixp4xx_eth.c | 61 +++++++++++++----------- + 1 file changed, 32 insertions(+), 29 deletions(-) + +diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c +index 9951006f1bc77..931494cc1c39e 100644 +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -371,20 +371,16 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb) + __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); + } + +-static int ixp4xx_hwtstamp_set(struct net_device *netdev, +- struct kernel_hwtstamp_config *cfg, +- struct netlink_ext_ack *extack) ++static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) + { ++ struct hwtstamp_config cfg; + struct ixp46x_ts_regs *regs; + struct port *port = netdev_priv(netdev); + int ret; + int ch; + +- if (!cpu_is_ixp46x()) +- return -EOPNOTSUPP; +- +- if (!netif_running(netdev)) +- return -EINVAL; ++ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) ++ return -EFAULT; + + if (cfg.flags) /* reserved for future extensions */ + return -EINVAL; +@@ -396,10 +392,10 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev, + ch = PORT2CHANNEL(port); + regs = port->timesync_regs; + +- if (cfg->tx_type != HWTSTAMP_TX_OFF && cfg->tx_type != HWTSTAMP_TX_ON) ++ if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON) + return -ERANGE; + +- switch (cfg->rx_filter) { ++ switch (cfg.rx_filter) { + case HWTSTAMP_FILTER_NONE: + port->hwts_rx_en = 0; + break; +@@ -415,45 +411,39 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev, + return -ERANGE; + } + +- port->hwts_tx_en = cfg->tx_type == HWTSTAMP_TX_ON; ++ port->hwts_tx_en = cfg.tx_type == HWTSTAMP_TX_ON; + + /* Clear out any old time stamps. */ + __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED, + ®s->channel[ch].ch_event); + +- return 0; ++ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + } + +-static int ixp4xx_hwtstamp_get(struct net_device *netdev, +- struct kernel_hwtstamp_config *cfg) ++static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) + { ++ struct hwtstamp_config cfg; + struct port *port = netdev_priv(netdev); + +- if (!cpu_is_ixp46x()) +- return -EOPNOTSUPP; +- +- if (!netif_running(netdev)) +- return -EINVAL; +- +- cfg->flags = 0; +- cfg->tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; ++ cfg.flags = 0; ++ cfg.tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + + switch (port->hwts_rx_en) { + case 0: +- cfg->rx_filter = HWTSTAMP_FILTER_NONE; ++ cfg.rx_filter = HWTSTAMP_FILTER_NONE; + break; + case PTP_SLAVE_MODE: +- cfg->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; ++ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; + break; + case PTP_MASTER_MODE: +- cfg->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; ++ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; + break; + default: + WARN_ON_ONCE(1); + return -ERANGE; + } + +- return 0; ++ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + } + + static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, +@@ -975,6 +965,21 @@ static void eth_set_mcast_list(struct net_device *dev) + } + + ++static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) ++{ ++ if (!netif_running(dev)) ++ return -EINVAL; ++ ++ if (cpu_is_ixp46x()) { ++ if (cmd == SIOCSHWTSTAMP) ++ return hwtstamp_set(dev, req); ++ if (cmd == SIOCGHWTSTAMP) ++ return hwtstamp_get(dev, req); ++ } ++ ++ return phy_mii_ioctl(dev->phydev, req, cmd); ++} ++ + /* ethtool support */ + + static void ixp4xx_get_drvinfo(struct net_device *dev, +@@ -1360,11 +1365,9 @@ static const struct net_device_ops ixp4xx_netdev_ops = { + .ndo_stop = eth_close, + .ndo_start_xmit = eth_xmit, + .ndo_set_rx_mode = eth_set_mcast_list, +- .ndo_eth_ioctl = phy_do_ioctl_running, ++ .ndo_eth_ioctl = eth_ioctl, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +- .ndo_hwtstamp_get = ixp4xx_hwtstamp_get, +- .ndo_hwtstamp_set = ixp4xx_hwtstamp_set, + }; + + #ifdef CONFIG_OF +-- +2.53.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 7c9839f308..0fee0122cf 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -88,3 +88,12 @@ media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_p nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch +net-tap-null-pointer-derefence-in-dev_parse_header_p.patch +pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch +revert-net-ethernet-xscale-check-for-ptp-support-pro.patch +revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch +ipv6-add-null-checks-for-idev-in-srv6-paths.patch +gfs2-improve-gfs2_consist_inode-usage.patch +gfs2-validate-i_depth-for-exhash-directories.patch +wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch +pci-acpi-restrict-program_hpx_type2-to-aer-bits.patch diff --git a/queue-5.15/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch b/queue-5.15/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch new file mode 100644 index 0000000000..db30e3c106 --- /dev/null +++ b/queue-5.15/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch @@ -0,0 +1,107 @@ +From 7f0abca43ad56902d5cde1a480e08aec8d3ed512 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 10:44:03 +0800 +Subject: wifi: mac80211: always free skb on ieee80211_tx_prepare_skb() failure + +From: Felix Fietkau + +[ Upstream commit d5ad6ab61cbd89afdb60881f6274f74328af3ee9 ] + +ieee80211_tx_prepare_skb() has three error paths, but only two of them +free the skb. The first error path (ieee80211_tx_prepare() returning +TX_DROP) does not free it, while invoke_tx_handlers() failure and the +fragmentation check both do. + +Add kfree_skb() to the first error path so all three are consistent, +and remove the now-redundant frees in callers (ath9k, mt76, +mac80211_hwsim) to avoid double-free. + +Document the skb ownership guarantee in the function's kdoc. + +Signed-off-by: Felix Fietkau +Link: https://patch.msgid.link/20260314065455.2462900-1-nbd@nbd.name +Fixes: 06be6b149f7e ("mac80211: add ieee80211_tx_prepare_skb() helper function") +Signed-off-by: Johannes Berg +[ Exclude changes to drivers/net/wireless/mediatek/mt76/scan.c as this file is first + introduced by commit 31083e38548f("wifi: mt76: add code for emulating hardware scanning") + after linux-6.14.] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/channel.c | 6 ++---- + drivers/net/wireless/mac80211_hwsim.c | 1 - + include/net/mac80211.h | 4 ++++ + net/mac80211/tx.c | 4 +++- + 4 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c +index 6cf0875221572..31b7921bf34f3 100644 +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -1011,7 +1011,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + + if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) +- goto error; ++ return; + + txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; + if (ath_tx_start(sc->hw, skb, &txctl)) +@@ -1124,10 +1124,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, + + skb->priority = 7; + skb_set_queue_mapping(skb, IEEE80211_AC_VO); +- if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { +- dev_kfree_skb_any(skb); ++ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) + return false; +- } + break; + default: + return false; +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 7d73502586839..ed4d83775fe70 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2347,7 +2347,6 @@ static void hw_scan_work(struct work_struct *work) + hwsim->tmp_chan->band, + NULL)) { + rcu_read_unlock(); +- kfree_skb(probe); + continue; + } + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index f101ef4a1fd69..a4ef9f93a53c4 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6454,6 +6454,10 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, + * @band: the band to transmit on + * @sta: optional pointer to get the station to send the frame to + * ++ * Return: %true if the skb was prepared, %false otherwise. ++ * On failure, the skb is freed by this function; callers must not ++ * free it again. ++ * + * Note: must be called under RCU lock + */ + bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index a5be5fe5c6b4e..0544931613763 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1882,8 +1882,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, + struct ieee80211_tx_data tx; + struct sk_buff *skb2; + +- if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) ++ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) { ++ kfree_skb(skb); + return false; ++ } + + info->band = band; + info->control.vif = vif; +-- +2.53.0 + diff --git a/queue-6.1/gfs2-improve-gfs2_consist_inode-usage.patch b/queue-6.1/gfs2-improve-gfs2_consist_inode-usage.patch new file mode 100644 index 0000000000..107dabc079 --- /dev/null +++ b/queue-6.1/gfs2-improve-gfs2_consist_inode-usage.patch @@ -0,0 +1,213 @@ +From 4c15a97ba9607c8facfff8a14a4b1f66e700427b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 18:37:16 +0800 +Subject: gfs2: Improve gfs2_consist_inode() usage + +From: Andrew Price + +[ Upstream commit 10398ef57aa189153406c110f5957145030f08fe ] + +gfs2_consist_inode() logs an error message with the source file and line +number. When we jump before calling it, the line number becomes less +useful as it no longer relates to the source of the error. To aid +troubleshooting, replace the gotos with the gfs2_consist_inode() calls +so that the error messages are more informative. + +Signed-off-by: Andrew Price +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Ruohan Lan +Signed-off-by: Sasha Levin +--- + fs/gfs2/dir.c | 31 +++++++++++++++++-------------- + fs/gfs2/glops.c | 34 ++++++++++++++++++++-------------- + fs/gfs2/xattr.c | 28 ++++++++++++++++------------ + 3 files changed, 53 insertions(+), 40 deletions(-) + +diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c +index 54a6d17b8c252..96924af95c8ef 100644 +--- a/fs/gfs2/dir.c ++++ b/fs/gfs2/dir.c +@@ -562,15 +562,18 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, + int ret = 0; + + ret = gfs2_dirent_offset(GFS2_SB(inode), buf); +- if (ret < 0) +- goto consist_inode; +- ++ if (ret < 0) { ++ gfs2_consist_inode(GFS2_I(inode)); ++ return ERR_PTR(-EIO); ++ } + offset = ret; + prev = NULL; + dent = buf + offset; + size = be16_to_cpu(dent->de_rec_len); +- if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1)) +- goto consist_inode; ++ if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1)) { ++ gfs2_consist_inode(GFS2_I(inode)); ++ return ERR_PTR(-EIO); ++ } + do { + ret = scan(dent, name, opaque); + if (ret) +@@ -582,8 +585,10 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, + dent = buf + offset; + size = be16_to_cpu(dent->de_rec_len); + if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, +- len, 0)) +- goto consist_inode; ++ len, 0)) { ++ gfs2_consist_inode(GFS2_I(inode)); ++ return ERR_PTR(-EIO); ++ } + } while(1); + + switch(ret) { +@@ -597,10 +602,6 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, + BUG_ON(ret > 0); + return ERR_PTR(ret); + } +- +-consist_inode: +- gfs2_consist_inode(GFS2_I(inode)); +- return ERR_PTR(-EIO); + } + + static int dirent_check_reclen(struct gfs2_inode *dip, +@@ -609,14 +610,16 @@ static int dirent_check_reclen(struct gfs2_inode *dip, + const void *ptr = d; + u16 rec_len = be16_to_cpu(d->de_rec_len); + +- if (unlikely(rec_len < sizeof(struct gfs2_dirent))) +- goto broken; ++ if (unlikely(rec_len < sizeof(struct gfs2_dirent))) { ++ gfs2_consist_inode(dip); ++ return -EIO; ++ } + ptr += rec_len; + if (ptr < end_p) + return rec_len; + if (ptr == end_p) + return -ENOENT; +-broken: ++ + gfs2_consist_inode(dip); + return -EIO; + } +diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c +index bb5bc32a5eea5..f4bd487a9b3b0 100644 +--- a/fs/gfs2/glops.c ++++ b/fs/gfs2/glops.c +@@ -404,10 +404,14 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) + struct inode *inode = &ip->i_inode; + bool is_new = inode->i_state & I_NEW; + +- if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) +- goto corrupt; +- if (unlikely(!is_new && inode_wrong_type(inode, mode))) +- goto corrupt; ++ if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } ++ if (unlikely(!is_new && inode_wrong_type(inode, mode))) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); + inode->i_mode = mode; + if (is_new) { +@@ -443,26 +447,28 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) + /* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */ + gfs2_set_inode_flags(inode); + height = be16_to_cpu(str->di_height); +- if (unlikely(height > sdp->sd_max_height)) +- goto corrupt; ++ if (unlikely(height > sdp->sd_max_height)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_height = (u8)height; + + depth = be16_to_cpu(str->di_depth); +- if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) +- goto corrupt; ++ if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_depth = (u8)depth; + ip->i_entries = be32_to_cpu(str->di_entries); + +- if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) +- goto corrupt; +- ++ if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + if (S_ISREG(inode->i_mode)) + gfs2_set_aops(inode); + + return 0; +-corrupt: +- gfs2_consist_inode(ip); +- return -EIO; + } + + /** +diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c +index f6a66050380e9..6590aad6720b4 100644 +--- a/fs/gfs2/xattr.c ++++ b/fs/gfs2/xattr.c +@@ -96,30 +96,34 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh, + return -EIO; + + for (ea = GFS2_EA_BH2FIRST(bh);; prev = ea, ea = GFS2_EA2NEXT(ea)) { +- if (!GFS2_EA_REC_LEN(ea)) +- goto fail; ++ if (!GFS2_EA_REC_LEN(ea)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <= +- bh->b_data + bh->b_size)) +- goto fail; +- if (!gfs2_eatype_valid(sdp, ea->ea_type)) +- goto fail; ++ bh->b_data + bh->b_size)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } ++ if (!gfs2_eatype_valid(sdp, ea->ea_type)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + error = ea_call(ip, bh, ea, prev, data); + if (error) + return error; + + if (GFS2_EA_IS_LAST(ea)) { + if ((char *)GFS2_EA2NEXT(ea) != +- bh->b_data + bh->b_size) +- goto fail; ++ bh->b_data + bh->b_size) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + break; + } + } + + return error; +- +-fail: +- gfs2_consist_inode(ip); +- return -EIO; + } + + static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data) +-- +2.53.0 + diff --git a/queue-6.1/gfs2-validate-i_depth-for-exhash-directories.patch b/queue-6.1/gfs2-validate-i_depth-for-exhash-directories.patch new file mode 100644 index 0000000000..46570656ef --- /dev/null +++ b/queue-6.1/gfs2-validate-i_depth-for-exhash-directories.patch @@ -0,0 +1,95 @@ +From 84ed1e95085fe049c908d7d7bedba8ea2ebc1e99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 18:37:17 +0800 +Subject: gfs2: Validate i_depth for exhash directories + +From: Andrew Price + +[ Upstream commit 557c024ca7250bb65ae60f16c02074106c2f197b ] + +A fuzzer test introduced corruption that ends up with a depth of 0 in +dir_e_read(), causing an undefined shift by 32 at: + + index = hash >> (32 - dip->i_depth); + +As calculated in an open-coded way in dir_make_exhash(), the minimum +depth for an exhash directory is ilog2(sdp->sd_hash_ptrs) and 0 is +invalid as sdp->sd_hash_ptrs is fixed as sdp->bsize / 16 at mount time. + +So we can avoid the undefined behaviour by checking for depth values +lower than the minimum in gfs2_dinode_in(). Values greater than the +maximum are already being checked for there. + +Also switch the calculation in dir_make_exhash() to use ilog2() to +clarify how the depth is calculated. + +Tested with the syzkaller repro.c and xfstests '-g quick'. + +Reported-by: syzbot+4708579bb230a0582a57@syzkaller.appspotmail.com +Signed-off-by: Andrew Price +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Ruohan Lan +Signed-off-by: Sasha Levin +--- + fs/gfs2/dir.c | 6 ++---- + fs/gfs2/glops.c | 6 ++++++ + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c +index 96924af95c8ef..3716d89d8af6f 100644 +--- a/fs/gfs2/dir.c ++++ b/fs/gfs2/dir.c +@@ -60,6 +60,7 @@ + #include + #include + #include ++#include + + #include "gfs2.h" + #include "incore.h" +@@ -912,7 +913,6 @@ static int dir_make_exhash(struct inode *inode) + struct qstr args; + struct buffer_head *bh, *dibh; + struct gfs2_leaf *leaf; +- int y; + u32 x; + __be64 *lp; + u64 bn; +@@ -979,9 +979,7 @@ static int dir_make_exhash(struct inode *inode) + i_size_write(inode, sdp->sd_sb.sb_bsize / 2); + gfs2_add_inode_blocks(&dip->i_inode, 1); + dip->i_diskflags |= GFS2_DIF_EXHASH; +- +- for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; +- dip->i_depth = y; ++ dip->i_depth = ilog2(sdp->sd_hash_ptrs); + + gfs2_dinode_out(dip, dibh->b_data); + +diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c +index f4bd487a9b3b0..e7904c1c985f6 100644 +--- a/fs/gfs2/glops.c ++++ b/fs/gfs2/glops.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "gfs2.h" + #include "incore.h" +@@ -458,6 +459,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) + gfs2_consist_inode(ip); + return -EIO; + } ++ if ((ip->i_diskflags & GFS2_DIF_EXHASH) && ++ depth < ilog2(sdp->sd_hash_ptrs)) { ++ gfs2_consist_inode(ip); ++ return -EIO; ++ } + ip->i_depth = (u8)depth; + ip->i_entries = be32_to_cpu(str->di_entries); + +-- +2.53.0 + diff --git a/queue-6.1/ipv6-add-null-checks-for-idev-in-srv6-paths.patch b/queue-6.1/ipv6-add-null-checks-for-idev-in-srv6-paths.patch new file mode 100644 index 0000000000..7bbc478685 --- /dev/null +++ b/queue-6.1/ipv6-add-null-checks-for-idev-in-srv6-paths.patch @@ -0,0 +1,60 @@ +From b5e751308ea27a5fdd5d7a46dc4e18af545dde0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 13:43:09 +0800 +Subject: ipv6: add NULL checks for idev in SRv6 paths + +From: Minhong He + +[ Upstream commit 06413793526251870e20402c39930804f14d59c0 ] + +__in6_dev_get() can return NULL when the device has no IPv6 configuration +(e.g. MTU < IPV6_MIN_MTU or after NETDEV_UNREGISTER). + +Add NULL checks for idev returned by __in6_dev_get() in both +seg6_hmac_validate_skb() and ipv6_srh_rcv() to prevent potential NULL +pointer dereferences. + +Fixes: 1ababeba4a21 ("ipv6: implement dataplane support for rthdr type 4 (Segment Routing Header)") +Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") +Signed-off-by: Minhong He +Reviewed-by: Andrea Mayer +Link: https://patch.msgid.link/20260316073301.106643-1-heminhong@kylinos.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + net/ipv6/exthdrs.c | 4 ++++ + net/ipv6/seg6_hmac.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 61e0060185f4b..5fb97a87d2cb5 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -381,6 +381,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) + hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); + + idev = __in6_dev_get(skb->dev); ++ if (!idev) { ++ kfree_skb(skb); ++ return -1; ++ } + + accept_seg6 = net->ipv6.devconf_all->seg6_enabled; + if (accept_seg6 > idev->cnf.seg6_enabled) +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index b90c286d77ed4..e784f539194ad 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -244,6 +244,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) + struct inet6_dev *idev; + + idev = __in6_dev_get(skb->dev); ++ if (!idev) ++ return false; + + srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); + +-- +2.53.0 + diff --git a/queue-6.1/net-dsa-clean-up-fdb-mdb-vlan-entries-on-unbind.patch b/queue-6.1/net-dsa-clean-up-fdb-mdb-vlan-entries-on-unbind.patch new file mode 100644 index 0000000000..9146e3702e --- /dev/null +++ b/queue-6.1/net-dsa-clean-up-fdb-mdb-vlan-entries-on-unbind.patch @@ -0,0 +1,121 @@ +From 3958a276a473db5c8c6aa7e3167a3898a66a182c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 15:36:35 +0800 +Subject: net: dsa: clean up FDB, MDB, VLAN entries on unbind + +From: Vladimir Oltean + +[ Upstream commit 7afb5fb42d4950f33af2732b8147c552659f79b7 ] + +As explained in many places such as commit b117e1e8a86d ("net: dsa: +delete dsa_legacy_fdb_add and dsa_legacy_fdb_del"), DSA is written given +the assumption that higher layers have balanced additions/deletions. +As such, it only makes sense to be extremely vocal when those +assumptions are violated and the driver unbinds with entries still +present. + +But Ido Schimmel points out a very simple situation where that is wrong: +https://lore.kernel.org/netdev/ZDazSM5UsPPjQuKr@shredder/ +(also briefly discussed by me in the aforementioned commit). + +Basically, while the bridge bypass operations are not something that DSA +explicitly documents, and for the majority of DSA drivers this API +simply causes them to go to promiscuous mode, that isn't the case for +all drivers. Some have the necessary requirements for bridge bypass +operations to do something useful - see dsa_switch_supports_uc_filtering(). + +Although in tools/testing/selftests/net/forwarding/local_termination.sh, +we made an effort to popularize better mechanisms to manage address +filters on DSA interfaces from user space - namely macvlan for unicast, +and setsockopt(IP_ADD_MEMBERSHIP) - through mtools - for multicast, the +fact is that 'bridge fdb add ... self static local' also exists as +kernel UAPI, and might be useful to someone, even if only for a quick +hack. + +It seems counter-productive to block that path by implementing shim +.ndo_fdb_add and .ndo_fdb_del operations which just return -EOPNOTSUPP +in order to prevent the ndo_dflt_fdb_add() and ndo_dflt_fdb_del() from +running, although we could do that. + +Accepting that cleanup is necessary seems to be the only option. +Especially since we appear to be coming back at this from a different +angle as well. Russell King is noticing that the WARN_ON() triggers even +for VLANs: +https://lore.kernel.org/netdev/Z_li8Bj8bD4-BYKQ@shell.armlinux.org.uk/ + +What happens in the bug report above is that dsa_port_do_vlan_del() fails, +then the VLAN entry lingers on, and then we warn on unbind and leak it. + +This is not a straight revert of the blamed commit, but we now add an +informational print to the kernel log (to still have a way to see +that bugs exist), and some extra comments gathered from past years' +experience, to justify the logic. + +Fixes: 0832cd9f1f02 ("net: dsa: warn if port lists aren't empty in dsa_port_teardown") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20250414212930.2956310-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +[ Apply the patch to net/dsa/dsa2.c in v6.1 since commit +47d2ce03dcfb ("net: dsa: rename dsa2.c back into dsa.c and create its header") +renamed this file to net/dsa/dsa.c starting from v6.2. ] +Signed-off-by: Alva Lan +Signed-off-by: Sasha Levin +--- + net/dsa/dsa2.c | 38 +++++++++++++++++++++++++++++++++++--- + 1 file changed, 35 insertions(+), 3 deletions(-) + +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index 415e856ba0acf..9ecb5e34e484e 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -1738,12 +1738,44 @@ static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd) + + static void dsa_switch_release_ports(struct dsa_switch *ds) + { ++ struct dsa_mac_addr *a, *tmp; + struct dsa_port *dp, *next; ++ struct dsa_vlan *v, *n; + + dsa_switch_for_each_port_safe(dp, next, ds) { +- WARN_ON(!list_empty(&dp->fdbs)); +- WARN_ON(!list_empty(&dp->mdbs)); +- WARN_ON(!list_empty(&dp->vlans)); ++ /* These are either entries that upper layers lost track of ++ * (probably due to bugs), or installed through interfaces ++ * where one does not necessarily have to remove them, like ++ * ndo_dflt_fdb_add(). ++ */ ++ list_for_each_entry_safe(a, tmp, &dp->fdbs, list) { ++ dev_info(ds->dev, ++ "Cleaning up unicast address %pM vid %u from port %d\n", ++ a->addr, a->vid, dp->index); ++ list_del(&a->list); ++ kfree(a); ++ } ++ ++ list_for_each_entry_safe(a, tmp, &dp->mdbs, list) { ++ dev_info(ds->dev, ++ "Cleaning up multicast address %pM vid %u from port %d\n", ++ a->addr, a->vid, dp->index); ++ list_del(&a->list); ++ kfree(a); ++ } ++ ++ /* These are entries that upper layers have lost track of, ++ * probably due to bugs, but also due to dsa_port_do_vlan_del() ++ * having failed and the VLAN entry still lingering on. ++ */ ++ list_for_each_entry_safe(v, n, &dp->vlans, list) { ++ dev_info(ds->dev, ++ "Cleaning up vid %u from port %d\n", ++ v->vid, dp->index); ++ list_del(&v->list); ++ kfree(v); ++ } ++ + list_del(&dp->list); + kfree(dp); + } +-- +2.53.0 + diff --git a/queue-6.1/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch b/queue-6.1/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch new file mode 100644 index 0000000000..c9fdc20bc6 --- /dev/null +++ b/queue-6.1/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch @@ -0,0 +1,97 @@ +From 05271a53447a15e48b5de20736beca47e7205a9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 10:58:35 -0400 +Subject: PCI: endpoint: pci-epf-vntb: Remove duplicate resource teardown + +From: Koichiro Den + +[ Upstream commit 0da63230d3ec1ec5fcc443a2314233e95bfece54 ] + +epf_ntb_epc_destroy() duplicates the teardown that the caller is +supposed to perform later. This leads to an oops when .allow_link fails +or when .drop_link is performed. The following is an example oops of the +former case: + + Unable to handle kernel paging request at virtual address dead000000000108 + [...] + [dead000000000108] address between user and kernel address ranges + Internal error: Oops: 0000000096000044 [#1] SMP + [...] + Call trace: + pci_epc_remove_epf+0x78/0xe0 (P) + pci_primary_epc_epf_link+0x88/0xa8 + configfs_symlink+0x1f4/0x5a0 + vfs_symlink+0x134/0x1d8 + do_symlinkat+0x88/0x138 + __arm64_sys_symlinkat+0x74/0xe0 + [...] + +Remove the helper, and drop pci_epc_put(). EPC device refcounting is +tied to the configfs EPC group lifetime, and pci_epc_put() in the +.drop_link path is sufficient. + +Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP") +Signed-off-by: Koichiro Den +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Frank Li +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260226084142.2226875-2-den@valinux.co.jp +[ adjusted context ] +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-vntb.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c +index d057537781f60..eee49a3eec04c 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c ++++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c +@@ -676,18 +676,6 @@ static void epf_ntb_mw_bar_clear(struct epf_ntb *ntb, int num_mws) + } + } + +-/** +- * epf_ntb_epc_destroy() - Cleanup NTB EPC interface +- * @ntb: NTB device that facilitates communication between HOST and VHOST +- * +- * Wrapper for epf_ntb_epc_destroy_interface() to cleanup all the NTB interfaces +- */ +-static void epf_ntb_epc_destroy(struct epf_ntb *ntb) +-{ +- pci_epc_remove_epf(ntb->epf->epc, ntb->epf, 0); +- pci_epc_put(ntb->epf->epc); +-} +- + /** + * epf_ntb_init_epc_bar() - Identify BARs to be used for each of the NTB + * constructs (scratchpad region, doorbell, memorywindow) +@@ -1331,7 +1319,7 @@ static int epf_ntb_bind(struct pci_epf *epf) + ret = epf_ntb_init_epc_bar(ntb); + if (ret) { + dev_err(dev, "Failed to create NTB EPC\n"); +- goto err_bar_init; ++ return ret; + } + + ret = epf_ntb_config_spad_bar_alloc(ntb); +@@ -1371,9 +1359,6 @@ static int epf_ntb_bind(struct pci_epf *epf) + err_bar_alloc: + epf_ntb_config_spad_bar_free(ntb); + +-err_bar_init: +- epf_ntb_epc_destroy(ntb); +- + return ret; + } + +@@ -1389,7 +1374,6 @@ static void epf_ntb_unbind(struct pci_epf *epf) + + epf_ntb_epc_cleanup(ntb); + epf_ntb_config_spad_bar_free(ntb); +- epf_ntb_epc_destroy(ntb); + + pci_unregister_driver(&vntb_pci_driver); + } +-- +2.53.0 + diff --git a/queue-6.1/revert-net-ethernet-xscale-check-for-ptp-support-pro.patch b/queue-6.1/revert-net-ethernet-xscale-check-for-ptp-support-pro.patch new file mode 100644 index 0000000000..52b50e69ad --- /dev/null +++ b/queue-6.1/revert-net-ethernet-xscale-check-for-ptp-support-pro.patch @@ -0,0 +1,51 @@ +From 77d8aa732776b13c2e9b95abb2a0bff4e9b638ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 13:19:24 -0400 +Subject: Revert "net: ethernet: xscale: Check for PTP support properly" + +This reverts commit 5195b10c34b8993194ad12ad7d8f54d861be084b. + +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xscale/ixp4xx_eth.c | 5 ++++- + drivers/net/ethernet/xscale/ptp_ixp46x.c | 3 --- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c +index aa6d30dd35c38..a5e03e66cfd38 100644 +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -395,12 +395,15 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev, + int ret; + int ch; + ++ if (!cpu_is_ixp46x()) ++ return -EOPNOTSUPP; ++ + if (!netif_running(netdev)) + return -EINVAL; + + ret = ixp46x_ptp_find(&port->timesync_regs, &port->phc_index); + if (ret) +- return -EOPNOTSUPP; ++ return ret; + + ch = PORT2CHANNEL(port); + regs = port->timesync_regs; +diff --git a/drivers/net/ethernet/xscale/ptp_ixp46x.c b/drivers/net/ethernet/xscale/ptp_ixp46x.c +index b8953745a9f2e..9abbdb71e629f 100644 +--- a/drivers/net/ethernet/xscale/ptp_ixp46x.c ++++ b/drivers/net/ethernet/xscale/ptp_ixp46x.c +@@ -243,9 +243,6 @@ static struct ixp_clock ixp_clock; + + int ixp46x_ptp_find(struct ixp46x_ts_regs *__iomem *regs, int *phc_index) + { +- if (!cpu_is_ixp46x()) +- return -ENODEV; +- + *regs = ixp_clock.regs; + *phc_index = ptp_clock_index(ixp_clock.ptp_clock); + +-- +2.53.0 + diff --git a/queue-6.1/revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch b/queue-6.1/revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch new file mode 100644 index 0000000000..c0a946b6f2 --- /dev/null +++ b/queue-6.1/revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch @@ -0,0 +1,149 @@ +From 026608f6b33a21b890efc5e47052019b4e4bc467 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 13:19:24 -0400 +Subject: Revert "net: ixp4xx_eth: convert to ndo_hwtstamp_get() and + ndo_hwtstamp_set()" + +This reverts commit a94d5447f6bf827bc29be2520ca636685bbc29e6. + +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xscale/ixp4xx_eth.c | 61 +++++++++++++----------- + 1 file changed, 32 insertions(+), 29 deletions(-) + +diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c +index a5e03e66cfd38..3b0c5f177447b 100644 +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -386,20 +386,16 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb) + __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); + } + +-static int ixp4xx_hwtstamp_set(struct net_device *netdev, +- struct kernel_hwtstamp_config *cfg, +- struct netlink_ext_ack *extack) ++static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) + { ++ struct hwtstamp_config cfg; + struct ixp46x_ts_regs *regs; + struct port *port = netdev_priv(netdev); + int ret; + int ch; + +- if (!cpu_is_ixp46x()) +- return -EOPNOTSUPP; +- +- if (!netif_running(netdev)) +- return -EINVAL; ++ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) ++ return -EFAULT; + + ret = ixp46x_ptp_find(&port->timesync_regs, &port->phc_index); + if (ret) +@@ -408,10 +404,10 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev, + ch = PORT2CHANNEL(port); + regs = port->timesync_regs; + +- if (cfg->tx_type != HWTSTAMP_TX_OFF && cfg->tx_type != HWTSTAMP_TX_ON) ++ if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON) + return -ERANGE; + +- switch (cfg->rx_filter) { ++ switch (cfg.rx_filter) { + case HWTSTAMP_FILTER_NONE: + port->hwts_rx_en = 0; + break; +@@ -427,45 +423,39 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev, + return -ERANGE; + } + +- port->hwts_tx_en = cfg->tx_type == HWTSTAMP_TX_ON; ++ port->hwts_tx_en = cfg.tx_type == HWTSTAMP_TX_ON; + + /* Clear out any old time stamps. */ + __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED, + ®s->channel[ch].ch_event); + +- return 0; ++ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + } + +-static int ixp4xx_hwtstamp_get(struct net_device *netdev, +- struct kernel_hwtstamp_config *cfg) ++static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) + { ++ struct hwtstamp_config cfg; + struct port *port = netdev_priv(netdev); + +- if (!cpu_is_ixp46x()) +- return -EOPNOTSUPP; +- +- if (!netif_running(netdev)) +- return -EINVAL; +- +- cfg->flags = 0; +- cfg->tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; ++ cfg.flags = 0; ++ cfg.tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + + switch (port->hwts_rx_en) { + case 0: +- cfg->rx_filter = HWTSTAMP_FILTER_NONE; ++ cfg.rx_filter = HWTSTAMP_FILTER_NONE; + break; + case PTP_SLAVE_MODE: +- cfg->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; ++ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; + break; + case PTP_MASTER_MODE: +- cfg->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; ++ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; + break; + default: + WARN_ON_ONCE(1); + return -ERANGE; + } + +- return 0; ++ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + } + + static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, +@@ -987,6 +977,21 @@ static void eth_set_mcast_list(struct net_device *dev) + } + + ++static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) ++{ ++ if (!netif_running(dev)) ++ return -EINVAL; ++ ++ if (cpu_is_ixp46x()) { ++ if (cmd == SIOCSHWTSTAMP) ++ return hwtstamp_set(dev, req); ++ if (cmd == SIOCGHWTSTAMP) ++ return hwtstamp_get(dev, req); ++ } ++ ++ return phy_mii_ioctl(dev->phydev, req, cmd); ++} ++ + /* ethtool support */ + + static void ixp4xx_get_drvinfo(struct net_device *dev, +@@ -1371,11 +1376,9 @@ static const struct net_device_ops ixp4xx_netdev_ops = { + .ndo_stop = eth_close, + .ndo_start_xmit = eth_xmit, + .ndo_set_rx_mode = eth_set_mcast_list, +- .ndo_eth_ioctl = phy_do_ioctl_running, ++ .ndo_eth_ioctl = eth_ioctl, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +- .ndo_hwtstamp_get = ixp4xx_hwtstamp_get, +- .ndo_hwtstamp_set = ixp4xx_hwtstamp_set, + }; + + static struct eth_plat_info *ixp4xx_of_get_platdata(struct device *dev) +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 23b8b1f93c..d9b1ebe001 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -107,3 +107,11 @@ media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_p nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch +pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch +revert-net-ethernet-xscale-check-for-ptp-support-pro.patch +revert-net-ixp4xx_eth-convert-to-ndo_hwtstamp_get-an.patch +ipv6-add-null-checks-for-idev-in-srv6-paths.patch +gfs2-improve-gfs2_consist_inode-usage.patch +gfs2-validate-i_depth-for-exhash-directories.patch +wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch +net-dsa-clean-up-fdb-mdb-vlan-entries-on-unbind.patch diff --git a/queue-6.1/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch b/queue-6.1/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch new file mode 100644 index 0000000000..7759645ab5 --- /dev/null +++ b/queue-6.1/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch @@ -0,0 +1,107 @@ +From 9f8569aacb9d3307e5a5f1cb8d48bca1ca21e82f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 10:43:52 +0800 +Subject: wifi: mac80211: always free skb on ieee80211_tx_prepare_skb() failure + +From: Felix Fietkau + +[ Upstream commit d5ad6ab61cbd89afdb60881f6274f74328af3ee9 ] + +ieee80211_tx_prepare_skb() has three error paths, but only two of them +free the skb. The first error path (ieee80211_tx_prepare() returning +TX_DROP) does not free it, while invoke_tx_handlers() failure and the +fragmentation check both do. + +Add kfree_skb() to the first error path so all three are consistent, +and remove the now-redundant frees in callers (ath9k, mt76, +mac80211_hwsim) to avoid double-free. + +Document the skb ownership guarantee in the function's kdoc. + +Signed-off-by: Felix Fietkau +Link: https://patch.msgid.link/20260314065455.2462900-1-nbd@nbd.name +Fixes: 06be6b149f7e ("mac80211: add ieee80211_tx_prepare_skb() helper function") +Signed-off-by: Johannes Berg +[ Exclude changes to drivers/net/wireless/mediatek/mt76/scan.c as this file is first + introduced by commit 31083e38548f("wifi: mt76: add code for emulating hardware scanning") + after linux-6.14.] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/channel.c | 6 ++---- + drivers/net/wireless/mac80211_hwsim.c | 1 - + include/net/mac80211.h | 4 ++++ + net/mac80211/tx.c | 4 +++- + 4 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c +index 571062f2e82a7..ba8ec5112afe8 100644 +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -1011,7 +1011,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + + if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) +- goto error; ++ return; + + txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; + if (ath_tx_start(sc->hw, skb, &txctl)) +@@ -1124,10 +1124,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, + + skb->priority = 7; + skb_set_queue_mapping(skb, IEEE80211_AC_VO); +- if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { +- dev_kfree_skb_any(skb); ++ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) + return false; +- } + break; + default: + return false; +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 80a2a668cfb9e..316b5f56b6e53 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2743,7 +2743,6 @@ static void hw_scan_work(struct work_struct *work) + hwsim->tmp_chan->band, + NULL)) { + rcu_read_unlock(); +- kfree_skb(probe); + continue; + } + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 62e0847d3793b..1769d03e6b1d4 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -6874,6 +6874,10 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, + * @band: the band to transmit on + * @sta: optional pointer to get the station to send the frame to + * ++ * Return: %true if the skb was prepared, %false otherwise. ++ * On failure, the skb is freed by this function; callers must not ++ * free it again. ++ * + * Note: must be called under RCU lock + */ + bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 7333e43dfc354..2e99a1063e939 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1934,8 +1934,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, + struct ieee80211_tx_data tx; + struct sk_buff *skb2; + +- if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) ++ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) { ++ kfree_skb(skb); + return false; ++ } + + info->band = band; + info->control.vif = vif; +-- +2.53.0 + diff --git a/queue-6.12/ima-do-not-copy-measurement-list-to-kdump-kernel.patch b/queue-6.12/ima-do-not-copy-measurement-list-to-kdump-kernel.patch new file mode 100644 index 0000000000..2e4aa9fd4b --- /dev/null +++ b/queue-6.12/ima-do-not-copy-measurement-list-to-kdump-kernel.patch @@ -0,0 +1,43 @@ +From 5938f939a3a593e478a564a67aade59461d6f22e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 May 2025 07:31:29 -0700 +Subject: ima: do not copy measurement list to kdump kernel + +From: Steven Chen + +[ Upstream commit fe3aebf27dc1875b2a0d13431e2e8cf3cf350cca ] + +Kdump kernel doesn't need IMA to do integrity measurement. +Hence the measurement list in 1st kernel doesn't need to be copied to +kdump kernel. + +Here skip allocating buffer for measurement list copying if loading +kdump kernel. Then there won't be the later handling related to +ima_kexec_buffer. + +Signed-off-by: Steven Chen +Tested-by: Baoquan He +Acked-by: Baoquan He +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_kexec.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c +index cc418a7e27f20..501b952b36981 100644 +--- a/security/integrity/ima/ima_kexec.c ++++ b/security/integrity/ima/ima_kexec.c +@@ -129,6 +129,9 @@ void ima_add_kexec_buffer(struct kimage *image) + size_t kexec_segment_size; + int ret; + ++ if (image->type == KEXEC_TYPE_CRASH) ++ return; ++ + /* + * Reserve an extra half page of memory for additional measurements + * added during the kexec load. +-- +2.53.0 + diff --git a/queue-6.12/ima-verify-if-the-segment-size-has-changed.patch b/queue-6.12/ima-verify-if-the-segment-size-has-changed.patch new file mode 100644 index 0000000000..3e0c50c92b --- /dev/null +++ b/queue-6.12/ima-verify-if-the-segment-size-has-changed.patch @@ -0,0 +1,53 @@ +From fdd39157a513b14430ef6908a75a286b54036671 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Apr 2025 15:25:13 -0700 +Subject: ima: verify if the segment size has changed + +From: Steven Chen + +[ Upstream commit d0a00ce470e3ea19ba3b9f1c390aee739570a44a ] + +kexec 'load' may be called multiple times. Free and realloc the buffer +only if the segment_size is changed from the previous kexec 'load' call. + +Signed-off-by: Steven Chen +Reviewed-by: Stefan Berger +Acked-by: Baoquan He +Tested-by: Stefan Berger # ppc64/kvm +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_kexec.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c +index c9e5b1d6b0ab8..cc418a7e27f20 100644 +--- a/security/integrity/ima/ima_kexec.c ++++ b/security/integrity/ima/ima_kexec.c +@@ -34,6 +34,14 @@ static void ima_free_kexec_file_buf(struct seq_file *sf) + + static int ima_alloc_kexec_file_buf(size_t segment_size) + { ++ /* ++ * kexec 'load' may be called multiple times. ++ * Free and realloc the buffer only if the segment_size is ++ * changed from the previous kexec 'load' call. ++ */ ++ if (ima_kexec_file.buf && ima_kexec_file.size == segment_size) ++ goto out; ++ + ima_free_kexec_file_buf(&ima_kexec_file); + + /* segment size can't change between kexec load and execute */ +@@ -42,6 +50,8 @@ static int ima_alloc_kexec_file_buf(size_t segment_size) + return -ENOMEM; + + ima_kexec_file.size = segment_size; ++ ++out: + ima_kexec_file.read_pos = 0; + ima_kexec_file.count = sizeof(struct ima_kexec_hdr); /* reserved space */ + +-- +2.53.0 + diff --git a/queue-6.12/mm-userfaultfd-fix-hugetlb-fault-mutex-hash-calculat.patch b/queue-6.12/mm-userfaultfd-fix-hugetlb-fault-mutex-hash-calculat.patch new file mode 100644 index 0000000000..8ffa28197a --- /dev/null +++ b/queue-6.12/mm-userfaultfd-fix-hugetlb-fault-mutex-hash-calculat.patch @@ -0,0 +1,92 @@ +From 9e7e82bb078e1f76f5f6ad8c6742c971fde9d7c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 14:36:06 -0400 +Subject: mm/userfaultfd: fix hugetlb fault mutex hash calculation + +From: Jianhui Zhou + +[ Upstream commit 0217c7fb4de4a40cee667eb21901f3204effe5ac ] + +In mfill_atomic_hugetlb(), linear_page_index() is used to calculate the +page index for hugetlb_fault_mutex_hash(). However, linear_page_index() +returns the index in PAGE_SIZE units, while hugetlb_fault_mutex_hash() +expects the index in huge page units. This mismatch means that different +addresses within the same huge page can produce different hash values, +leading to the use of different mutexes for the same huge page. This can +cause races between faulting threads, which can corrupt the reservation +map and trigger the BUG_ON in resv_map_release(). + +Fix this by introducing hugetlb_linear_page_index(), which returns the +page index in huge page granularity, and using it in place of +linear_page_index(). + +Link: https://lkml.kernel.org/r/20260310110526.335749-1-jianhuizzzzz@gmail.com +Fixes: a08c7193e4f1 ("mm/filemap: remove hugetlb special casing in filemap.c") +Signed-off-by: Jianhui Zhou +Reported-by: syzbot+f525fd79634858f478e7@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=f525fd79634858f478e7 +Acked-by: SeongJae Park +Reviewed-by: David Hildenbrand (Arm) +Acked-by: Mike Rapoport (Microsoft) +Cc: Jane Chu +Cc: Andrea Arcangeli +Cc: Hugh Dickins +Cc: JonasZhou +Cc: Muchun Song +Cc: Oscar Salvador +Cc: Peter Xu +Cc: SeongJae Park +Cc: Sidhartha Kumar +Cc: +Signed-off-by: Andrew Morton +[ placed new `hugetlb_linear_page_index()` before `hstate_is_gigantic()` ] +Signed-off-by: Sasha Levin +--- + include/linux/hugetlb.h | 17 +++++++++++++++++ + mm/userfaultfd.c | 2 +- + 2 files changed, 18 insertions(+), 1 deletion(-) + +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index 81b69287ab3b0..32c9bc8c750c5 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -783,6 +783,23 @@ static inline unsigned huge_page_shift(struct hstate *h) + return h->order + PAGE_SHIFT; + } + ++/** ++ * hugetlb_linear_page_index() - linear_page_index() but in hugetlb ++ * page size granularity. ++ * @vma: the hugetlb VMA ++ * @address: the virtual address within the VMA ++ * ++ * Return: the page offset within the mapping in huge page units. ++ */ ++static inline pgoff_t hugetlb_linear_page_index(struct vm_area_struct *vma, ++ unsigned long address) ++{ ++ struct hstate *h = hstate_vma(vma); ++ ++ return ((address - vma->vm_start) >> huge_page_shift(h)) + ++ (vma->vm_pgoff >> huge_page_order(h)); ++} ++ + static inline bool hstate_is_gigantic(struct hstate *h) + { + return huge_page_order(h) > MAX_PAGE_ORDER; +diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c +index 904095f69a6e3..9951b4f42c65a 100644 +--- a/mm/userfaultfd.c ++++ b/mm/userfaultfd.c +@@ -573,7 +573,7 @@ static __always_inline ssize_t mfill_atomic_hugetlb( + * in the case of shared pmds. fault mutex prevents + * races with other faulting threads. + */ +- idx = linear_page_index(dst_vma, dst_addr); ++ idx = hugetlb_linear_page_index(dst_vma, dst_addr); + mapping = dst_vma->vm_file->f_mapping; + hash = hugetlb_fault_mutex_hash(mapping, idx); + mutex_lock(&hugetlb_fault_mutex_table[hash]); +-- +2.53.0 + diff --git a/queue-6.12/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch b/queue-6.12/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch new file mode 100644 index 0000000000..e668f8a703 --- /dev/null +++ b/queue-6.12/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch @@ -0,0 +1,146 @@ +From 410558a6254cc5596c86fb8d864a8f87e837e0e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:11:22 +0100 +Subject: net: ethernet: mtk_eth_soc: initialize PPE per-tag-layer MTU + registers + +From: Daniel Golle + +commit 2dddb34dd0d07b01fa770eca89480a4da4f13153 upstream. + +The PPE enforces output frame size limits via per-tag-layer VLAN_MTU +registers that the driver never initializes. The hardware defaults do +not account for PPPoE overhead, causing the PPE to punt encapsulated +frames back to the CPU instead of forwarding them. + +Initialize the registers at PPE start and on MTU changes using the +maximum GMAC MTU. This is a conservative approximation -- the actual +per-PPE requirement depends on egress path, but using the global +maximum ensures the limits are never too small. + +Fixes: ba37b7caf1ed ("net: ethernet: mtk_eth_soc: add support for initializing the PPE") +Signed-off-by: Daniel Golle +Link: https://patch.msgid.link/ec995ab8ce8be423267a1cc093147a74d2eb9d82.1775789829.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++++++- + drivers/net/ethernet/mediatek/mtk_ppe.c | 30 +++++++++++++++++++++ + drivers/net/ethernet/mediatek/mtk_ppe.h | 1 + + 3 files changed, 52 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 45d4bac984a52..7406b706fb753 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3384,12 +3384,23 @@ static int mtk_device_event(struct notifier_block *n, unsigned long event, void + return NOTIFY_DONE; + } + ++static int mtk_max_gmac_mtu(struct mtk_eth *eth) ++{ ++ int i, max_mtu = ETH_DATA_LEN; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->netdev); i++) ++ if (eth->netdev[i] && eth->netdev[i]->mtu > max_mtu) ++ max_mtu = eth->netdev[i]->mtu; ++ ++ return max_mtu; ++} ++ + static int mtk_open(struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + struct mtk_mac *target_mac; +- int i, err, ppe_num; ++ int i, err, ppe_num, mtu; + + ppe_num = eth->soc->ppe_num; + +@@ -3436,6 +3447,10 @@ static int mtk_open(struct net_device *dev) + mtk_gdm_config(eth, target_mac->id, gdm_config); + } + ++ mtu = mtk_max_gmac_mtu(eth); ++ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) ++ mtk_ppe_update_mtu(eth->ppe[i], mtu); ++ + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +@@ -4129,6 +4144,7 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + int length = new_mtu + MTK_RX_ETH_HLEN; + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; ++ int max_mtu, i; + + if (rcu_access_pointer(eth->prog) && + length > MTK_PP_MAX_BUF_SIZE) { +@@ -4139,6 +4155,10 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + mtk_set_mcr_max_rx(mac, length); + WRITE_ONCE(dev->mtu, new_mtu); + ++ max_mtu = mtk_max_gmac_mtu(eth); ++ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) ++ mtk_ppe_update_mtu(eth->ppe[i], max_mtu); ++ + return 0; + } + +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c +index ada852adc5f70..fa688a42a22f5 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -973,6 +973,36 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) + } + } + ++void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu) ++{ ++ int base; ++ u32 val; ++ ++ if (!ppe) ++ return; ++ ++ /* The PPE checks output frame size against per-tag-layer MTU limits, ++ * treating PPPoE and DSA tags just like 802.1Q VLAN tags. The Linux ++ * device MTU already accounts for PPPoE (PPPOE_SES_HLEN) and DSA tag ++ * overhead, but 802.1Q VLAN tags are handled transparently without ++ * being reflected by the lower device MTU being increased by 4. ++ * Use the maximum MTU across all GMAC interfaces so that PPE output ++ * frame limits are sufficiently high regardless of which port a flow ++ * egresses through. ++ */ ++ base = ETH_HLEN + mtu; ++ ++ val = FIELD_PREP(MTK_PPE_VLAN_MTU0_NONE, base) | ++ FIELD_PREP(MTK_PPE_VLAN_MTU0_1TAG, base + VLAN_HLEN); ++ ppe_w32(ppe, MTK_PPE_VLAN_MTU0, val); ++ ++ val = FIELD_PREP(MTK_PPE_VLAN_MTU1_2TAG, ++ base + 2 * VLAN_HLEN) | ++ FIELD_PREP(MTK_PPE_VLAN_MTU1_3TAG, ++ base + 3 * VLAN_HLEN); ++ ppe_w32(ppe, MTK_PPE_VLAN_MTU1, val); ++} ++ + void mtk_ppe_start(struct mtk_ppe *ppe) + { + u32 val; +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h +index 223f709e2704f..ba85e39a155bf 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -346,6 +346,7 @@ struct mtk_ppe { + struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index); + + void mtk_ppe_deinit(struct mtk_eth *eth); ++void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu); + void mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + int mtk_ppe_prepare_reset(struct mtk_ppe *ppe); +-- +2.53.0 + diff --git a/queue-6.12/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch b/queue-6.12/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch new file mode 100644 index 0000000000..2fb3699e2a --- /dev/null +++ b/queue-6.12/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch @@ -0,0 +1,97 @@ +From 367c33632b188040b727d112835533313c457180 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 10:31:05 -0400 +Subject: PCI: endpoint: pci-epf-vntb: Remove duplicate resource teardown + +From: Koichiro Den + +[ Upstream commit 0da63230d3ec1ec5fcc443a2314233e95bfece54 ] + +epf_ntb_epc_destroy() duplicates the teardown that the caller is +supposed to perform later. This leads to an oops when .allow_link fails +or when .drop_link is performed. The following is an example oops of the +former case: + + Unable to handle kernel paging request at virtual address dead000000000108 + [...] + [dead000000000108] address between user and kernel address ranges + Internal error: Oops: 0000000096000044 [#1] SMP + [...] + Call trace: + pci_epc_remove_epf+0x78/0xe0 (P) + pci_primary_epc_epf_link+0x88/0xa8 + configfs_symlink+0x1f4/0x5a0 + vfs_symlink+0x134/0x1d8 + do_symlinkat+0x88/0x138 + __arm64_sys_symlinkat+0x74/0xe0 + [...] + +Remove the helper, and drop pci_epc_put(). EPC device refcounting is +tied to the configfs EPC group lifetime, and pci_epc_put() in the +.drop_link path is sufficient. + +Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP") +Signed-off-by: Koichiro Den +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Frank Li +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260226084142.2226875-2-den@valinux.co.jp +[ adjusted context ] +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-vntb.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c +index be2277cb9b637..6875af691b2de 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c ++++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c +@@ -662,18 +662,6 @@ static void epf_ntb_mw_bar_clear(struct epf_ntb *ntb, int num_mws) + } + } + +-/** +- * epf_ntb_epc_destroy() - Cleanup NTB EPC interface +- * @ntb: NTB device that facilitates communication between HOST and VHOST +- * +- * Wrapper for epf_ntb_epc_destroy_interface() to cleanup all the NTB interfaces +- */ +-static void epf_ntb_epc_destroy(struct epf_ntb *ntb) +-{ +- pci_epc_remove_epf(ntb->epf->epc, ntb->epf, 0); +- pci_epc_put(ntb->epf->epc); +-} +- + /** + * epf_ntb_init_epc_bar() - Identify BARs to be used for each of the NTB + * constructs (scratchpad region, doorbell, memorywindow) +@@ -1315,7 +1303,7 @@ static int epf_ntb_bind(struct pci_epf *epf) + ret = epf_ntb_init_epc_bar(ntb); + if (ret) { + dev_err(dev, "Failed to create NTB EPC\n"); +- goto err_bar_init; ++ return ret; + } + + ret = epf_ntb_config_spad_bar_alloc(ntb); +@@ -1355,9 +1343,6 @@ static int epf_ntb_bind(struct pci_epf *epf) + err_bar_alloc: + epf_ntb_config_spad_bar_free(ntb); + +-err_bar_init: +- epf_ntb_epc_destroy(ntb); +- + return ret; + } + +@@ -1373,7 +1358,6 @@ static void epf_ntb_unbind(struct pci_epf *epf) + + epf_ntb_epc_cleanup(ntb); + epf_ntb_config_spad_bar_free(ntb); +- epf_ntb_epc_destroy(ntb); + + pci_unregister_driver(&vntb_pci_driver); + } +-- +2.53.0 + diff --git a/queue-6.12/rust-warn-on-bindgen-0.69.5-and-libclang-19.1.patch b/queue-6.12/rust-warn-on-bindgen-0.69.5-and-libclang-19.1.patch new file mode 100644 index 0000000000..c69f307790 --- /dev/null +++ b/queue-6.12/rust-warn-on-bindgen-0.69.5-and-libclang-19.1.patch @@ -0,0 +1,194 @@ +From 0727b4a81addc1e542f9aefc24ef2bf0c3236dc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Nov 2024 21:16:07 +0100 +Subject: rust: warn on bindgen < 0.69.5 and libclang >= 19.1 + +From: Miguel Ojeda + +[ Upstream commit b2603f8ac8217bc59f5c7f248ac248423b9b99cb ] + +When testing a `clang` upgrade with Rust Binder, Alice encountered [1] a +build failure caused by `bindgen` not translating some symbols related to +tracepoints. This was caused by commit 2e770edd8ce1 ("[libclang] Compute +the right spelling location") changing the behavior of a function exposed +by `libclang`. `bindgen` fixed the regression in commit 600f63895f73 +("Use clang_getFileLocation instead of clang_getSpellingLocation"). + +However, the regression fix is only available in `bindgen` versions +0.69.5 or later (it was backported for 0.69.x). This means that when +older bindgen versions are used with new versions of `libclang`, `bindgen` +may do the wrong thing, which could lead to a build failure. + +Alice encountered the bug with some header files related to tracepoints, +but it could also cause build failures in other circumstances. Thus, +always emit a warning when using an old `bindgen` with a new `libclang` +so that other people do not have to spend time chasing down the same +bug. + +However, testing just the version is inconvenient, since distributions +do patch their packages without changing the version, so I reduced the +issue into the following piece of code that can trigger the issue: + + #define F(x) int x##x + F(foo); + +In particular, an unpatched `bindgen` will ignore the macro expansion +and thus not provide a declaration for the exported `int`. + +Thus add a build test to `rust_is_available.sh` using the code above +(that is only triggered if the versions appear to be affected), following +what we did for the 0.66.x issue. + +Moreover, I checked the status in the major distributions we have +instructions for: + + - Fedora 41 was affected but is now OK, since it now ships `bindgen` + 0.69.5. + + Thanks Ben for the quick reply on the updates that were ongoing. + + Fedora 40 and earlier are OK (older `libclang`, and they also now + carry `bindgen` 0.69.5). + + - Debian Sid was affected but is now OK, since they now ship a patched + `bindgen` binary (0.66.1-7+b3). The issue was reported to Debian by + email and then as a bug report [2]. + + Thanks NoisyCoil and Matthias for the quick replies. NoisyCoil handled + the needed updates. Debian may upgrade to `bindgen` 0.70.x, too. + + Debian Testing is OK (older `libclang` so far). + + - Ubuntu non-LTS (oracular) is affected. The issue was reported to Ubuntu + by email and then as a bug report [3]. + + Ubuntu LTS is not affected (older `libclang` so far). + + - Arch Linux, Gentoo Linux and openSUSE should be OK (newer `bindgen` is + provided). Nix as well (older `libclang` so far). + +This issue was also added to our "live list" that tracks issues around +distributions [4]. + +Cc: Ben Beasley +Cc: NoisyCoil +Cc: Matthias Geiger +Link: https://lore.kernel.org/rust-for-linux/20241030-bindgen-libclang-warn-v1-1-3a7ba9fedcfe@google.com/ [1] +Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1086510 [2] +Link: https://bugs.launchpad.net/ubuntu/+source/rust-bindgen-cli/+bug/2086639 [3] +Link: https://github.com/Rust-for-Linux/linux/issues/1127 [4] +Co-developed-by: Alice Ryhl +Signed-off-by: Alice Ryhl +Link: https://lore.kernel.org/r/20241111201607.653149-1-ojeda@kernel.org +Signed-off-by: Miguel Ojeda +Signed-off-by: Sasha Levin +--- + scripts/rust_is_available.sh | 15 ++++++++ + ...ust_is_available_bindgen_libclang_concat.h | 3 ++ + scripts/rust_is_available_test.py | 34 ++++++++++++++++++- + 3 files changed, 51 insertions(+), 1 deletion(-) + create mode 100644 scripts/rust_is_available_bindgen_libclang_concat.h + +diff --git a/scripts/rust_is_available.sh b/scripts/rust_is_available.sh +index 5262c56dd674e..93c0ef7fb3fb2 100755 +--- a/scripts/rust_is_available.sh ++++ b/scripts/rust_is_available.sh +@@ -225,6 +225,21 @@ if [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then + exit 1 + fi + ++if [ "$bindgen_libclang_cversion" -ge 1900100 ] && ++ [ "$rust_bindings_generator_cversion" -lt 6905 ]; then ++ # Distributions may have patched the issue (e.g. Debian did). ++ if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_concat.h | grep -q foofoo; then ++ echo >&2 "***" ++ echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.69.5 together with libclang >= 19.1" ++ echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2824)," ++ echo >&2 "*** unless patched (like Debian's)." ++ echo >&2 "*** Your bindgen version: $rust_bindings_generator_version" ++ echo >&2 "*** Your libclang version: $bindgen_libclang_version" ++ echo >&2 "***" ++ warning=1 ++ fi ++fi ++ + # If the C compiler is Clang, then we can also check whether its version + # matches the `libclang` version used by the Rust bindings generator. + # +diff --git a/scripts/rust_is_available_bindgen_libclang_concat.h b/scripts/rust_is_available_bindgen_libclang_concat.h +new file mode 100644 +index 0000000000000..efc6e98d0f1d0 +--- /dev/null ++++ b/scripts/rust_is_available_bindgen_libclang_concat.h +@@ -0,0 +1,3 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#define F(x) int x##x ++F(foo); +diff --git a/scripts/rust_is_available_test.py b/scripts/rust_is_available_test.py +index 413741037fb30..4fcc319dea84e 100755 +--- a/scripts/rust_is_available_test.py ++++ b/scripts/rust_is_available_test.py +@@ -54,7 +54,7 @@ else: + """) + + @classmethod +- def generate_bindgen(cls, version_stdout, libclang_stderr, version_0_66_patched=False): ++ def generate_bindgen(cls, version_stdout, libclang_stderr, version_0_66_patched=False, libclang_concat_patched=False): + if libclang_stderr is None: + libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})" + else: +@@ -65,12 +65,19 @@ else: + else: + version_0_66_case = "raise SystemExit(1)" + ++ if libclang_concat_patched: ++ libclang_concat_case = "print('pub static mut foofoo: ::std::os::raw::c_int;')" ++ else: ++ libclang_concat_case = "pass" ++ + return cls.generate_executable(f"""#!/usr/bin/env python3 + import sys + if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv): + {libclang_case} + elif "rust_is_available_bindgen_0_66.h" in " ".join(sys.argv): + {version_0_66_case} ++elif "rust_is_available_bindgen_libclang_concat.h" in " ".join(sys.argv): ++ {libclang_concat_case} + else: + print({repr(version_stdout)}) + """) +@@ -268,6 +275,31 @@ else: + result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) + self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr) + ++ def test_bindgen_bad_libclang_concat(self): ++ for (bindgen_version, libclang_version, expected_not_patched) in ( ++ ("0.69.4", "18.0.0", self.Expected.SUCCESS), ++ ("0.69.4", "19.1.0", self.Expected.SUCCESS_WITH_WARNINGS), ++ ("0.69.4", "19.2.0", self.Expected.SUCCESS_WITH_WARNINGS), ++ ++ ("0.69.5", "18.0.0", self.Expected.SUCCESS), ++ ("0.69.5", "19.1.0", self.Expected.SUCCESS), ++ ("0.69.5", "19.2.0", self.Expected.SUCCESS), ++ ++ ("0.70.0", "18.0.0", self.Expected.SUCCESS), ++ ("0.70.0", "19.1.0", self.Expected.SUCCESS), ++ ("0.70.0", "19.2.0", self.Expected.SUCCESS), ++ ): ++ with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version): ++ cc = self.generate_clang(f"clang version {libclang_version}") ++ libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false" ++ bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr) ++ result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc }) ++ if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS: ++ self.assertIn(f"Rust bindings generator '{bindgen}' < 0.69.5 together with libclang >= 19.1", result.stderr) ++ ++ bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_concat_patched=True) ++ result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc }) ++ + def test_clang_matches_bindgen_libclang_different_bindgen(self): + bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 999.0.0 [-W#pragma-messages], err: false") + result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen }) +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series new file mode 100644 index 0000000000..ba8c81918b --- /dev/null +++ b/queue-6.12/series @@ -0,0 +1,7 @@ +mm-userfaultfd-fix-hugetlb-fault-mutex-hash-calculat.patch +pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch +ima-verify-if-the-segment-size-has-changed.patch +ima-do-not-copy-measurement-list-to-kdump-kernel.patch +wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch +rust-warn-on-bindgen-0.69.5-and-libclang-19.1.patch +net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch diff --git a/queue-6.12/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch b/queue-6.12/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch new file mode 100644 index 0000000000..83218ce579 --- /dev/null +++ b/queue-6.12/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch @@ -0,0 +1,107 @@ +From 6ea5f128742a1c1076de92dcb130a32c6e80665c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 10:42:50 +0800 +Subject: wifi: mac80211: always free skb on ieee80211_tx_prepare_skb() failure + +From: Felix Fietkau + +[ Upstream commit d5ad6ab61cbd89afdb60881f6274f74328af3ee9 ] + +ieee80211_tx_prepare_skb() has three error paths, but only two of them +free the skb. The first error path (ieee80211_tx_prepare() returning +TX_DROP) does not free it, while invoke_tx_handlers() failure and the +fragmentation check both do. + +Add kfree_skb() to the first error path so all three are consistent, +and remove the now-redundant frees in callers (ath9k, mt76, +mac80211_hwsim) to avoid double-free. + +Document the skb ownership guarantee in the function's kdoc. + +Signed-off-by: Felix Fietkau +Link: https://patch.msgid.link/20260314065455.2462900-1-nbd@nbd.name +Fixes: 06be6b149f7e ("mac80211: add ieee80211_tx_prepare_skb() helper function") +Signed-off-by: Johannes Berg +[ Exclude changes to drivers/net/wireless/mediatek/mt76/scan.c as this file is first + introduced by commit 31083e38548f("wifi: mt76: add code for emulating hardware scanning") + after linux-6.14.] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/channel.c | 6 ++---- + drivers/net/wireless/virtual/mac80211_hwsim.c | 1 - + include/net/mac80211.h | 4 +++- + net/mac80211/tx.c | 4 +++- + 4 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c +index 571062f2e82a7..ba8ec5112afe8 100644 +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -1011,7 +1011,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + + if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) +- goto error; ++ return; + + txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; + if (ath_tx_start(sc->hw, skb, &txctl)) +@@ -1124,10 +1124,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, + + skb->priority = 7; + skb_set_queue_mapping(skb, IEEE80211_AC_VO); +- if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { +- dev_kfree_skb_any(skb); ++ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) + return false; +- } + break; + default: + return false; +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index 8b4fd5fd11b0e..e992e59b59189 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -2977,7 +2977,6 @@ static void hw_scan_work(struct work_struct *work) + hwsim->tmp_chan->band, + NULL)) { + rcu_read_unlock(); +- kfree_skb(probe); + continue; + } + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 80259a37e7247..7d71a4149cdf9 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -7208,7 +7208,9 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, + * @band: the band to transmit on + * @sta: optional pointer to get the station to send the frame to + * +- * Return: %true if the skb was prepared, %false otherwise ++ * Return: %true if the skb was prepared, %false otherwise. ++ * On failure, the skb is freed by this function; callers must not ++ * free it again. + * + * Note: must be called under RCU lock + */ +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 9142d748a6a70..0458cbba232e2 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1897,8 +1897,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, + struct ieee80211_tx_data tx; + struct sk_buff *skb2; + +- if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) ++ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) { ++ kfree_skb(skb); + return false; ++ } + + info->band = band; + info->control.vif = vif; +-- +2.53.0 + diff --git a/queue-6.18/arm64-cputype-add-c1-pro-definitions.patch b/queue-6.18/arm64-cputype-add-c1-pro-definitions.patch new file mode 100644 index 0000000000..af34240e92 --- /dev/null +++ b/queue-6.18/arm64-cputype-add-c1-pro-definitions.patch @@ -0,0 +1,50 @@ +From 66ca32af358c11a23108700529612bfd0206a44b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 11:00:16 +0100 +Subject: arm64: cputype: Add C1-Pro definitions + +From: Catalin Marinas + +commit 2c99561016c591f4c3d5ad7d22a61b8726e79735 upstream. + +Add cputype definitions for C1-Pro. These will be used for errata +detection in subsequent patches. + +These values can be found in "Table A-303: MIDR_EL1 bit descriptions" in +issue 07 of the C1-Pro TRM: + + https://documentation-service.arm.com/static/6930126730f8f55a656570af + +Acked-by: Mark Rutland +Cc: Will Deacon +Cc: James Morse +Reviewed-by: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/cputype.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index 9b00b75acbf29..18f98fb7ee783 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -98,6 +98,7 @@ + #define ARM_CPU_PART_CORTEX_A725 0xD87 + #define ARM_CPU_PART_CORTEX_A720AE 0xD89 + #define ARM_CPU_PART_NEOVERSE_N3 0xD8E ++#define ARM_CPU_PART_C1_PRO 0xD8B + + #define APM_CPU_PART_XGENE 0x000 + #define APM_CPU_VAR_POTENZA 0x00 +@@ -189,6 +190,7 @@ + #define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) + #define MIDR_CORTEX_A720AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720AE) + #define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3) ++#define MIDR_C1_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_PRO) + #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) + #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) + #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) +-- +2.53.0 + diff --git a/queue-6.18/arm64-errata-work-around-early-cme-dvmsync-acknowled.patch b/queue-6.18/arm64-errata-work-around-early-cme-dvmsync-acknowled.patch new file mode 100644 index 0000000000..4e1d54e4dd --- /dev/null +++ b/queue-6.18/arm64-errata-work-around-early-cme-dvmsync-acknowled.patch @@ -0,0 +1,531 @@ +From faa8d2c214b68a6e5a2650041f3e05b0ce27b6a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 11:00:17 +0100 +Subject: arm64: errata: Work around early CME DVMSync acknowledgement + +From: Catalin Marinas + +commit 0baba94a9779c13c857f6efc55807e6a45b1d4e4 upstream. + +C1-Pro acknowledges DVMSync messages before completing the SME/CME +memory accesses. Work around this by issuing an IPI to the affected CPUs +if they are running in EL0 with SME enabled. + +Note that we avoid the local DSB in the IPI handler as the kernel runs +with SCTLR_EL1.IESB=1. This is sufficient to complete SME memory +accesses at EL0 on taking an exception to EL1. On the return to user +path, no barrier is necessary either. See the comment in +sme_set_active() and the more detailed explanation in the link below. + +To avoid a potential IPI flood from malicious applications (e.g. +madvise(MADV_PAGEOUT) in a tight loop), track where a process is active +via mm_cpumask() and only interrupt those CPUs. + +Link: https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3 +Cc: Will Deacon +Cc: Mark Rutland +Cc: James Morse +Cc: Mark Brown +Reviewed-by: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + Documentation/arch/arm64/silicon-errata.rst | 2 + + arch/arm64/Kconfig | 12 ++++ + arch/arm64/include/asm/cpucaps.h | 2 + + arch/arm64/include/asm/fpsimd.h | 21 ++++++ + arch/arm64/include/asm/tlbbatch.h | 10 ++- + arch/arm64/include/asm/tlbflush.h | 72 ++++++++++++++++++- + arch/arm64/kernel/cpu_errata.c | 30 ++++++++ + arch/arm64/kernel/entry-common.c | 3 + + arch/arm64/kernel/fpsimd.c | 79 +++++++++++++++++++++ + arch/arm64/kernel/process.c | 36 ++++++++++ + arch/arm64/tools/cpucaps | 1 + + 11 files changed, 264 insertions(+), 4 deletions(-) + +diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst +index a7ec57060f64f..93cdf16937159 100644 +--- a/Documentation/arch/arm64/silicon-errata.rst ++++ b/Documentation/arch/arm64/silicon-errata.rst +@@ -202,6 +202,8 @@ stable kernels. + +----------------+-----------------+-----------------+-----------------------------+ + | ARM | Neoverse-V3AE | #3312417 | ARM64_ERRATUM_3194386 | + +----------------+-----------------+-----------------+-----------------------------+ ++| ARM | C1-Pro | #4193714 | ARM64_ERRATUM_4193714 | +++----------------+-----------------+-----------------+-----------------------------+ + | ARM | MMU-500 | #841119,826419 | ARM_SMMU_MMU_500_CPRE_ERRATA| + | | | #562869,1047329 | | + +----------------+-----------------+-----------------+-----------------------------+ +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 6663ffd23f252..840a945cb4acd 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -1154,6 +1154,18 @@ config ARM64_ERRATUM_3194386 + + If unsure, say Y. + ++config ARM64_ERRATUM_4193714 ++ bool "C1-Pro: 4193714: SME DVMSync early acknowledgement" ++ depends on ARM64_SME ++ default y ++ help ++ Enable workaround for C1-Pro acknowledging the DVMSync before ++ the SME memory accesses are complete. This will cause TLB ++ maintenance for processes using SME to also issue an IPI to ++ the affected CPUs. ++ ++ If unsure, say Y. ++ + config CAVIUM_ERRATUM_22375 + bool "Cavium erratum 22375, 24313" + default y +diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h +index 9d769291a3067..121210b7ffd0b 100644 +--- a/arch/arm64/include/asm/cpucaps.h ++++ b/arch/arm64/include/asm/cpucaps.h +@@ -66,6 +66,8 @@ cpucap_is_possible(const unsigned int cap) + return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI); + case ARM64_WORKAROUND_SPECULATIVE_SSBS: + return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386); ++ case ARM64_WORKAROUND_4193714: ++ return IS_ENABLED(CONFIG_ARM64_ERRATUM_4193714); + case ARM64_MPAM: + /* + * KVM MPAM support doesn't rely on the host kernel supporting MPAM. +diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h +index b8cf0ea43cc05..0fa8d1d5722e0 100644 +--- a/arch/arm64/include/asm/fpsimd.h ++++ b/arch/arm64/include/asm/fpsimd.h +@@ -428,6 +428,24 @@ static inline size_t sme_state_size(struct task_struct const *task) + return __sme_state_size(task_get_sme_vl(task)); + } + ++void sme_enable_dvmsync(void); ++void sme_set_active(void); ++void sme_clear_active(void); ++ ++static inline void sme_enter_from_user_mode(void) ++{ ++ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) && ++ test_thread_flag(TIF_SME)) ++ sme_clear_active(); ++} ++ ++static inline void sme_exit_to_user_mode(void) ++{ ++ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) && ++ test_thread_flag(TIF_SME)) ++ sme_set_active(); ++} ++ + #else + + static inline void sme_user_disable(void) { BUILD_BUG(); } +@@ -456,6 +474,9 @@ static inline size_t sme_state_size(struct task_struct const *task) + return 0; + } + ++static inline void sme_enter_from_user_mode(void) { } ++static inline void sme_exit_to_user_mode(void) { } ++ + #endif /* ! CONFIG_ARM64_SME */ + + /* For use by EFI runtime services calls only */ +diff --git a/arch/arm64/include/asm/tlbbatch.h b/arch/arm64/include/asm/tlbbatch.h +index fedb0b87b8db4..6297631532e59 100644 +--- a/arch/arm64/include/asm/tlbbatch.h ++++ b/arch/arm64/include/asm/tlbbatch.h +@@ -2,11 +2,17 @@ + #ifndef _ARCH_ARM64_TLBBATCH_H + #define _ARCH_ARM64_TLBBATCH_H + ++#include ++ + struct arch_tlbflush_unmap_batch { ++#ifdef CONFIG_ARM64_ERRATUM_4193714 + /* +- * For arm64, HW can do tlb shootdown, so we don't +- * need to record cpumask for sending IPI ++ * Track CPUs that need SME DVMSync on completion of this batch. ++ * Otherwise, the arm64 HW can do tlb shootdown, so we don't need to ++ * record cpumask for sending IPI + */ ++ cpumask_var_t cpumask; ++#endif + }; + + #endif /* _ARCH_ARM64_TLBBATCH_H */ +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index ba36e91aefb82..f53ab3ba0c48b 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -80,6 +80,71 @@ static inline unsigned long get_trans_granule(void) + } + } + ++#ifdef CONFIG_ARM64_ERRATUM_4193714 ++ ++void sme_do_dvmsync(const struct cpumask *mask); ++ ++static inline void sme_dvmsync(struct mm_struct *mm) ++{ ++ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714)) ++ return; ++ ++ sme_do_dvmsync(mm_cpumask(mm)); ++} ++ ++static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch, ++ struct mm_struct *mm) ++{ ++ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714)) ++ return; ++ ++ /* ++ * Order the mm_cpumask() read after the hardware DVMSync. ++ */ ++ dsb(ish); ++ if (cpumask_empty(mm_cpumask(mm))) ++ return; ++ ++ /* ++ * Allocate the batch cpumask on first use. Fall back to an immediate ++ * IPI for this mm in case of failure. ++ */ ++ if (!cpumask_available(batch->cpumask) && ++ !zalloc_cpumask_var(&batch->cpumask, GFP_ATOMIC)) { ++ sme_do_dvmsync(mm_cpumask(mm)); ++ return; ++ } ++ ++ cpumask_or(batch->cpumask, batch->cpumask, mm_cpumask(mm)); ++} ++ ++static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch) ++{ ++ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714)) ++ return; ++ ++ if (!cpumask_available(batch->cpumask)) ++ return; ++ ++ sme_do_dvmsync(batch->cpumask); ++ cpumask_clear(batch->cpumask); ++} ++ ++#else ++ ++static inline void sme_dvmsync(struct mm_struct *mm) ++{ ++} ++static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch, ++ struct mm_struct *mm) ++{ ++} ++static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch) ++{ ++} ++ ++#endif /* CONFIG_ARM64_ERRATUM_4193714 */ ++ + /* + * Level-based TLBI operations. + * +@@ -189,12 +254,14 @@ static inline void __tlbi_sync_s1ish(struct mm_struct *mm) + { + dsb(ish); + __repeat_tlbi_sync(vale1is, 0); ++ sme_dvmsync(mm); + } + +-static inline void __tlbi_sync_s1ish_batch(void) ++static inline void __tlbi_sync_s1ish_batch(struct arch_tlbflush_unmap_batch *batch) + { + dsb(ish); + __repeat_tlbi_sync(vale1is, 0); ++ sme_dvmsync_batch(batch); + } + + static inline void __tlbi_sync_s1ish_kernel(void) +@@ -357,7 +424,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) + */ + static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) + { +- __tlbi_sync_s1ish_batch(); ++ __tlbi_sync_s1ish_batch(batch); + } + + /* +@@ -546,6 +613,7 @@ static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *b + struct mm_struct *mm, unsigned long start, unsigned long end) + { + __flush_tlb_range_nosync(mm, start, end, PAGE_SIZE, true, 3); ++ sme_dvmsync_add_pending(batch, mm); + } + #endif + +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index 8cb3b575a0316..6c8c4301d9c6d 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -551,6 +552,23 @@ static const struct midr_range erratum_spec_ssbs_list[] = { + }; + #endif + ++#ifdef CONFIG_ARM64_ERRATUM_4193714 ++static bool has_sme_dvmsync_erratum(const struct arm64_cpu_capabilities *entry, ++ int scope) ++{ ++ if (!id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1))) ++ return false; ++ ++ return is_affected_midr_range(entry, scope); ++} ++ ++static void cpu_enable_sme_dvmsync(const struct arm64_cpu_capabilities *__unused) ++{ ++ if (this_cpu_has_cap(ARM64_WORKAROUND_4193714)) ++ sme_enable_dvmsync(); ++} ++#endif ++ + #ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 + static const struct midr_range erratum_ac03_cpu_38_list[] = { + MIDR_ALL_VERSIONS(MIDR_AMPERE1), +@@ -870,6 +888,18 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list), + }, + #endif ++#ifdef CONFIG_ARM64_ERRATUM_4193714 ++ { ++ .desc = "C1-Pro SME DVMSync early acknowledgement", ++ .capability = ARM64_WORKAROUND_4193714, ++ .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, ++ .matches = has_sme_dvmsync_erratum, ++ .cpu_enable = cpu_enable_sme_dvmsync, ++ /* C1-Pro r0p0 - r1p2 (the latter only when REVIDR_EL1[0]==0) */ ++ .midr_range = MIDR_RANGE(MIDR_C1_PRO, 0, 0, 1, 2), ++ MIDR_FIXED(MIDR_CPU_VAR_REV(1, 2), BIT(0)), ++ }, ++#endif + #ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD + { + .desc = "ARM errata 2966298, 3117295", +diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c +index a9c81715ce59e..5b97dfcf796d9 100644 +--- a/arch/arm64/kernel/entry-common.c ++++ b/arch/arm64/kernel/entry-common.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -84,6 +85,7 @@ static __always_inline void __enter_from_user_mode(struct pt_regs *regs) + { + enter_from_user_mode(regs); + mte_disable_tco_entry(current); ++ sme_enter_from_user_mode(); + } + + static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs) +@@ -102,6 +104,7 @@ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs) + local_irq_disable(); + exit_to_user_mode_prepare(regs); + local_daif_mask(); ++ sme_exit_to_user_mode(); + mte_check_tfsr_exit(); + exit_to_user_mode(); + } +diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c +index e3f8f51748bc9..ca18214ce2abe 100644 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -28,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1384,6 +1386,83 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs) + put_cpu_fpsimd_context(); + } + ++#ifdef CONFIG_ARM64_ERRATUM_4193714 ++ ++/* ++ * SME/CME erratum handling. ++ */ ++static cpumask_t sme_dvmsync_cpus; ++ ++/* ++ * These helpers are only called from non-preemptible contexts, so ++ * smp_processor_id() is safe here. ++ */ ++void sme_set_active(void) ++{ ++ unsigned int cpu = smp_processor_id(); ++ ++ if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus)) ++ return; ++ ++ cpumask_set_cpu(cpu, mm_cpumask(current->mm)); ++ ++ /* ++ * A subsequent (post ERET) SME access may use a stale address ++ * translation. On C1-Pro, a TLBI+DSB on a different CPU will wait for ++ * the completion of cpumask_set_cpu() above as it appears in program ++ * order before the SME access. The post-TLBI+DSB read of mm_cpumask() ++ * will lead to the IPI being issued. ++ * ++ * https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3 ++ */ ++} ++ ++void sme_clear_active(void) ++{ ++ unsigned int cpu = smp_processor_id(); ++ ++ if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus)) ++ return; ++ ++ /* ++ * With SCTLR_EL1.IESB enabled, the SME memory transactions are ++ * completed on entering EL1. ++ */ ++ cpumask_clear_cpu(cpu, mm_cpumask(current->mm)); ++} ++ ++static void sme_dvmsync_ipi(void *unused) ++{ ++ /* ++ * With SCTLR_EL1.IESB on, taking an exception is sufficient to ensure ++ * the completion of the SME memory accesses, so no need for an ++ * explicit DSB. ++ */ ++} ++ ++void sme_do_dvmsync(const struct cpumask *mask) ++{ ++ /* ++ * This is called from the TLB maintenance functions after the DSB ISH ++ * to send the hardware DVMSync message. If this CPU sees the mask as ++ * empty, the remote CPU executing sme_set_active() would have seen ++ * the DVMSync and no IPI required. ++ */ ++ if (cpumask_empty(mask)) ++ return; ++ ++ preempt_disable(); ++ smp_call_function_many(mask, sme_dvmsync_ipi, NULL, true); ++ preempt_enable(); ++} ++ ++void sme_enable_dvmsync(void) ++{ ++ cpumask_set_cpu(smp_processor_id(), &sme_dvmsync_cpus); ++} ++ ++#endif /* CONFIG_ARM64_ERRATUM_4193714 */ ++ + /* + * Trapped SME access + * +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 489554931231e..4c328b7c79ba3 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -339,8 +340,41 @@ void flush_thread(void) + flush_gcs(); + } + ++#ifdef CONFIG_ARM64_ERRATUM_4193714 ++ ++static void arch_dup_tlbbatch_mask(struct task_struct *dst) ++{ ++ /* ++ * Clear the inherited cpumask with memset() to cover both cases where ++ * cpumask_var_t is a pointer or an array. It will be allocated lazily ++ * in sme_dvmsync_add_pending() if CPUMASK_OFFSTACK=y. ++ */ ++ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714)) ++ memset(&dst->tlb_ubc.arch.cpumask, 0, ++ sizeof(dst->tlb_ubc.arch.cpumask)); ++} ++ ++static void arch_release_tlbbatch_mask(struct task_struct *tsk) ++{ ++ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714)) ++ free_cpumask_var(tsk->tlb_ubc.arch.cpumask); ++} ++ ++#else ++ ++static void arch_dup_tlbbatch_mask(struct task_struct *dst) ++{ ++} ++ ++static void arch_release_tlbbatch_mask(struct task_struct *tsk) ++{ ++} ++ ++#endif /* CONFIG_ARM64_ERRATUM_4193714 */ ++ + void arch_release_task_struct(struct task_struct *tsk) + { ++ arch_release_tlbbatch_mask(tsk); + fpsimd_release_task(tsk); + } + +@@ -356,6 +390,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) + + *dst = *src; + ++ arch_dup_tlbbatch_mask(dst); ++ + /* + * Drop stale reference to src's sve_state and convert dst to + * non-streaming FPSIMD mode. +diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps +index 1b32c1232d28d..16d123088ddd4 100644 +--- a/arch/arm64/tools/cpucaps ++++ b/arch/arm64/tools/cpucaps +@@ -101,6 +101,7 @@ WORKAROUND_2077057 + WORKAROUND_2457168 + WORKAROUND_2645198 + WORKAROUND_2658417 ++WORKAROUND_4193714 + WORKAROUND_AMPERE_AC03_CPU_38 + WORKAROUND_AMPERE_AC04_CPU_23 + WORKAROUND_TRBE_OVERWRITE_FILL_MODE +-- +2.53.0 + diff --git a/queue-6.18/arm64-tlb-allow-xzr-argument-to-tlbi-ops.patch b/queue-6.18/arm64-tlb-allow-xzr-argument-to-tlbi-ops.patch new file mode 100644 index 0000000000..2119462a07 --- /dev/null +++ b/queue-6.18/arm64-tlb-allow-xzr-argument-to-tlbi-ops.patch @@ -0,0 +1,59 @@ +From bd04b0c2c4878edbfe8b4fad3e198ce637d1be4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 11:00:12 +0100 +Subject: arm64: tlb: Allow XZR argument to TLBI ops + +From: Mark Rutland + +commit bfd9c931d19aa59fb8371d557774fa169b15db9a upstream. + +The TLBI instruction accepts XZR as a register argument, and for TLBI +operations with a register argument, there is no functional difference +between using XZR or another GPR which contains zeroes. Operations +without a register argument are encoded as if XZR were used. + +Allow the __TLBI_1() macro to use XZR when a register argument is all +zeroes. + +Today this only results in a trivial code saving in +__do_compat_cache_op()'s workaround for Neoverse-N1 erratum #1542419. In +subsequent patches this pattern will be used more generally. + +There should be no functional change as a result of this patch. + +Signed-off-by: Mark Rutland +Cc: Catalin Marinas +Cc: Marc Zyngier +Cc: Oliver Upton +Cc: Ryan Roberts +Cc: Will Deacon +Signed-off-by: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/tlbflush.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index 18a5dc0c9a540..0ddb344f83b4e 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -38,12 +38,12 @@ + : : ) + + #define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \ +- "tlbi " #op ", %0\n" \ ++ "tlbi " #op ", %x0\n" \ + ALTERNATIVE("nop\n nop", \ +- "dsb ish\n tlbi " #op ", %0", \ ++ "dsb ish\n tlbi " #op ", %x0", \ + ARM64_WORKAROUND_REPEAT_TLBI, \ + CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \ +- : : "r" (arg)) ++ : : "rZ" (arg)) + + #define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg) + +-- +2.53.0 + diff --git a/queue-6.18/arm64-tlb-introduce-__tlbi_sync_s1ish_-kernel-batch-.patch b/queue-6.18/arm64-tlb-introduce-__tlbi_sync_s1ish_-kernel-batch-.patch new file mode 100644 index 0000000000..2636567a3c --- /dev/null +++ b/queue-6.18/arm64-tlb-introduce-__tlbi_sync_s1ish_-kernel-batch-.patch @@ -0,0 +1,91 @@ +From b0133a902703b93dd46ef288b1f91ca5a126cd20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 11:00:14 +0100 +Subject: arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB + maintenance + +From: Catalin Marinas + +commit 6bfbf574a39139da11af9fdf6e8d56fe1989cd3e upstream. + +Add __tlbi_sync_s1ish_kernel() similar to __tlbi_sync_s1ish() and use it +for kernel TLB maintenance. Also use this function in flush_tlb_all() +which is only used in relation to kernel mappings. Subsequent patches +can differentiate between workarounds that apply to user only or both +user and kernel. + +A subsequent patch will add mm_struct to __tlbi_sync_s1ish(). Since +arch_tlbbatch_flush() is not specific to an mm, add a corresponding +__tlbi_sync_s1ish_batch() helper. + +Acked-by: Mark Rutland +Cc: Will Deacon +Reviewed-by: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/tlbflush.h | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index c87d13bee37de..387bd86af7021 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -191,6 +191,18 @@ static inline void __tlbi_sync_s1ish(void) + __repeat_tlbi_sync(vale1is, 0); + } + ++static inline void __tlbi_sync_s1ish_batch(void) ++{ ++ dsb(ish); ++ __repeat_tlbi_sync(vale1is, 0); ++} ++ ++static inline void __tlbi_sync_s1ish_kernel(void) ++{ ++ dsb(ish); ++ __repeat_tlbi_sync(vale1is, 0); ++} ++ + /* + * Complete broadcast TLB maintenance issued by hyp code which invalidates + * stage 1 translation information in any translation regime. +@@ -286,7 +298,7 @@ static inline void flush_tlb_all(void) + { + dsb(ishst); + __tlbi(vmalle1is); +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish_kernel(); + isb(); + } + +@@ -345,7 +357,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) + */ + static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) + { +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish_batch(); + } + + /* +@@ -512,7 +524,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end + dsb(ishst); + __flush_tlb_range_op(vaale1is, start, pages, stride, 0, + TLBI_TTL_UNKNOWN, false, lpa2_is_enabled()); +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish_kernel(); + isb(); + } + +@@ -526,7 +538,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr) + + dsb(ishst); + __tlbi(vaae1is, addr); +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish_kernel(); + isb(); + } + +-- +2.53.0 + diff --git a/queue-6.18/arm64-tlb-optimize-arm64_workaround_repeat_tlbi.patch b/queue-6.18/arm64-tlb-optimize-arm64_workaround_repeat_tlbi.patch new file mode 100644 index 0000000000..bb305e32ce --- /dev/null +++ b/queue-6.18/arm64-tlb-optimize-arm64_workaround_repeat_tlbi.patch @@ -0,0 +1,453 @@ +From ff4dc5561fb57e82c7d972a1faa44d736aba839b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 11:00:13 +0100 +Subject: arm64: tlb: Optimize ARM64_WORKAROUND_REPEAT_TLBI + +From: Mark Rutland + +commit a8f78680ee6bf795086384e8aea159a52814f827 upstream. + +The ARM64_WORKAROUND_REPEAT_TLBI workaround is used to mitigate several +errata where broadcast TLBI;DSB sequences don't provide all the +architecturally required synchronization. The workaround performs more +work than necessary, and can have significant overhead. This patch +optimizes the workaround, as explained below. + +The workaround was originally added for Qualcomm Falkor erratum 1009 in +commit: + + d9ff80f83ecb ("arm64: Work around Falkor erratum 1009") + +As noted in the message for that commit, the workaround is applied even +in cases where it is not strictly necessary. + +The workaround was later reused without changes for: + +* Arm Cortex-A76 erratum #1286807 + SDEN v33: https://developer.arm.com/documentation/SDEN-885749/33-0/ + +* Arm Cortex-A55 erratum #2441007 + SDEN v16: https://developer.arm.com/documentation/SDEN-859338/1600/ + +* Arm Cortex-A510 erratum #2441009 + SDEN v19: https://developer.arm.com/documentation/SDEN-1873351/1900/ + +The important details to note are as follows: + +1. All relevant errata only affect the ordering and/or completion of + memory accesses which have been translated by an invalidated TLB + entry. The actual invalidation of TLB entries is unaffected. + +2. The existing workaround is applied to both broadcast and local TLB + invalidation, whereas for all relevant errata it is only necessary to + apply a workaround for broadcast invalidation. + +3. The existing workaround replaces every TLBI with a TLBI;DSB;TLBI + sequence, whereas for all relevant errata it is only necessary to + execute a single additional TLBI;DSB sequence after any number of + TLBIs are completed by a DSB. + + For example, for a sequence of batched TLBIs: + + TLBI [, ] + TLBI [, ] + TLBI [, ] + DSB ISH + + ... the existing workaround will expand this to: + + TLBI [, ] + DSB ISH // additional + TLBI [, ] // additional + TLBI [, ] + DSB ISH // additional + TLBI [, ] // additional + TLBI [, ] + DSB ISH // additional + TLBI [, ] // additional + DSB ISH + + ... whereas it is sufficient to have: + + TLBI [, ] + TLBI [, ] + TLBI [, ] + DSB ISH + TLBI [, ] // additional + DSB ISH // additional + + Using a single additional TBLI and DSB at the end of the sequence can + have significantly lower overhead as each DSB which completes a TLBI + must synchronize with other PEs in the system, with potential + performance effects both locally and system-wide. + +4. The existing workaround repeats each specific TLBI operation, whereas + for all relevant errata it is sufficient for the additional TLBI to + use *any* operation which will be broadcast, regardless of which + translation regime or stage of translation the operation applies to. + + For example, for a single TLBI: + + TLBI ALLE2IS + DSB ISH + + ... the existing workaround will expand this to: + + TLBI ALLE2IS + DSB ISH + TLBI ALLE2IS // additional + DSB ISH // additional + + ... whereas it is sufficient to have: + + TLBI ALLE2IS + DSB ISH + TLBI VALE1IS, XZR // additional + DSB ISH // additional + + As the additional TLBI doesn't have to match a specific earlier TLBI, + the additional TLBI can be implemented in separate code, with no + memory of the earlier TLBIs. The additional TLBI can also use a + cheaper TLBI operation. + +5. The existing workaround is applied to both Stage-1 and Stage-2 TLB + invalidation, whereas for all relevant errata it is only necessary to + apply a workaround for Stage-1 invalidation. + + Architecturally, TLBI operations which invalidate only Stage-2 + information (e.g. IPAS2E1IS) are not required to invalidate TLB + entries which combine information from Stage-1 and Stage-2 + translation table entries, and consequently may not complete memory + accesses translated by those combined entries. In these cases, + completion of memory accesses is only guaranteed after subsequent + invalidation of Stage-1 information (e.g. VMALLE1IS). + +Taking the above points into account, this patch reworks the workaround +logic to reduce overhead: + +* New __tlbi_sync_s1ish() and __tlbi_sync_s1ish_hyp() functions are + added and used in place of any dsb(ish) which is used to complete + broadcast Stage-1 TLB maintenance. When the + ARM64_WORKAROUND_REPEAT_TLBI workaround is enabled, these helpers will + execute an additional TLBI;DSB sequence. + + For consistency, it might make sense to add __tlbi_sync_*() helpers + for local and stage 2 maintenance. For now I've left those with + open-coded dsb() to keep the diff small. + +* The duplication of TLBIs in __TLBI_0() and __TLBI_1() is removed. This + is no longer needed as the necessary synchronization will happen in + __tlbi_sync_s1ish() or __tlbi_sync_s1ish_hyp(). + +* The additional TLBI operation is chosen to have minimal impact: + + - __tlbi_sync_s1ish() uses "TLBI VALE1IS, XZR". This is only used at + EL1 or at EL2 with {E2H,TGE}=={1,1}, where it will target an unused + entry for the reserved ASID in the kernel's own translation regime, + and have no adverse affect. + + - __tlbi_sync_s1ish_hyp() uses "TLBI VALE2IS, XZR". This is only used + in hyp code, where it will target an unused entry in the hyp code's + TTBR0 mapping, and should have no adverse effect. + +* As __TLBI_0() and __TLBI_1() no longer replace each TLBI with a + TLBI;DSB;TLBI sequence, batching TLBIs is worthwhile, and there's no + need for arch_tlbbatch_should_defer() to consider + ARM64_WORKAROUND_REPEAT_TLBI. + +When building defconfig with GCC 15.1.0, compared to v6.19-rc1, this +patch saves ~1KiB of text, makes the vmlinux ~42KiB smaller, and makes +the resulting Image 64KiB smaller: + +| [mark@lakrids:~/src/linux]% size vmlinux-* +| text data bss dec hex filename +| 21179831 19660919 708216 41548966 279fca6 vmlinux-after +| 21181075 19660903 708216 41550194 27a0172 vmlinux-before +| [mark@lakrids:~/src/linux]% ls -l vmlinux-* +| -rwxr-xr-x 1 mark mark 157771472 Feb 4 12:05 vmlinux-after +| -rwxr-xr-x 1 mark mark 157815432 Feb 4 12:05 vmlinux-before +| [mark@lakrids:~/src/linux]% ls -l Image-* +| -rw-r--r-- 1 mark mark 41007616 Feb 4 12:05 Image-after +| -rw-r--r-- 1 mark mark 41073152 Feb 4 12:05 Image-before + +Signed-off-by: Mark Rutland +Cc: Catalin Marinas +Cc: Marc Zyngier +Cc: Oliver Upton +Cc: Ryan Roberts +Cc: Will Deacon +Signed-off-by: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/tlbflush.h | 59 ++++++++++++++++++------------- + arch/arm64/kernel/sys_compat.c | 2 +- + arch/arm64/kvm/hyp/nvhe/mm.c | 2 +- + arch/arm64/kvm/hyp/nvhe/tlb.c | 8 ++--- + arch/arm64/kvm/hyp/pgtable.c | 2 +- + arch/arm64/kvm/hyp/vhe/tlb.c | 10 +++--- + 6 files changed, 47 insertions(+), 36 deletions(-) + +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index 0ddb344f83b4e..c87d13bee37de 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -31,18 +31,10 @@ + */ + #define __TLBI_0(op, arg) asm (ARM64_ASM_PREAMBLE \ + "tlbi " #op "\n" \ +- ALTERNATIVE("nop\n nop", \ +- "dsb ish\n tlbi " #op, \ +- ARM64_WORKAROUND_REPEAT_TLBI, \ +- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \ + : : ) + + #define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \ + "tlbi " #op ", %x0\n" \ +- ALTERNATIVE("nop\n nop", \ +- "dsb ish\n tlbi " #op ", %x0", \ +- ARM64_WORKAROUND_REPEAT_TLBI, \ +- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \ + : : "rZ" (arg)) + + #define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg) +@@ -181,6 +173,34 @@ static inline unsigned long get_trans_granule(void) + (__pages >> (5 * (scale) + 1)) - 1; \ + }) + ++#define __repeat_tlbi_sync(op, arg...) \ ++do { \ ++ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI)) \ ++ break; \ ++ __tlbi(op, ##arg); \ ++ dsb(ish); \ ++} while (0) ++ ++/* ++ * Complete broadcast TLB maintenance issued by the host which invalidates ++ * stage 1 information in the host's own translation regime. ++ */ ++static inline void __tlbi_sync_s1ish(void) ++{ ++ dsb(ish); ++ __repeat_tlbi_sync(vale1is, 0); ++} ++ ++/* ++ * Complete broadcast TLB maintenance issued by hyp code which invalidates ++ * stage 1 translation information in any translation regime. ++ */ ++static inline void __tlbi_sync_s1ish_hyp(void) ++{ ++ dsb(ish); ++ __repeat_tlbi_sync(vale2is, 0); ++} ++ + /* + * TLB Invalidation + * ================ +@@ -266,7 +286,7 @@ static inline void flush_tlb_all(void) + { + dsb(ishst); + __tlbi(vmalle1is); +- dsb(ish); ++ __tlbi_sync_s1ish(); + isb(); + } + +@@ -278,7 +298,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm) + asid = __TLBI_VADDR(0, ASID(mm)); + __tlbi(aside1is, asid); + __tlbi_user(aside1is, asid); +- dsb(ish); ++ __tlbi_sync_s1ish(); + mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL); + } + +@@ -305,20 +325,11 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long uaddr) + { + flush_tlb_page_nosync(vma, uaddr); +- dsb(ish); ++ __tlbi_sync_s1ish(); + } + + static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) + { +- /* +- * TLB flush deferral is not required on systems which are affected by +- * ARM64_WORKAROUND_REPEAT_TLBI, as __tlbi()/__tlbi_user() implementation +- * will have two consecutive TLBI instructions with a dsb(ish) in between +- * defeating the purpose (i.e save overall 'dsb ish' cost). +- */ +- if (alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI)) +- return false; +- + return true; + } + +@@ -334,7 +345,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) + */ + static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) + { +- dsb(ish); ++ __tlbi_sync_s1ish(); + } + + /* +@@ -469,7 +480,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, + { + __flush_tlb_range_nosync(vma->vm_mm, start, end, stride, + last_level, tlb_level); +- dsb(ish); ++ __tlbi_sync_s1ish(); + } + + static inline void flush_tlb_range(struct vm_area_struct *vma, +@@ -501,7 +512,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end + dsb(ishst); + __flush_tlb_range_op(vaale1is, start, pages, stride, 0, + TLBI_TTL_UNKNOWN, false, lpa2_is_enabled()); +- dsb(ish); ++ __tlbi_sync_s1ish(); + isb(); + } + +@@ -515,7 +526,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr) + + dsb(ishst); + __tlbi(vaae1is, addr); +- dsb(ish); ++ __tlbi_sync_s1ish(); + isb(); + } + +diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c +index 4a609e9b65de0..b9d4998c97efa 100644 +--- a/arch/arm64/kernel/sys_compat.c ++++ b/arch/arm64/kernel/sys_compat.c +@@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end) + * We pick the reserved-ASID to minimise the impact. + */ + __tlbi(aside1is, __TLBI_VADDR(0, 0)); +- dsb(ish); ++ __tlbi_sync_s1ish(); + } + + ret = caches_clean_inval_user_pou(start, start + chunk); +diff --git a/arch/arm64/kvm/hyp/nvhe/mm.c b/arch/arm64/kvm/hyp/nvhe/mm.c +index ae8391baebc30..218976287d3fe 100644 +--- a/arch/arm64/kvm/hyp/nvhe/mm.c ++++ b/arch/arm64/kvm/hyp/nvhe/mm.c +@@ -271,7 +271,7 @@ static void fixmap_clear_slot(struct hyp_fixmap_slot *slot) + */ + dsb(ishst); + __tlbi_level(vale2is, __TLBI_VADDR(addr, 0), level); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + } + +diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c +index 48da9ca9763f6..3dc1ce0d27fe6 100644 +--- a/arch/arm64/kvm/hyp/nvhe/tlb.c ++++ b/arch/arm64/kvm/hyp/nvhe/tlb.c +@@ -169,7 +169,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, + */ + dsb(ish); + __tlbi(vmalle1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + + exit_vmid_context(&cxt); +@@ -226,7 +226,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu, + + dsb(ish); + __tlbi(vmalle1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + + exit_vmid_context(&cxt); +@@ -240,7 +240,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu) + enter_vmid_context(mmu, &cxt, false); + + __tlbi(vmalls12e1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + + exit_vmid_context(&cxt); +@@ -266,5 +266,5 @@ void __kvm_flush_vm_context(void) + /* Same remark as in enter_vmid_context() */ + dsb(ish); + __tlbi(alle1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + } +diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c +index c351b4abd5dbf..cbf8cd2e16735 100644 +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -483,7 +483,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx, + *unmapped += granule; + } + +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + mm_ops->put_page(ctx->ptep); + +diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c +index ec25698186297..35855dadfb1b3 100644 +--- a/arch/arm64/kvm/hyp/vhe/tlb.c ++++ b/arch/arm64/kvm/hyp/vhe/tlb.c +@@ -115,7 +115,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, + */ + dsb(ish); + __tlbi(vmalle1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + + exit_vmid_context(&cxt); +@@ -176,7 +176,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu, + + dsb(ish); + __tlbi(vmalle1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + + exit_vmid_context(&cxt); +@@ -192,7 +192,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu) + enter_vmid_context(mmu, &cxt); + + __tlbi(vmalls12e1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + + exit_vmid_context(&cxt); +@@ -217,7 +217,7 @@ void __kvm_flush_vm_context(void) + { + dsb(ishst); + __tlbi(alle1is); +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + } + + /* +@@ -358,7 +358,7 @@ int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding) + default: + ret = -EINVAL; + } +- dsb(ish); ++ __tlbi_sync_s1ish_hyp(); + isb(); + + if (mmu) +-- +2.53.0 + diff --git a/queue-6.18/arm64-tlb-pass-the-corresponding-mm-to-__tlbi_sync_s.patch b/queue-6.18/arm64-tlb-pass-the-corresponding-mm-to-__tlbi_sync_s.patch new file mode 100644 index 0000000000..ac727e4ec4 --- /dev/null +++ b/queue-6.18/arm64-tlb-pass-the-corresponding-mm-to-__tlbi_sync_s.patch @@ -0,0 +1,78 @@ +From 4f8d2ea4fb246a4a5b379779f9bdef1190582b1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 11:00:15 +0100 +Subject: arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish() + +From: Catalin Marinas + +commit d9fb08ba946a6190c371dcd9f9e465d0d52c5021 upstream. + +The mm structure will be used for workarounds that need limiting to +specific tasks. + +Acked-by: Mark Rutland +Cc: Will Deacon +Reviewed-by: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/tlbflush.h | 8 ++++---- + arch/arm64/kernel/sys_compat.c | 2 +- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index 387bd86af7021..ba36e91aefb82 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -185,7 +185,7 @@ do { \ + * Complete broadcast TLB maintenance issued by the host which invalidates + * stage 1 information in the host's own translation regime. + */ +-static inline void __tlbi_sync_s1ish(void) ++static inline void __tlbi_sync_s1ish(struct mm_struct *mm) + { + dsb(ish); + __repeat_tlbi_sync(vale1is, 0); +@@ -310,7 +310,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm) + asid = __TLBI_VADDR(0, ASID(mm)); + __tlbi(aside1is, asid); + __tlbi_user(aside1is, asid); +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish(mm); + mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL); + } + +@@ -337,7 +337,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long uaddr) + { + flush_tlb_page_nosync(vma, uaddr); +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish(vma->vm_mm); + } + + static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm) +@@ -492,7 +492,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, + { + __flush_tlb_range_nosync(vma->vm_mm, start, end, stride, + last_level, tlb_level); +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish(vma->vm_mm); + } + + static inline void flush_tlb_range(struct vm_area_struct *vma, +diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c +index b9d4998c97efa..03fde2677d5be 100644 +--- a/arch/arm64/kernel/sys_compat.c ++++ b/arch/arm64/kernel/sys_compat.c +@@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end) + * We pick the reserved-ASID to minimise the impact. + */ + __tlbi(aside1is, __TLBI_VADDR(0, 0)); +- __tlbi_sync_s1ish(); ++ __tlbi_sync_s1ish(current->mm); + } + + ret = caches_clean_inval_user_pou(start, start + chunk); +-- +2.53.0 + diff --git a/queue-6.18/ipv6-add-null-checks-for-idev-in-srv6-paths.patch b/queue-6.18/ipv6-add-null-checks-for-idev-in-srv6-paths.patch new file mode 100644 index 0000000000..1feb348b65 --- /dev/null +++ b/queue-6.18/ipv6-add-null-checks-for-idev-in-srv6-paths.patch @@ -0,0 +1,59 @@ +From e7f5dc975b2cad05b135843a662814acad72e529 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 15:33:01 +0800 +Subject: ipv6: add NULL checks for idev in SRv6 paths + +From: Minhong He + +[ Upstream commit 06413793526251870e20402c39930804f14d59c0 ] + +__in6_dev_get() can return NULL when the device has no IPv6 configuration +(e.g. MTU < IPV6_MIN_MTU or after NETDEV_UNREGISTER). + +Add NULL checks for idev returned by __in6_dev_get() in both +seg6_hmac_validate_skb() and ipv6_srh_rcv() to prevent potential NULL +pointer dereferences. + +Fixes: 1ababeba4a21 ("ipv6: implement dataplane support for rthdr type 4 (Segment Routing Header)") +Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") +Signed-off-by: Minhong He +Reviewed-by: Andrea Mayer +Link: https://patch.msgid.link/20260316073301.106643-1-heminhong@kylinos.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/exthdrs.c | 4 ++++ + net/ipv6/seg6_hmac.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 310836a0cf17b..1d509b6d16bbd 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -379,6 +379,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) + hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); + + idev = __in6_dev_get(skb->dev); ++ if (!idev) { ++ kfree_skb(skb); ++ return -1; ++ } + + accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled), + READ_ONCE(idev->cnf.seg6_enabled)); +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index ee6bac0160ace..e6964c6b0d381 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -184,6 +184,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) + int require_hmac; + + idev = __in6_dev_get(skb->dev); ++ if (!idev) ++ return false; + + srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); + +-- +2.53.0 + diff --git a/queue-6.18/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch b/queue-6.18/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch new file mode 100644 index 0000000000..649487c56f --- /dev/null +++ b/queue-6.18/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch @@ -0,0 +1,146 @@ +From 0d8406ede5098b92ccd92a55e0fd1491a786a340 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:11:30 +0100 +Subject: net: ethernet: mtk_eth_soc: initialize PPE per-tag-layer MTU + registers + +From: Daniel Golle + +commit 2dddb34dd0d07b01fa770eca89480a4da4f13153 upstream. + +The PPE enforces output frame size limits via per-tag-layer VLAN_MTU +registers that the driver never initializes. The hardware defaults do +not account for PPPoE overhead, causing the PPE to punt encapsulated +frames back to the CPU instead of forwarding them. + +Initialize the registers at PPE start and on MTU changes using the +maximum GMAC MTU. This is a conservative approximation -- the actual +per-PPE requirement depends on egress path, but using the global +maximum ensures the limits are never too small. + +Fixes: ba37b7caf1ed2 ("net: ethernet: mtk_eth_soc: add support for initializing the PPE") +Signed-off-by: Daniel Golle +Link: https://patch.msgid.link/ec995ab8ce8be423267a1cc093147a74d2eb9d82.1775789829.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++++++- + drivers/net/ethernet/mediatek/mtk_ppe.c | 30 +++++++++++++++++++++ + drivers/net/ethernet/mediatek/mtk_ppe.h | 1 + + 3 files changed, 52 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 8d3e15bc867d2..0f676bd72832b 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3567,12 +3567,23 @@ static int mtk_device_event(struct notifier_block *n, unsigned long event, void + return NOTIFY_DONE; + } + ++static int mtk_max_gmac_mtu(struct mtk_eth *eth) ++{ ++ int i, max_mtu = ETH_DATA_LEN; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->netdev); i++) ++ if (eth->netdev[i] && eth->netdev[i]->mtu > max_mtu) ++ max_mtu = eth->netdev[i]->mtu; ++ ++ return max_mtu; ++} ++ + static int mtk_open(struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + struct mtk_mac *target_mac; +- int i, err, ppe_num; ++ int i, err, ppe_num, mtu; + + ppe_num = eth->soc->ppe_num; + +@@ -3619,6 +3630,10 @@ static int mtk_open(struct net_device *dev) + mtk_gdm_config(eth, target_mac->id, gdm_config); + } + ++ mtu = mtk_max_gmac_mtu(eth); ++ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) ++ mtk_ppe_update_mtu(eth->ppe[i], mtu); ++ + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +@@ -4312,6 +4327,7 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + int length = new_mtu + MTK_RX_ETH_HLEN; + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; ++ int max_mtu, i; + + if (rcu_access_pointer(eth->prog) && + length > MTK_PP_MAX_BUF_SIZE) { +@@ -4322,6 +4338,10 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + mtk_set_mcr_max_rx(mac, length); + WRITE_ONCE(dev->mtu, new_mtu); + ++ max_mtu = mtk_max_gmac_mtu(eth); ++ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) ++ mtk_ppe_update_mtu(eth->ppe[i], max_mtu); ++ + return 0; + } + +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c +index ada852adc5f70..fa688a42a22f5 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -973,6 +973,36 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) + } + } + ++void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu) ++{ ++ int base; ++ u32 val; ++ ++ if (!ppe) ++ return; ++ ++ /* The PPE checks output frame size against per-tag-layer MTU limits, ++ * treating PPPoE and DSA tags just like 802.1Q VLAN tags. The Linux ++ * device MTU already accounts for PPPoE (PPPOE_SES_HLEN) and DSA tag ++ * overhead, but 802.1Q VLAN tags are handled transparently without ++ * being reflected by the lower device MTU being increased by 4. ++ * Use the maximum MTU across all GMAC interfaces so that PPE output ++ * frame limits are sufficiently high regardless of which port a flow ++ * egresses through. ++ */ ++ base = ETH_HLEN + mtu; ++ ++ val = FIELD_PREP(MTK_PPE_VLAN_MTU0_NONE, base) | ++ FIELD_PREP(MTK_PPE_VLAN_MTU0_1TAG, base + VLAN_HLEN); ++ ppe_w32(ppe, MTK_PPE_VLAN_MTU0, val); ++ ++ val = FIELD_PREP(MTK_PPE_VLAN_MTU1_2TAG, ++ base + 2 * VLAN_HLEN) | ++ FIELD_PREP(MTK_PPE_VLAN_MTU1_3TAG, ++ base + 3 * VLAN_HLEN); ++ ppe_w32(ppe, MTK_PPE_VLAN_MTU1, val); ++} ++ + void mtk_ppe_start(struct mtk_ppe *ppe) + { + u32 val; +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h +index 223f709e2704f..ba85e39a155bf 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -346,6 +346,7 @@ struct mtk_ppe { + struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index); + + void mtk_ppe_deinit(struct mtk_eth *eth); ++void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu); + void mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + int mtk_ppe_prepare_reset(struct mtk_ppe *ppe); +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series new file mode 100644 index 0000000000..6a67dad2e3 --- /dev/null +++ b/queue-6.18/series @@ -0,0 +1,8 @@ +arm64-tlb-allow-xzr-argument-to-tlbi-ops.patch +arm64-tlb-optimize-arm64_workaround_repeat_tlbi.patch +arm64-tlb-introduce-__tlbi_sync_s1ish_-kernel-batch-.patch +arm64-tlb-pass-the-corresponding-mm-to-__tlbi_sync_s.patch +arm64-cputype-add-c1-pro-definitions.patch +arm64-errata-work-around-early-cme-dvmsync-acknowled.patch +ipv6-add-null-checks-for-idev-in-srv6-paths.patch +net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch diff --git a/queue-6.6/i40e-fix-preempt-count-leak-in-napi-poll-tracepoint.patch b/queue-6.6/i40e-fix-preempt-count-leak-in-napi-poll-tracepoint.patch new file mode 100644 index 0000000000..2784be42ac --- /dev/null +++ b/queue-6.6/i40e-fix-preempt-count-leak-in-napi-poll-tracepoint.patch @@ -0,0 +1,49 @@ +From 889b7bdce4c73577a1f8b956f1a6ea285acaf2cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 15:18:38 +0800 +Subject: i40e: Fix preempt count leak in napi poll tracepoint + +From: Thomas Gleixner + +[ Upstream commit 4b3d54a85bd37ebf2d9836f0d0de775c0ff21af9 ] + +Using get_cpu() in the tracepoint assignment causes an obvious preempt +count leak because nothing invokes put_cpu() to undo it: + + softirq: huh, entered softirq 3 NET_RX with preempt_count 00000100, exited with 00000101? + +This clearly has seen a lot of testing in the last 3+ years... + +Use smp_processor_id() instead. + +Fixes: 6d4d584a7ea8 ("i40e: Add i40e_napi_poll tracepoint") +Signed-off-by: Thomas Gleixner +Cc: Tony Nguyen +Cc: Przemek Kitszel +Cc: intel-wired-lan@lists.osuosl.org +Cc: netdev@vger.kernel.org +Reviewed-by: Joe Damato +Reviewed-by: Aleksandr Loktionov +Signed-off-by: Tony Nguyen +Signed-off-by: Charles Xu +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_trace.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_trace.h b/drivers/net/ethernet/intel/i40e/i40e_trace.h +index 33b4e30f5e004..9b735a9e21140 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_trace.h ++++ b/drivers/net/ethernet/intel/i40e/i40e_trace.h +@@ -88,7 +88,7 @@ TRACE_EVENT(i40e_napi_poll, + __entry->rx_clean_complete = rx_clean_complete; + __entry->tx_clean_complete = tx_clean_complete; + __entry->irq_num = q->irq_num; +- __entry->curr_cpu = get_cpu(); ++ __entry->curr_cpu = smp_processor_id(); + __assign_str(qname, q->name); + __assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV); + __assign_bitmask(irq_affinity, cpumask_bits(&q->affinity_mask), +-- +2.53.0 + diff --git a/queue-6.6/ipv6-add-null-checks-for-idev-in-srv6-paths.patch b/queue-6.6/ipv6-add-null-checks-for-idev-in-srv6-paths.patch new file mode 100644 index 0000000000..c0f9d5c64b --- /dev/null +++ b/queue-6.6/ipv6-add-null-checks-for-idev-in-srv6-paths.patch @@ -0,0 +1,60 @@ +From 2b23ea97b2bbe6d82d4e0be54a70fc90d6951957 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 13:42:58 +0800 +Subject: ipv6: add NULL checks for idev in SRv6 paths + +From: Minhong He + +[ Upstream commit 06413793526251870e20402c39930804f14d59c0 ] + +__in6_dev_get() can return NULL when the device has no IPv6 configuration +(e.g. MTU < IPV6_MIN_MTU or after NETDEV_UNREGISTER). + +Add NULL checks for idev returned by __in6_dev_get() in both +seg6_hmac_validate_skb() and ipv6_srh_rcv() to prevent potential NULL +pointer dereferences. + +Fixes: 1ababeba4a21 ("ipv6: implement dataplane support for rthdr type 4 (Segment Routing Header)") +Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") +Signed-off-by: Minhong He +Reviewed-by: Andrea Mayer +Link: https://patch.msgid.link/20260316073301.106643-1-heminhong@kylinos.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + net/ipv6/exthdrs.c | 4 ++++ + net/ipv6/seg6_hmac.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 676284b6efe8b..a8790163e8b6d 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -378,6 +378,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) + hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); + + idev = __in6_dev_get(skb->dev); ++ if (!idev) { ++ kfree_skb(skb); ++ return -1; ++ } + + accept_seg6 = net->ipv6.devconf_all->seg6_enabled; + if (accept_seg6 > idev->cnf.seg6_enabled) +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index 6e15a65faeccd..bf97bf5ac1387 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -244,6 +244,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) + struct inet6_dev *idev; + + idev = __in6_dev_get(skb->dev); ++ if (!idev) ++ return false; + + srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); + +-- +2.53.0 + diff --git a/queue-6.6/md-raid1-raid10-don-t-ignore-io-flags.patch b/queue-6.6/md-raid1-raid10-don-t-ignore-io-flags.patch new file mode 100644 index 0000000000..0996d8c703 --- /dev/null +++ b/queue-6.6/md-raid1-raid10-don-t-ignore-io-flags.patch @@ -0,0 +1,111 @@ +From f39d7a91b60a71420c5ef55261eb91230a62a733 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:20:53 +0800 +Subject: md/raid1,raid10: don't ignore IO flags + +From: Yu Kuai + +commit e879a0d9cb086c8e52ce6c04e5bfa63825a6213c upstream. + +If blk-wbt is enabled by default, it's found that raid write performance +is quite bad because all IO are throttled by wbt of underlying disks, +due to flag REQ_IDLE is ignored. And turns out this behaviour exist since +blk-wbt is introduced. + +Other than REQ_IDLE, other flags should not be ignored as well, for +example REQ_META can be set for filesystems, clearing it can cause priority +reverse problems; And REQ_NOWAIT should not be cleared as well, because +io will wait instead of failing directly in underlying disks. + +Fix those problems by keep IO flags from master bio. + +Fises: f51d46d0e7cb ("md: add support for REQ_NOWAIT") +Fixes: e34cbd307477 ("blk-wbt: add general throttling mechanism") +Fixes: 5404bc7a87b9 ("[PATCH] Allow file systems to differentiate between data and meta reads") +Link: https://lore.kernel.org/linux-raid/20250227121657.832356-1-yukuai1@huaweicloud.com +Signed-off-by: Yu Kuai +[ Harshit: Resolve conflicts due to missing commit: f2a38abf5f1c + ("md/raid1: Atomic write support") and commit: a1d9b4fd42d9 + ("md/raid10: Atomic write support") in 6.12.y, we don't have Atomic + writes feature in 6.12.y ] +Signed-off-by: Harshit Mogalapalli +Signed-off-by: Greg Kroah-Hartman +[ Based on Harshit's backport for 6.12, fixed minor conflicts for 6.6. ] +Signed-off-by: Charles Xu +Signed-off-by: Sasha Levin +--- + drivers/md/raid1.c | 4 ---- + drivers/md/raid10.c | 7 ------- + 2 files changed, 11 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 4c1f86ca55208..d313e9834d447 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1214,8 +1214,6 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, + struct raid1_info *mirror; + struct bio *read_bio; + struct bitmap *bitmap = mddev->bitmap; +- const enum req_op op = bio_op(bio); +- const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC; + int max_sectors; + int rdisk; + bool r1bio_existed = !!r1_bio; +@@ -1315,7 +1313,6 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, + read_bio->bi_iter.bi_sector = r1_bio->sector + + mirror->rdev->data_offset; + read_bio->bi_end_io = raid1_end_read_request; +- read_bio->bi_opf = op | do_sync; + if (test_bit(FailFast, &mirror->rdev->flags) && + test_bit(R1BIO_FailFast, &r1_bio->state)) + read_bio->bi_opf |= MD_FAILFAST; +@@ -1537,7 +1534,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, + + mbio->bi_iter.bi_sector = (r1_bio->sector + rdev->data_offset); + mbio->bi_end_io = raid1_end_write_request; +- mbio->bi_opf = bio_op(bio) | (bio->bi_opf & (REQ_SYNC | REQ_FUA)); + if (test_bit(FailFast, &rdev->flags) && + !test_bit(WriteMostly, &rdev->flags) && + conf->raid_disks - mddev->degraded > 1) +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 8546ef98bfa7e..6bcf6852c2000 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1168,8 +1168,6 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, + { + struct r10conf *conf = mddev->private; + struct bio *read_bio; +- const enum req_op op = bio_op(bio); +- const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC; + int max_sectors; + struct md_rdev *rdev; + char b[BDEVNAME_SIZE]; +@@ -1250,7 +1248,6 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, + read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr + + choose_data_offset(r10_bio, rdev); + read_bio->bi_end_io = raid10_end_read_request; +- read_bio->bi_opf = op | do_sync; + if (test_bit(FailFast, &rdev->flags) && + test_bit(R10BIO_FailFast, &r10_bio->state)) + read_bio->bi_opf |= MD_FAILFAST; +@@ -1267,9 +1264,6 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, + struct bio *bio, bool replacement, + int n_copy) + { +- const enum req_op op = bio_op(bio); +- const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC; +- const blk_opf_t do_fua = bio->bi_opf & REQ_FUA; + unsigned long flags; + struct r10conf *conf = mddev->private; + struct md_rdev *rdev; +@@ -1295,7 +1289,6 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, + mbio->bi_iter.bi_sector = (r10_bio->devs[n_copy].addr + + choose_data_offset(r10_bio, rdev)); + mbio->bi_end_io = raid10_end_write_request; +- mbio->bi_opf = op | do_sync | do_fua; + if (!replacement && test_bit(FailFast, + &conf->mirrors[devnum].rdev->flags) + && enough(conf, devnum)) +-- +2.53.0 + diff --git a/queue-6.6/net-annotate-data-races-around-sk-sk_-data_ready-wri.patch b/queue-6.6/net-annotate-data-races-around-sk-sk_-data_ready-wri.patch new file mode 100644 index 0000000000..1c38d47be6 --- /dev/null +++ b/queue-6.6/net-annotate-data-races-around-sk-sk_-data_ready-wri.patch @@ -0,0 +1,262 @@ +From e6d40ae68224b135b9761fbd9741769b27da648b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Apr 2026 10:16:26 +0800 +Subject: net: annotate data-races around sk->sk_{data_ready,write_space} + +From: Eric Dumazet + +[ Upstream commit 2ef2b20cf4e04ac8a6ba68493f8780776ff84300 ] + +skmsg (and probably other layers) are changing these pointers +while other cpus might read them concurrently. + +Add corresponding READ_ONCE()/WRITE_ONCE() annotations +for UDP, TCP and AF_UNIX. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Reported-by: syzbot+87f770387a9e5dc6b79b@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/699ee9fc.050a0220.1cd54b.0009.GAE@google.com/ +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Cc: John Fastabend +Cc: Jakub Sitnicki +Cc: Willem de Bruijn +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260225131547.1085509-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Leon Chen +Signed-off-by: Sasha Levin +--- + net/core/skmsg.c | 14 +++++++------- + net/ipv4/tcp.c | 4 ++-- + net/ipv4/tcp_bpf.c | 2 +- + net/ipv4/tcp_input.c | 14 ++++++++------ + net/ipv4/tcp_minisocks.c | 2 +- + net/ipv4/udp.c | 3 ++- + net/ipv4/udp_bpf.c | 2 +- + net/unix/af_unix.c | 8 ++++---- + 8 files changed, 26 insertions(+), 23 deletions(-) + +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index e2bba1e86752e..14208d32eeaf3 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -1204,8 +1204,8 @@ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) + return; + + psock->saved_data_ready = sk->sk_data_ready; +- sk->sk_data_ready = sk_psock_strp_data_ready; +- sk->sk_write_space = sk_psock_write_space; ++ WRITE_ONCE(sk->sk_data_ready, sk_psock_strp_data_ready); ++ WRITE_ONCE(sk->sk_write_space, sk_psock_write_space); + } + + void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) +@@ -1215,8 +1215,8 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) + if (!psock->saved_data_ready) + return; + +- sk->sk_data_ready = psock->saved_data_ready; +- psock->saved_data_ready = NULL; ++ WRITE_ONCE(sk->sk_data_ready, psock->saved_data_ready); ++ WRITE_ONCE(psock->saved_data_ready, NULL); + strp_stop(&psock->strp); + } + +@@ -1298,8 +1298,8 @@ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock) + return; + + psock->saved_data_ready = sk->sk_data_ready; +- sk->sk_data_ready = sk_psock_verdict_data_ready; +- sk->sk_write_space = sk_psock_write_space; ++ WRITE_ONCE(sk->sk_data_ready, sk_psock_verdict_data_ready); ++ WRITE_ONCE(sk->sk_write_space, sk_psock_write_space); + } + + void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock) +@@ -1310,6 +1310,6 @@ void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock) + if (!psock->saved_data_ready) + return; + +- sk->sk_data_ready = psock->saved_data_ready; ++ WRITE_ONCE(sk->sk_data_ready, psock->saved_data_ready); + psock->saved_data_ready = NULL; + } +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 021e1bdbddcb8..33b724dcde6ed 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1333,7 +1333,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) + err = sk_stream_error(sk, flags, err); + /* make sure we wake any epoll edge trigger waiter */ + if (unlikely(tcp_rtx_and_write_queues_empty(sk) && err == -EAGAIN)) { +- sk->sk_write_space(sk); ++ READ_ONCE(sk->sk_write_space)(sk); + tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED); + } + return err; +@@ -3709,7 +3709,7 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname, + break; + case TCP_NOTSENT_LOWAT: + WRITE_ONCE(tp->notsent_lowat, val); +- sk->sk_write_space(sk); ++ READ_ONCE(sk->sk_write_space)(sk); + break; + case TCP_INQ: + if (val > 1 || val < 0) +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 06a185bb1e35c..da5e14ec8ed6d 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -725,7 +725,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) + WRITE_ONCE(sk->sk_prot->unhash, psock->saved_unhash); + tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); + } else { +- sk->sk_write_space = psock->saved_write_space; ++ WRITE_ONCE(sk->sk_write_space, psock->saved_write_space); + /* Pairs with lockless read in sk_clone_lock() */ + sock_replace_proto(sk, psock->sk_proto); + } +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index bec3bbf57a4f1..359d36be04829 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -4936,7 +4936,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) + + if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) { + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFODROP); +- sk->sk_data_ready(sk); ++ READ_ONCE(sk->sk_data_ready)(sk); + tcp_drop_reason(sk, skb, SKB_DROP_REASON_PROTO_MEM); + return; + } +@@ -5143,7 +5143,7 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) + void tcp_data_ready(struct sock *sk) + { + if (tcp_epollin_ready(sk, sk->sk_rcvlowat) || sock_flag(sk, SOCK_DONE)) +- sk->sk_data_ready(sk); ++ READ_ONCE(sk->sk_data_ready)(sk); + } + + static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +@@ -5189,7 +5189,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) + inet_csk(sk)->icsk_ack.pending |= + (ICSK_ACK_NOMEM | ICSK_ACK_NOW); + inet_csk_schedule_ack(sk); +- sk->sk_data_ready(sk); ++ READ_ONCE(sk->sk_data_ready)(sk); + + if (skb_queue_len(&sk->sk_receive_queue)) { + reason = SKB_DROP_REASON_PROTO_MEM; +@@ -5626,7 +5626,9 @@ static void tcp_new_space(struct sock *sk) + tp->snd_cwnd_stamp = tcp_jiffies32; + } + +- INDIRECT_CALL_1(sk->sk_write_space, sk_stream_write_space, sk); ++ INDIRECT_CALL_1(READ_ONCE(sk->sk_write_space), ++ sk_stream_write_space, ++ sk); + } + + /* Caller made space either from: +@@ -5832,7 +5834,7 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *t + BUG(); + WRITE_ONCE(tp->urg_data, TCP_URG_VALID | tmp); + if (!sock_flag(sk, SOCK_DEAD)) +- sk->sk_data_ready(sk); ++ READ_ONCE(sk->sk_data_ready)(sk); + } + } + } +@@ -7216,7 +7218,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, + sock_put(fastopen_sk); + goto drop_and_free; + } +- sk->sk_data_ready(sk); ++ READ_ONCE(sk->sk_data_ready)(sk); + bh_unlock_sock(fastopen_sk); + sock_put(fastopen_sk); + } else { +diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c +index ddb90b9057e75..2eea9672ca01e 100644 +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -876,7 +876,7 @@ int tcp_child_process(struct sock *parent, struct sock *child, + ret = tcp_rcv_state_process(child, skb); + /* Wakeup parent, send SIGIO */ + if (state == TCP_SYN_RECV && child->sk_state != state) +- parent->sk_data_ready(parent); ++ READ_ONCE(parent->sk_data_ready)(parent); + } else { + /* Alas, it is possible again, because we do lookup + * in main socket hash table and lock on listening +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index f301871fa2b1a..3bc1ba937a212 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1560,7 +1560,8 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) + spin_unlock(&list->lock); + + if (!sock_flag(sk, SOCK_DEAD)) +- INDIRECT_CALL_1(sk->sk_data_ready, sock_def_readable, sk); ++ INDIRECT_CALL_1(READ_ONCE(sk->sk_data_ready), ++ sock_def_readable, sk); + + busylock_release(busy); + return 0; +diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c +index 91233e37cd97a..779a3a03762f1 100644 +--- a/net/ipv4/udp_bpf.c ++++ b/net/ipv4/udp_bpf.c +@@ -158,7 +158,7 @@ int udp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) + int family = sk->sk_family == AF_INET ? UDP_BPF_IPV4 : UDP_BPF_IPV6; + + if (restore) { +- sk->sk_write_space = psock->saved_write_space; ++ WRITE_ONCE(sk->sk_write_space, psock->saved_write_space); + sock_replace_proto(sk, psock->sk_proto); + return 0; + } +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index f89cd01247f6b..6bc7aef06a5be 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1678,7 +1678,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, + __skb_queue_tail(&other->sk_receive_queue, skb); + spin_unlock(&other->sk_receive_queue.lock); + unix_state_unlock(other); +- other->sk_data_ready(other); ++ READ_ONCE(other->sk_data_ready)(other); + sock_put(other); + return 0; + +@@ -2138,7 +2138,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, + scm_stat_add(other, skb); + skb_queue_tail(&other->sk_receive_queue, skb); + unix_state_unlock(other); +- other->sk_data_ready(other); ++ READ_ONCE(other->sk_data_ready)(other); + sock_put(other); + scm_destroy(&scm); + return len; +@@ -2206,7 +2206,7 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other + + sk_send_sigurg(other); + unix_state_unlock(other); +- other->sk_data_ready(other); ++ READ_ONCE(other->sk_data_ready)(other); + + return err; + } +@@ -2317,7 +2317,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, + scm_stat_add(other, skb); + skb_queue_tail(&other->sk_receive_queue, skb); + unix_state_unlock(other); +- other->sk_data_ready(other); ++ READ_ONCE(other->sk_data_ready)(other); + sent += size; + } + +-- +2.53.0 + diff --git a/queue-6.6/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch b/queue-6.6/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch new file mode 100644 index 0000000000..b0e0859e5f --- /dev/null +++ b/queue-6.6/net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch @@ -0,0 +1,145 @@ +From 3b7c17677dd8d2db1677766cf35128aa5ca9e50b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 16:11:06 +0100 +Subject: net: ethernet: mtk_eth_soc: initialize PPE per-tag-layer MTU + registers + +From: Daniel Golle + +commit 2dddb34dd0d07b01fa770eca89480a4da4f13153 upstream. + +The PPE enforces output frame size limits via per-tag-layer VLAN_MTU +registers that the driver never initializes. The hardware defaults do +not account for PPPoE overhead, causing the PPE to punt encapsulated +frames back to the CPU instead of forwarding them. + +Initialize the registers at PPE start and on MTU changes using the +maximum GMAC MTU. This is a conservative approximation -- the actual +per-PPE requirement depends on egress path, but using the global +maximum ensures the limits are never too small. + +Fixes: ba37b7caf1ed ("net: ethernet: mtk_eth_soc: add support for initializing the PPE") +Signed-off-by: Daniel Golle +Link: https://patch.msgid.link/ec995ab8ce8be423267a1cc093147a74d2eb9d82.1775789829.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++++++- + drivers/net/ethernet/mediatek/mtk_ppe.c | 30 +++++++++++++++++++++ + drivers/net/ethernet/mediatek/mtk_ppe.h | 1 + + 3 files changed, 52 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index e2d3bda1dc923..74cb96dbff9ee 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3368,11 +3368,22 @@ static int mtk_device_event(struct notifier_block *n, unsigned long event, void + return NOTIFY_DONE; + } + ++static int mtk_max_gmac_mtu(struct mtk_eth *eth) ++{ ++ int i, max_mtu = ETH_DATA_LEN; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->netdev); i++) ++ if (eth->netdev[i] && eth->netdev[i]->mtu > max_mtu) ++ max_mtu = eth->netdev[i]->mtu; ++ ++ return max_mtu; ++} ++ + static int mtk_open(struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; +- int i, err; ++ int i, err, mtu; + + err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); + if (err) { +@@ -3400,6 +3411,10 @@ static int mtk_open(struct net_device *dev) + : MTK_GDMA_TO_PDMA; + mtk_gdm_config(eth, gdm_config); + ++ mtu = mtk_max_gmac_mtu(eth); ++ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) ++ mtk_ppe_update_mtu(eth->ppe[i], mtu); ++ + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +@@ -4088,6 +4103,7 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + int length = new_mtu + MTK_RX_ETH_HLEN; + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; ++ int max_mtu, i; + + if (rcu_access_pointer(eth->prog) && + length > MTK_PP_MAX_BUF_SIZE) { +@@ -4098,6 +4114,10 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) + mtk_set_mcr_max_rx(mac, length); + dev->mtu = new_mtu; + ++ max_mtu = mtk_max_gmac_mtu(eth); ++ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) ++ mtk_ppe_update_mtu(eth->ppe[i], max_mtu); ++ + return 0; + } + +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c +index 6e222a000bf7e..1e033d63b4510 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -971,6 +971,36 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) + } + } + ++void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu) ++{ ++ int base; ++ u32 val; ++ ++ if (!ppe) ++ return; ++ ++ /* The PPE checks output frame size against per-tag-layer MTU limits, ++ * treating PPPoE and DSA tags just like 802.1Q VLAN tags. The Linux ++ * device MTU already accounts for PPPoE (PPPOE_SES_HLEN) and DSA tag ++ * overhead, but 802.1Q VLAN tags are handled transparently without ++ * being reflected by the lower device MTU being increased by 4. ++ * Use the maximum MTU across all GMAC interfaces so that PPE output ++ * frame limits are sufficiently high regardless of which port a flow ++ * egresses through. ++ */ ++ base = ETH_HLEN + mtu; ++ ++ val = FIELD_PREP(MTK_PPE_VLAN_MTU0_NONE, base) | ++ FIELD_PREP(MTK_PPE_VLAN_MTU0_1TAG, base + VLAN_HLEN); ++ ppe_w32(ppe, MTK_PPE_VLAN_MTU0, val); ++ ++ val = FIELD_PREP(MTK_PPE_VLAN_MTU1_2TAG, ++ base + 2 * VLAN_HLEN) | ++ FIELD_PREP(MTK_PPE_VLAN_MTU1_3TAG, ++ base + 3 * VLAN_HLEN); ++ ppe_w32(ppe, MTK_PPE_VLAN_MTU1, val); ++} ++ + void mtk_ppe_start(struct mtk_ppe *ppe) + { + u32 val; +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h +index e3d0ec72bc699..11c76fb8289ac 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -346,6 +346,7 @@ struct mtk_ppe { + struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index); + + void mtk_ppe_deinit(struct mtk_eth *eth); ++void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu); + void mtk_ppe_start(struct mtk_ppe *ppe); + int mtk_ppe_stop(struct mtk_ppe *ppe); + int mtk_ppe_prepare_reset(struct mtk_ppe *ppe); +-- +2.53.0 + diff --git a/queue-6.6/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch b/queue-6.6/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch new file mode 100644 index 0000000000..5d1d440666 --- /dev/null +++ b/queue-6.6/pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch @@ -0,0 +1,97 @@ +From d391355ba7f404ed48f52f2d29838b2e4c649602 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2026 10:41:52 -0400 +Subject: PCI: endpoint: pci-epf-vntb: Remove duplicate resource teardown + +From: Koichiro Den + +[ Upstream commit 0da63230d3ec1ec5fcc443a2314233e95bfece54 ] + +epf_ntb_epc_destroy() duplicates the teardown that the caller is +supposed to perform later. This leads to an oops when .allow_link fails +or when .drop_link is performed. The following is an example oops of the +former case: + + Unable to handle kernel paging request at virtual address dead000000000108 + [...] + [dead000000000108] address between user and kernel address ranges + Internal error: Oops: 0000000096000044 [#1] SMP + [...] + Call trace: + pci_epc_remove_epf+0x78/0xe0 (P) + pci_primary_epc_epf_link+0x88/0xa8 + configfs_symlink+0x1f4/0x5a0 + vfs_symlink+0x134/0x1d8 + do_symlinkat+0x88/0x138 + __arm64_sys_symlinkat+0x74/0xe0 + [...] + +Remove the helper, and drop pci_epc_put(). EPC device refcounting is +tied to the configfs EPC group lifetime, and pci_epc_put() in the +.drop_link path is sufficient. + +Fixes: e35f56bb0330 ("PCI: endpoint: Support NTB transfer between RC and EP") +Signed-off-by: Koichiro Den +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Frank Li +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260226084142.2226875-2-den@valinux.co.jp +[ adjusted context ] +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-vntb.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c +index 33c3f9b980e68..b0cc081490853 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c ++++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c +@@ -673,18 +673,6 @@ static void epf_ntb_mw_bar_clear(struct epf_ntb *ntb, int num_mws) + } + } + +-/** +- * epf_ntb_epc_destroy() - Cleanup NTB EPC interface +- * @ntb: NTB device that facilitates communication between HOST and VHOST +- * +- * Wrapper for epf_ntb_epc_destroy_interface() to cleanup all the NTB interfaces +- */ +-static void epf_ntb_epc_destroy(struct epf_ntb *ntb) +-{ +- pci_epc_remove_epf(ntb->epf->epc, ntb->epf, 0); +- pci_epc_put(ntb->epf->epc); +-} +- + /** + * epf_ntb_init_epc_bar() - Identify BARs to be used for each of the NTB + * constructs (scratchpad region, doorbell, memorywindow) +@@ -1328,7 +1316,7 @@ static int epf_ntb_bind(struct pci_epf *epf) + ret = epf_ntb_init_epc_bar(ntb); + if (ret) { + dev_err(dev, "Failed to create NTB EPC\n"); +- goto err_bar_init; ++ return ret; + } + + ret = epf_ntb_config_spad_bar_alloc(ntb); +@@ -1368,9 +1356,6 @@ static int epf_ntb_bind(struct pci_epf *epf) + err_bar_alloc: + epf_ntb_config_spad_bar_free(ntb); + +-err_bar_init: +- epf_ntb_epc_destroy(ntb); +- + return ret; + } + +@@ -1386,7 +1371,6 @@ static void epf_ntb_unbind(struct pci_epf *epf) + + epf_ntb_epc_cleanup(ntb); + epf_ntb_config_spad_bar_free(ntb); +- epf_ntb_epc_destroy(ntb); + + pci_unregister_driver(&vntb_pci_driver); + } +-- +2.53.0 + diff --git a/queue-6.6/revert-perf-unwind-libdw-fix-invalid-reference-count.patch b/queue-6.6/revert-perf-unwind-libdw-fix-invalid-reference-count.patch new file mode 100644 index 0000000000..1fc4ac1ae5 --- /dev/null +++ b/queue-6.6/revert-perf-unwind-libdw-fix-invalid-reference-count.patch @@ -0,0 +1,53 @@ +From 30d2933e88c73898bff227d5d2c06a31689c1274 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 01:32:22 +0900 +Subject: Revert "perf unwind-libdw: Fix invalid reference counts" + +From: Kenta Akagi + +This reverts commit eddddf4ed7f69697cb54e714e773f764c8d3b67e. + +Upstream commit f815fc0c66e7 ("perf unwind-libdw: Fix invalid reference counts"), +was backported to v6.6.128 as eddddf4ed7f6. + +However, this commit depends on map_symbol__exit, which was introduced +in v6.7 as commit 56e144fe9826 ("perf mem_info: Add and use +map_symbol__exit and addr_map_symbol__exit") and is absent in v6.6.y. +This results in a build failure. + +This is a revert of a backport, so there is no upstream commit. + +Signed-off-by: Kenta Akagi +Signed-off-by: Sasha Levin +--- + tools/perf/util/unwind-libdw.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c +index bd027fdf6af17..6013335a8daea 100644 +--- a/tools/perf/util/unwind-libdw.c ++++ b/tools/perf/util/unwind-libdw.c +@@ -133,8 +133,8 @@ static int entry(u64 ip, struct unwind_info *ui) + } + + e->ip = ip; +- e->ms.maps = maps__get(al.maps); +- e->ms.map = map__get(al.map); ++ e->ms.maps = al.maps; ++ e->ms.map = al.map; + e->ms.sym = al.sym; + + pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", +@@ -319,9 +319,6 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, + if (err) + pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1)); + +- for (i = 0; i < ui->idx; i++) +- map_symbol__exit(&ui->entries[i].ms); +- + dwfl_end(ui->dwfl); + free(ui); + return 0; +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index d7660f72a4..06f10262c7 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -123,3 +123,11 @@ media-as102-fix-to-not-free-memory-after-the-device-is-registered-in-as102_usb_p nilfs2-fix-null-i_assoc_inode-dereference-in-nilfs_mdt_save_to_shadow_map.patch media-vidtv-fix-pass-by-value-structs-causing-msan-warnings.patch media-hackrf-fix-to-not-free-memory-after-the-device-is-registered-in-hackrf_probe.patch +revert-perf-unwind-libdw-fix-invalid-reference-count.patch +pci-endpoint-pci-epf-vntb-remove-duplicate-resource-.patch +ipv6-add-null-checks-for-idev-in-srv6-paths.patch +md-raid1-raid10-don-t-ignore-io-flags.patch +wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch +net-ethernet-mtk_eth_soc-initialize-ppe-per-tag-laye.patch +i40e-fix-preempt-count-leak-in-napi-poll-tracepoint.patch +net-annotate-data-races-around-sk-sk_-data_ready-wri.patch diff --git a/queue-6.6/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch b/queue-6.6/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch new file mode 100644 index 0000000000..5db5125ee3 --- /dev/null +++ b/queue-6.6/wifi-mac80211-always-free-skb-on-ieee80211_tx_prepar.patch @@ -0,0 +1,107 @@ +From 36620529580ac67e7ab56ac7211d049adaf015f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 10:43:09 +0800 +Subject: wifi: mac80211: always free skb on ieee80211_tx_prepare_skb() failure + +From: Felix Fietkau + +[ Upstream commit d5ad6ab61cbd89afdb60881f6274f74328af3ee9 ] + +ieee80211_tx_prepare_skb() has three error paths, but only two of them +free the skb. The first error path (ieee80211_tx_prepare() returning +TX_DROP) does not free it, while invoke_tx_handlers() failure and the +fragmentation check both do. + +Add kfree_skb() to the first error path so all three are consistent, +and remove the now-redundant frees in callers (ath9k, mt76, +mac80211_hwsim) to avoid double-free. + +Document the skb ownership guarantee in the function's kdoc. + +Signed-off-by: Felix Fietkau +Link: https://patch.msgid.link/20260314065455.2462900-1-nbd@nbd.name +Fixes: 06be6b149f7e ("mac80211: add ieee80211_tx_prepare_skb() helper function") +Signed-off-by: Johannes Berg +[ Exclude changes to drivers/net/wireless/mediatek/mt76/scan.c as this file is first + introduced by commit 31083e38548f("wifi: mt76: add code for emulating hardware scanning") + after linux-6.14.] +Signed-off-by: Li hongliang <1468888505@139.com> +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/channel.c | 6 ++---- + drivers/net/wireless/virtual/mac80211_hwsim.c | 1 - + include/net/mac80211.h | 4 ++++ + net/mac80211/tx.c | 4 +++- + 4 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c +index 571062f2e82a7..ba8ec5112afe8 100644 +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -1011,7 +1011,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + + if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) +- goto error; ++ return; + + txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; + if (ath_tx_start(sc->hw, skb, &txctl)) +@@ -1124,10 +1124,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, + + skb->priority = 7; + skb_set_queue_mapping(skb, IEEE80211_AC_VO); +- if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { +- dev_kfree_skb_any(skb); ++ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) + return false; +- } + break; + default: + return false; +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index 1214e7dcc8124..bf12ff0ab06ab 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -2892,7 +2892,6 @@ static void hw_scan_work(struct work_struct *work) + hwsim->tmp_chan->band, + NULL)) { + rcu_read_unlock(); +- kfree_skb(probe); + continue; + } + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index adaa1b2323d2c..85d785060e761 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -7032,6 +7032,10 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, + * @band: the band to transmit on + * @sta: optional pointer to get the station to send the frame to + * ++ * Return: %true if the skb was prepared, %false otherwise. ++ * On failure, the skb is freed by this function; callers must not ++ * free it again. ++ * + * Note: must be called under RCU lock + */ + bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 7eddcb6f96455..2a708132320c4 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1911,8 +1911,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, + struct ieee80211_tx_data tx; + struct sk_buff *skb2; + +- if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) ++ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) { ++ kfree_skb(skb); + return false; ++ } + + info->band = band; + info->control.vif = vif; +-- +2.53.0 + diff --git a/queue-7.0/pwm-th1520-fix-clippy-1-warning.patch b/queue-7.0/pwm-th1520-fix-clippy-1-warning.patch new file mode 100644 index 0000000000..b0ca65d836 --- /dev/null +++ b/queue-7.0/pwm-th1520-fix-clippy-1-warning.patch @@ -0,0 +1,75 @@ +From 11ff874582ebed2ed85bd6d1a64ad66ebf5ca8f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 19:37:19 +0100 +Subject: pwm: th1520: fix `CLIPPY=1` warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Miguel Ojeda + +[ Upstream commit aa8f35172ab66c57d4355a8c4e28d05b44c938e3 ] + +The Rust kernel code should be kept `CLIPPY=1`-clean [1]. + +Clippy reports: + + error: this pattern reimplements `Option::unwrap_or` + --> drivers/pwm/pwm_th1520.rs:64:5 + | + 64 | / (match ns.checked_mul(rate_hz) { + 65 | | Some(product) => product, + 66 | | None => u64::MAX, + 67 | | }) / NSEC_PER_SEC_U64 + | |______^ help: replace with: `ns.checked_mul(rate_hz).unwrap_or(u64::MAX)` + | + = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#manual_unwrap_or + = note: `-D clippy::manual-unwrap-or` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or)]` + +Applying the suggestion then triggers: + + error: manual saturating arithmetic + --> drivers/pwm/pwm_th1520.rs:64:5 + | + 64 | ns.checked_mul(rate_hz).unwrap_or(u64::MAX) / NSEC_PER_SEC_U64 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_mul`: `ns.saturating_mul(rate_hz)` + | + = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#manual_saturating_arithmetic + = note: `-D clippy::manual-saturating-arithmetic` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_saturating_arithmetic)]` + +Thus fix it by using saturating arithmetic, which simplifies the code +as well. + +Link: https://rust-for-linux.com/contributing#submit-checklist-addendum [1] +Fixes: e03724aac758 ("pwm: Add Rust driver for T-HEAD TH1520 SoC") +Signed-off-by: Miguel Ojeda +Reviewed-by: Danilo Krummrich +Reviewed-by: Michal Wilczynski +Link: https://patch.msgid.link/20260121183719.71659-1-ojeda@kernel.org +Signed-off-by: Uwe Kleine-König +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm_th1520.rs | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs +index b0e24ee724e45..36567fc17dcc8 100644 +--- a/drivers/pwm/pwm_th1520.rs ++++ b/drivers/pwm/pwm_th1520.rs +@@ -64,10 +64,7 @@ const fn th1520_pwm_fp(n: u32) -> usize { + fn ns_to_cycles(ns: u64, rate_hz: u64) -> u64 { + const NSEC_PER_SEC_U64: u64 = time::NSEC_PER_SEC as u64; + +- (match ns.checked_mul(rate_hz) { +- Some(product) => product, +- None => u64::MAX, +- }) / NSEC_PER_SEC_U64 ++ ns.saturating_mul(rate_hz) / NSEC_PER_SEC_U64 + } + + fn cycles_to_ns(cycles: u64, rate_hz: u64) -> u64 { +-- +2.53.0 + diff --git a/queue-7.0/series b/queue-7.0/series new file mode 100644 index 0000000000..65df2810bd --- /dev/null +++ b/queue-7.0/series @@ -0,0 +1 @@ +pwm-th1520-fix-clippy-1-warning.patch