--- /dev/null
+From 5a9b47a301f5605ceb0139be5225d5394bae0066 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 09:58:45 -0400
+Subject: nvmet-tcp: Fix potential UAF when ddgst mismatch
+
+From: Sagi Grimberg <sagi@grimberg.me>
+
+commit dbbd07d0a7020b80f6a7028e561908f7b83b3d5a upstream.
+
+Shivam Kumar found via vulnerability testing:
+When data digest is enabled on an NVMe/TCP connection and a digest
+mismatch occurs on a non-final H2C_DATA PDU during an R2T-based
+data transfer, the digest error handler in nvmet_tcp_try_recv_ddgst()
+calls nvmet_req_uninit() - which performs percpu_ref_put() on the
+submission queue - but does NOT mark the command as completed. It
+does not set cqe->status, does not modify rbytes_done, and does not
+clear any flag. When the subsequent fatal error triggers queue
+teardown, nvmet_tcp_uninit_data_in_cmds() iterates all commands,
+checks nvmet_tcp_need_data_in() for each one, and finds that the
+already-uninited command still appears to need data (because
+rbytes_done < transfer_len and cqe->status == 0). It therefore calls
+nvmet_req_uninit() a second time on the same command - a double
+percpu_ref_put against a single percpu_ref_get.
+
+Reported-by: Shivam Kumar <kumar.shivam43666@gmail.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Shivam Kumar <kumar.shivam43666@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/target/tcp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
+index 3d9a830950ef26..27d001fd882168 100644
+--- a/drivers/nvme/target/tcp.c
++++ b/drivers/nvme/target/tcp.c
+@@ -1227,8 +1227,10 @@ static int nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue *queue)
+ queue->idx, cmd->req.cmd->common.command_id,
+ queue->pdu.cmd.hdr.type, le32_to_cpu(cmd->recv_ddgst),
+ le32_to_cpu(cmd->exp_ddgst));
+- if (!(cmd->flags & NVMET_TCP_F_INIT_FAILED))
++ if (!(cmd->flags & NVMET_TCP_F_INIT_FAILED)) {
++ cmd->req.cqe->status = NVME_SC_CMD_SEQ_ERROR;
+ nvmet_req_uninit(&cmd->req);
++ }
+ nvmet_tcp_free_cmd_buffers(cmd);
+ nvmet_tcp_fatal_error(queue);
+ ret = -EPROTO;
+--
+2.53.0
+
--- /dev/null
+nvmet-tcp-fix-potential-uaf-when-ddgst-mismatch.patch
--- /dev/null
+From bd820d84764444c7ea306ee629d6d89e0adeb844 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 09:54:38 -0400
+Subject: nvmet-tcp: Fix potential UAF when ddgst mismatch
+
+From: Sagi Grimberg <sagi@grimberg.me>
+
+commit dbbd07d0a7020b80f6a7028e561908f7b83b3d5a upstream.
+
+Shivam Kumar found via vulnerability testing:
+When data digest is enabled on an NVMe/TCP connection and a digest
+mismatch occurs on a non-final H2C_DATA PDU during an R2T-based
+data transfer, the digest error handler in nvmet_tcp_try_recv_ddgst()
+calls nvmet_req_uninit() - which performs percpu_ref_put() on the
+submission queue - but does NOT mark the command as completed. It
+does not set cqe->status, does not modify rbytes_done, and does not
+clear any flag. When the subsequent fatal error triggers queue
+teardown, nvmet_tcp_uninit_data_in_cmds() iterates all commands,
+checks nvmet_tcp_need_data_in() for each one, and finds that the
+already-uninited command still appears to need data (because
+rbytes_done < transfer_len and cqe->status == 0). It therefore calls
+nvmet_req_uninit() a second time on the same command - a double
+percpu_ref_put against a single percpu_ref_get.
+
+Reported-by: Shivam Kumar <kumar.shivam43666@gmail.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Shivam Kumar <kumar.shivam43666@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/target/tcp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
+index 95081052dce78f..8fe51218441e46 100644
+--- a/drivers/nvme/target/tcp.c
++++ b/drivers/nvme/target/tcp.c
+@@ -1239,8 +1239,10 @@ static int nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue *queue)
+ queue->idx, cmd->req.cmd->common.command_id,
+ queue->pdu.cmd.hdr.type, le32_to_cpu(cmd->recv_ddgst),
+ le32_to_cpu(cmd->exp_ddgst));
+- if (!(cmd->flags & NVMET_TCP_F_INIT_FAILED))
++ if (!(cmd->flags & NVMET_TCP_F_INIT_FAILED)) {
++ cmd->req.cqe->status = NVME_SC_CMD_SEQ_ERROR;
+ nvmet_req_uninit(&cmd->req);
++ }
+ nvmet_tcp_free_cmd_buffers(cmd);
+ nvmet_tcp_fatal_error(queue);
+ ret = -EPROTO;
+--
+2.53.0
+
--- /dev/null
+nvmet-tcp-fix-potential-uaf-when-ddgst-mismatch.patch
--- /dev/null
+From 8589d7617aab572407fe8336f38d373d259fce3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 23:07:15 +0800
+Subject: platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU
+ hotplug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guixiong Wei <weiguixiong@bytedance.com>
+
+commit 6b63520ed14b17bbe9c2103debbd2152dde1fba3 upstream.
+
+When the last CPU of a legacy uncore die goes offline,
+uncore_freq_remove_die_entry() clears control_cpu. During CPU hotplug
+re-add, uncore_freq_add_entry() still populates sysfs attributes before
+assigning the new control CPU. As a result, the current frequency read
+returns -ENXIO and current_freq_khz is omitted from the recreated sysfs
+group.
+
+Assign control_cpu before the initial read paths and before
+create_attr_group() so sysfs recreation uses the new online CPU. If
+sysfs creation fails, restore control_cpu to -1 to keep the error path
+state consistent.
+
+Fixes: 4d73c6772ab7 ("platform/x86: intel-uncore-freq: Conditionally create attribute for read frequency")
+Cc: stable@vger.kernel.org
+Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Link: https://patch.msgid.link/20260602020752.3126-1-weiguixiong@bytedance.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+[weiguixiong: Adapt to legacy uncore_read() and create_attr_group() flow.]
+Signed-off-by: Guixiong Wei <weiguixiong@bytedance.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../intel/uncore-frequency/uncore-frequency-common.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+index dd2e654daf4b17..88316ceb4c6c4d 100644
+--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
++++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+@@ -197,13 +197,18 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu)
+
+ sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
+
++ /*
++ * Set the control CPU before any read path so entry recreation after CPU
++ * hotplug can populate read-only attributes from the new online CPU.
++ */
++ data->control_cpu = cpu;
+ uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz);
+
+ ret = create_attr_group(data, data->name);
+- if (!ret) {
+- data->control_cpu = cpu;
++ if (ret)
++ data->control_cpu = -1;
++ else
+ data->valid = true;
+- }
+
+ uncore_unlock:
+ mutex_unlock(&uncore_lock);
+--
+2.53.0
+
--- /dev/null
+platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
--- /dev/null
+From 74123d40df79a3b64e2f07a8070fd7e48d7f45a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Jun 2026 16:17:44 +0800
+Subject: net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Wayen Yan <win847@gmail.com>
+
+[ Upstream commit 86e51aa24686cc95bb35613059e8b94b9b81e3f0 ]
+
+In airoha_dev_select_queue(), the expression:
+
+ queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES;
+
+implicitly converts to unsigned arithmetic: when skb->priority is 0
+(the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX,
+and UINT_MAX % 8 = 7, routing default best-effort packets to the
+highest-priority QoS queue. This causes QoS inversion where the
+majority of traffic on a PON gateway starves actual high-priority
+flows (VoIP, gaming, etc.).
+
+The "- 1" offset was a leftover from the ETS offload implementation
+that has since been removed. The correct mapping is a direct modulo:
+
+ queue = skb->priority % AIROHA_NUM_QOS_QUEUES;
+
+This maps priority 0 → queue 0 (lowest), priority 7 → queue 7
+(highest), with higher priorities wrapping around. This is the
+standard Linux sk_prio → HW queue mapping used by other drivers.
+
+Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback")
+Link: https://lore.kernel.org/netdev/178185573207.2378135.3729126358670287878@gmail.com/
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Joe Damato <joe@dama.to>
+Signed-off-by: Wayen Yan <win847@gmail.com>
+Link: https://patch.msgid.link/178194366700.2485734.5368768965976693502@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
+index 07f89e08b5faad..db4b87c17a2864 100644
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -2505,7 +2505,7 @@ static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
+ */
+ channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
+ channel = channel % AIROHA_NUM_QOS_CHANNELS;
+- queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
++ queue = skb->priority % AIROHA_NUM_QOS_QUEUES;
+ queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
+
+ return queue < dev->num_tx_queues ? queue : 0;
+--
+2.53.0
+
--- /dev/null
+From 9909ede86efb0d4132c277d7a0005c3a4adb4f2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Feb 2025 11:54:09 +0100
+Subject: net: airoha: Move airoha_eth driver in a dedicated folder
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit fb3dda82fd38ca42140f29b3082324dcdc128293 ]
+
+The airoha_eth driver has no codebase shared with mtk_eth_soc one.
+Moreover, the upcoming features (flowtable hw offloading, PCS, ..) will
+not reuse any code from MediaTek driver. Move the Airoha driver in a
+dedicated folder.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 86e51aa24686 ("net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/Kconfig | 2 ++
+ drivers/net/ethernet/Makefile | 1 +
+ drivers/net/ethernet/airoha/Kconfig | 18 ++++++++++++++++++
+ drivers/net/ethernet/airoha/Makefile | 6 ++++++
+ .../ethernet/{mediatek => airoha}/airoha_eth.c | 0
+ drivers/net/ethernet/mediatek/Kconfig | 8 --------
+ drivers/net/ethernet/mediatek/Makefile | 1 -
+ 7 files changed, 27 insertions(+), 9 deletions(-)
+ create mode 100644 drivers/net/ethernet/airoha/Kconfig
+ create mode 100644 drivers/net/ethernet/airoha/Makefile
+ rename drivers/net/ethernet/{mediatek => airoha}/airoha_eth.c (100%)
+
+diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
+index 9a542e3c9b05d8..0875b5706b83ac 100644
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -20,6 +20,8 @@ source "drivers/net/ethernet/actions/Kconfig"
+ source "drivers/net/ethernet/adaptec/Kconfig"
+ source "drivers/net/ethernet/aeroflex/Kconfig"
+ source "drivers/net/ethernet/agere/Kconfig"
++source "drivers/net/ethernet/airoha/Kconfig"
++source "drivers/net/ethernet/mellanox/Kconfig"
+ source "drivers/net/ethernet/alacritech/Kconfig"
+ source "drivers/net/ethernet/allwinner/Kconfig"
+ source "drivers/net/ethernet/alteon/Kconfig"
+diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
+index 99fa180dedb805..67182339469a0d 100644
+--- a/drivers/net/ethernet/Makefile
++++ b/drivers/net/ethernet/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
+ obj-$(CONFIG_GRETH) += aeroflex/
+ obj-$(CONFIG_NET_VENDOR_ADI) += adi/
+ obj-$(CONFIG_NET_VENDOR_AGERE) += agere/
++obj-$(CONFIG_NET_VENDOR_AIROHA) += airoha/
+ obj-$(CONFIG_NET_VENDOR_ALACRITECH) += alacritech/
+ obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
+ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
+diff --git a/drivers/net/ethernet/airoha/Kconfig b/drivers/net/ethernet/airoha/Kconfig
+new file mode 100644
+index 00000000000000..b6a131845f13b2
+--- /dev/null
++++ b/drivers/net/ethernet/airoha/Kconfig
+@@ -0,0 +1,18 @@
++# SPDX-License-Identifier: GPL-2.0-only
++config NET_VENDOR_AIROHA
++ bool "Airoha devices"
++ depends on ARCH_AIROHA || COMPILE_TEST
++ help
++ If you have a Airoha SoC with ethernet, say Y.
++
++if NET_VENDOR_AIROHA
++
++config NET_AIROHA
++ tristate "Airoha SoC Gigabit Ethernet support"
++ depends on NET_DSA || !NET_DSA
++ select PAGE_POOL
++ help
++ This driver supports the gigabit ethernet MACs in the
++ Airoha SoC family.
++
++endif #NET_VENDOR_AIROHA
+diff --git a/drivers/net/ethernet/airoha/Makefile b/drivers/net/ethernet/airoha/Makefile
+new file mode 100644
+index 00000000000000..73a6f3680a4c4c
+--- /dev/null
++++ b/drivers/net/ethernet/airoha/Makefile
+@@ -0,0 +1,6 @@
++# SPDX-License-Identifier: GPL-2.0-only
++#
++# Airoha for the Mediatek SoCs built-in ethernet macs
++#
++
++obj-$(CONFIG_NET_AIROHA) += airoha_eth.o
+diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
+similarity index 100%
+rename from drivers/net/ethernet/mediatek/airoha_eth.c
+rename to drivers/net/ethernet/airoha/airoha_eth.c
+diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig
+index 95c4405b7d7bee..7bfd3f230ff507 100644
+--- a/drivers/net/ethernet/mediatek/Kconfig
++++ b/drivers/net/ethernet/mediatek/Kconfig
+@@ -7,14 +7,6 @@ config NET_VENDOR_MEDIATEK
+
+ if NET_VENDOR_MEDIATEK
+
+-config NET_AIROHA
+- tristate "Airoha SoC Gigabit Ethernet support"
+- depends on NET_DSA || !NET_DSA
+- select PAGE_POOL
+- help
+- This driver supports the gigabit ethernet MACs in the
+- Airoha SoC family.
+-
+ config NET_MEDIATEK_SOC_WED
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ def_bool NET_MEDIATEK_SOC != n
+diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
+index ddbb7f4a516cac..03e008fbc859b3 100644
+--- a/drivers/net/ethernet/mediatek/Makefile
++++ b/drivers/net/ethernet/mediatek/Makefile
+@@ -11,4 +11,3 @@ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
+ endif
+ obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o
+ obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o
+-obj-$(CONFIG_NET_AIROHA) += airoha_eth.o
+--
+2.53.0
+
--- /dev/null
+From ee8407aaccb0b1309cbe6bcdc3c76d02c1a41e32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 23:07:44 +0800
+Subject: platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU
+ hotplug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guixiong Wei <weiguixiong@bytedance.com>
+
+commit 6b63520ed14b17bbe9c2103debbd2152dde1fba3 upstream.
+
+When the last CPU of a legacy uncore die goes offline,
+uncore_freq_remove_die_entry() clears control_cpu. During CPU hotplug
+re-add, uncore_freq_add_entry() still populates sysfs attributes before
+assigning the new control CPU. As a result, the current frequency read
+returns -ENXIO and current_freq_khz is omitted from the recreated sysfs
+group.
+
+Assign control_cpu before the initial read paths and before
+create_attr_group() so sysfs recreation uses the new online CPU. If
+sysfs creation fails, restore control_cpu to -1 to keep the error path
+state consistent.
+
+Fixes: 4d73c6772ab7 ("platform/x86: intel-uncore-freq: Conditionally create attribute for read frequency")
+Cc: stable@vger.kernel.org
+Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Link: https://patch.msgid.link/20260602020752.3126-1-weiguixiong@bytedance.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Guixiong Wei <weiguixiong@bytedance.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../x86/intel/uncore-frequency/uncore-frequency-common.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+index e22b683a7a434c..2e4e2bcc3c6e71 100644
+--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
++++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+@@ -240,15 +240,20 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu)
+ sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
+ }
+
++ /*
++ * Set the control CPU before any read path so entry recreation after CPU
++ * hotplug can populate read-only attributes from the new online CPU.
++ */
++ data->control_cpu = cpu;
+ uncore_read(data, &data->initial_min_freq_khz, UNCORE_INDEX_MIN_FREQ);
+ uncore_read(data, &data->initial_max_freq_khz, UNCORE_INDEX_MAX_FREQ);
+
+ ret = create_attr_group(data, data->name);
+ if (ret) {
++ data->control_cpu = -1;
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
+ ida_free(&intel_uncore_ida, data->instance_id);
+ } else {
+- data->control_cpu = cpu;
+ data->valid = true;
+ }
+
+--
+2.53.0
+
--- /dev/null
+platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
+net-airoha-move-airoha_eth-driver-in-a-dedicated-fol.patch
+net-airoha-fix-skb-priority-underflow-in-airoha_dev_.patch
--- /dev/null
+From d2b3ca4dd9a5d02ebc39c791138dd5f56831a2b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 23:07:57 +0800
+Subject: platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU
+ hotplug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guixiong Wei <weiguixiong@bytedance.com>
+
+commit 6b63520ed14b17bbe9c2103debbd2152dde1fba3 upstream.
+
+When the last CPU of a legacy uncore die goes offline,
+uncore_freq_remove_die_entry() clears control_cpu. During CPU hotplug
+re-add, uncore_freq_add_entry() still populates sysfs attributes before
+assigning the new control CPU. As a result, the current frequency read
+returns -ENXIO and current_freq_khz is omitted from the recreated sysfs
+group.
+
+Assign control_cpu before the initial read paths and before
+create_attr_group() so sysfs recreation uses the new online CPU. If
+sysfs creation fails, restore control_cpu to -1 to keep the error path
+state consistent.
+
+Fixes: 4d73c6772ab7 ("platform/x86: intel-uncore-freq: Conditionally create attribute for read frequency")
+Cc: stable@vger.kernel.org
+Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Link: https://patch.msgid.link/20260602020752.3126-1-weiguixiong@bytedance.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Guixiong Wei <weiguixiong@bytedance.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../x86/intel/uncore-frequency/uncore-frequency-common.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+index 65897fae17dfba..6091b617480ff6 100644
+--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
++++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+@@ -274,15 +274,20 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu)
+ sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
+ }
+
++ /*
++ * Set the control CPU before any read path so entry recreation after CPU
++ * hotplug can populate read-only attributes from the new online CPU.
++ */
++ data->control_cpu = cpu;
+ uncore_read(data, &data->initial_min_freq_khz, UNCORE_INDEX_MIN_FREQ);
+ uncore_read(data, &data->initial_max_freq_khz, UNCORE_INDEX_MAX_FREQ);
+
+ ret = create_attr_group(data, data->name);
+ if (ret) {
++ data->control_cpu = -1;
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
+ ida_free(&intel_uncore_ida, data->instance_id);
+ } else {
+- data->control_cpu = cpu;
+ data->valid = true;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 0ad28e2e40b0d6eb34c62a357edc992edf33f338 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jul 2026 12:02:38 +0200
+Subject: posix-cpu-timers: Prevent UAF caused by non-leader exec() race
+
+From: Thomas Gleixner <tglx@kernel.org>
+
+commit 920f893f735e92ba3a1cd9256899a186b161928d upstream.
+
+Wongi and Jungwoo decoded and reported a non-leader exec() related race
+which can result in an UAF:
+
+ sys_timer_delete() exec()
+ posix_cpu_timer_del()
+ // Observes old leader
+ p = pid_task(pid, pid_type); de_thread()
+ switch_leader();
+ release_task(old_leader)
+ __exit_signal(old_leader)
+ sighand = lock(old_leader, sighand);
+ posix_cpu_timers*_exit();
+ sighand = lock_task_sighand(p) unhash_task(old_leader);
+ sh = lock(p, sighand) old_leader->sighand = NULL;
+ unlock(sighand);
+ (p->sighand == NULL)
+ unlock(sh)
+ return NULL;
+
+ // Returns without action
+ if(!sighand)
+ return 0;
+ free_posix_timer();
+
+This is "harmless" unless the deleted timer was armed and enqueued in
+p->signal because on exec() a TGID targeted timer is inherited.
+
+As sys_timer_delete() freed the underlying posix timer object
+run_posix_cpu_timers() or any timerqueue related add/delete operations on
+other timers will access the freed object's timerqueue node, which results
+in an UAF.
+
+There is a similar problem vs. posix_cpu_timer_set(). For regular posix
+timers it just transiently returns -ESRCH to user space, but for the use
+case in do_cpu_nanosleep() it's the same UAF just that the k_itimer is
+allocated on the stack.
+
+Also posix_cpu_timer_rearm() fails to rearm the timer, which means it stops
+to expire.
+
+While debating solutions Frederic pointed out another problem:
+
+ posix_cpu_timer_del(tmr)
+ __exit_signal(p)
+ posix_cpu_timers*_exit(p);
+ unhash_task(p);
+ p->sighand = NULL;
+ sh = lock_task_sighand(p)
+ sighand = p->sighand;
+ if (!sighand)
+ return NULL;
+ lock(sighand);
+
+ if (!sh)
+ WARN_ON_ONCE(timer_queued(tmr));
+
+On weakly ordered architectures it is not guaranteed that
+posix_cpu_timer_del() will observe the stores in posix_cpu_timers*_exit()
+when p->sighand is observed as NULL, which means the WARN() can be a false
+positive.
+
+Solve these issues by:
+
+ 1) Changing the store in __exit_signal() to smp_store_release().
+
+ 2) Adding a smp_acquire__after_ctrl_dep() into the !sighand path
+ of lock_task_sighand().
+
+ 3) Creating a helper function for looking up the task and locking sighand
+ which does not return when sighand == NULL. Instead it retries the
+ task lookup and only if that fails it gives up.
+
+ 4) Using that helper in the three affected functions.
+
+observes all preceeding stores, i.e. the stores in posix_cpu_timers*_exit()
+and the ones in unhash_task().
+
+gracefully. When the task lookup returns the old leader, but sighand ==
+NULL then it retries. In the non-leader exec() case the subsequent task
+lookup will observe the new leader due to #1/#2. In normal exit() scenarios
+the subsequent lookup fails.
+
+When the task lookup fails, the function also checks whether the timer is
+still enqueued and issues a warning if that's the case. Unfortunately there
+is nothing which can be done about it, but as the task is already not
+longer visible the timer should not be accessed anymore. This check also
+requires memory ordering, which is not provided when the first lookup
+fails. To achieve that the check is preceeded by a smp_rmb() which pairs
+with the smp_wmb() in write_seqlock() in __exit_signal(). That ensures that
+the stores in posix_cpu_timers*_exit() are visible.
+
+The history of the non-leader exec() issue goes back to the early days of
+posix CPU timers, which stored a pointer to the group leader task in the
+timer. That obviously fails when a non-leader exec() switches the leader.
+commit e0a70217107e ("posix-cpu-timers: workaround to suppress the problems
+with mt exec") added a temporary workaround for that in 2010 which survived
+about 10 years. The fix for the workaround changed the task pointer to a
+pid pointer, but failed to see the subtle race described above. So the
+Fixes tag picks that commit, which seems to be halfways accurate.
+
+Thanks to Frederic Weissbecker, Oleg Nesterov and Peter Zijlstra for
+review, feedback and suggestions and to Wongi and Jungwoo for the excellent
+bug report and analysis!
+
+Fixes: 55e8c8eb2c7b ("posix-cpu-timers: Store a reference to a pid not a task")
+Reported-by: Wongi Lee <qw3rtyp0@gmail.com>
+Reported-by: Jungwoo Lee <jwlee2217@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Reviewed-by: Oleg Nesterov <oleg@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/exit.c | 7 +-
+ kernel/signal.c | 10 +-
+ kernel/time/posix-cpu-timers.c | 173 ++++++++++++++++++++++-----------
+ 3 files changed, 130 insertions(+), 60 deletions(-)
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index c832946823f488..a32bc65569a508 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -212,7 +212,12 @@ static void __exit_signal(struct release_task_post *post, struct task_struct *ts
+ __unhash_process(post, tsk, group_dead);
+ write_sequnlock(&sig->stats_lock);
+
+- tsk->sighand = NULL;
++ /*
++ * Ensure that all preceeding state is visible. Pairs with
++ * the smp_acquire__after_ctrl_dep() in the sighand == NULL
++ * path of lock_task_sighand().
++ */
++ smp_store_release(&tsk->sighand, NULL);
+ spin_unlock(&sighand->siglock);
+
+ __cleanup_sighand(sighand);
+diff --git a/kernel/signal.c b/kernel/signal.c
+index 810098300ecdcb..e1843b71efff13 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -1364,8 +1364,16 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
+ rcu_read_lock();
+ for (;;) {
+ sighand = rcu_dereference(tsk->sighand);
+- if (unlikely(sighand == NULL))
++ if (unlikely(sighand == NULL)) {
++ /*
++ * Pairs with the smp_store_release() in
++ * __exit_signal(). It ensures that all state
++ * modifications to the task preceeding the store are
++ * visible to the callers of lock_task_sighand().
++ */
++ smp_acquire__after_ctrl_dep();
+ break;
++ }
+
+ /*
+ * This sighand can be already freed and even reused, but
+diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
+index d14523fbc146cd..2d64972fd0804b 100644
+--- a/kernel/time/posix-cpu-timers.c
++++ b/kernel/time/posix-cpu-timers.c
+@@ -461,6 +461,109 @@ static void disarm_timer(struct k_itimer *timer, struct task_struct *p)
+ trigger_base_recalc_expires(timer, p);
+ }
+
++/*
++ * Lookup the task via timer->it.cpu.pid and attempt to lock the task's sighand.
++ *
++ * This can race with the reaping of the task:
++ *
++ * CPU0 CPU1
++ *
++ * // Finds task
++ * p = pid_task(pid, pid_type); __exit_signal(p)
++ * lock(p, sighand);
++ * posix_cpu_timers*_exit();
++ * sighand = lock_task_sighand(p); unhash_task(p);
++ * p->sighand = NULL;
++ * unlock(sighand);
++ *
++ * In this case sighand is NULL, which means the task and the associated timer
++ * queue cannot be longer accessed safely.
++ *
++ * __exit_signal() invokes posix_cpu_timers_exit() and if the thread group is
++ * dead it also invokes posix_cpu_timers_group_exit(). These functions delete
++ * all pending timers from the related timer queues. The POSIX timers (k_itimer)
++ * themself are still accessible, but not longer connected to the task.
++ *
++ * exec() works slightly differently. The task which exec()'s terminates all
++ * other threads in the thread group and runs __exit_signal() on them. As the
++ * thread group is not dead they only clean up the per task timers via
++ * posix_cpu_timers_exit().
++ *
++ * As the TGID on exec() stays the same per process timers stay queued, if they
++ * are armed. This works without a problem when exec() is done by the thread
++ * group leader. If a non-leader thread exec()'s this can end up in the
++ * following scenario:
++ *
++ * CPU0 CPU1
++ * // Returns old leader
++ * p = pid_task(pid, pid_type); de_thread()
++ * switch_leader()
++ * release_task(old leader)
++ * __exit_signal()
++ * old_leader->sighand = NULL;
++ * // Returns NULL
++ * sighand = lock_task_sighand(p)
++ *
++ * That's problematic for several functions:
++ *
++ * - posix_cpu_timer_del(): If the timer is still enqueued on the task the
++ * underlying k_itimer will be freed which results in a UAF in
++ * run_posix_cpu_timers() or on timerqueue related add/delete operations.
++ * If the timer is not enqueued, the failure is harmless
++ *
++ * - posix_cpu_timer_set(): Independent of the enqueued state that results in a
++ * transient failure which is user space visible (-ESRCH) for regular posix
++ * timers. But for the use case in do_cpu_nanosleep() it's the same UAF
++ * problem just that the timer is allocated on the stack.
++ *
++ * - posix_cpu_timer_rearm(): Timer is not enqueued at that point, but this
++ * silently ignores the rearm request, which is a functional problem as the
++ * timer wont expire anymore.
++ */
++static struct task_struct *timer_lock_sighand(struct k_itimer *timer, unsigned long *flags)
++{
++ enum pid_type type = clock_pid_type(timer->it_clock);
++ struct cpu_timer *ctmr = &timer->it.cpu;
++
++ guard(rcu)();
++
++ for (;;) {
++ struct task_struct *t = pid_task(timer->it.cpu.pid, type);
++
++ /* Fail if the task cannot be found. */
++ if (!t)
++ break;
++
++ /* Try to lock the task's sighand */
++ if (lock_task_sighand(t, flags))
++ return t;
++
++ /*
++ * The next PID lookup might either fail or return the new
++ * leader. This is correct for both exit() and exec().
++ */
++ }
++
++ /*
++ * If the timer is still enqueued, warn. There is nothing safe to do
++ * here as there might be two timers in there which are removed in
++ * parallel and that will cause more damage than good. This should never
++ * happen!
++ *
++ * Ensure that the stores to the timer and timerqueue are visible:
++ *
++ * __exit_signal()
++ * posix_cpu_timers*_exit()
++ * write_seqlock(seqlock)
++ * smp_wmb(); <-------
++ * __unhash_process() | !pid_task()
++ * ----> smp_rmb();
++ * WARN_ON_ONCE(...)
++ */
++ smp_rmb();
++ WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
++ return NULL;
++}
+
+ /*
+ * Clean up a CPU-clock timer that is about to be destroyed.
+@@ -470,29 +573,13 @@ static void disarm_timer(struct k_itimer *timer, struct task_struct *p)
+ */
+ static int posix_cpu_timer_del(struct k_itimer *timer)
+ {
+- struct cpu_timer *ctmr = &timer->it.cpu;
+- struct sighand_struct *sighand;
+ struct task_struct *p;
+ unsigned long flags;
+ int ret = 0;
+
+- rcu_read_lock();
+- p = cpu_timer_task_rcu(timer);
+- if (!p)
+- goto out;
++ p = timer_lock_sighand(timer, &flags);
+
+- /*
+- * Protect against sighand release/switch in exit/exec and process/
+- * thread timer list entry concurrent read/writes.
+- */
+- sighand = lock_task_sighand(p, &flags);
+- if (unlikely(sighand == NULL)) {
+- /*
+- * This raced with the reaping of the task. The exit cleanup
+- * should have removed this timer from the timer queue.
+- */
+- WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
+- } else {
++ if (likely(p)) {
+ if (timer->it.cpu.firing) {
+ /*
+ * Prevent signal delivery. The timer cannot be dequeued
+@@ -508,11 +595,8 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
+ unlock_task_sighand(p, &flags);
+ }
+
+-out:
+- rcu_read_unlock();
+-
+ if (!ret) {
+- put_pid(ctmr->pid);
++ put_pid(timer->it.cpu.pid);
+ timer->it_status = POSIX_TIMER_DISARMED;
+ }
+ return ret;
+@@ -626,21 +710,17 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
+ clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
+ struct cpu_timer *ctmr = &timer->it.cpu;
+ u64 old_expires, new_expires, now;
+- struct sighand_struct *sighand;
+ struct task_struct *p;
+ unsigned long flags;
+ int ret = 0;
+
+- rcu_read_lock();
+- p = cpu_timer_task_rcu(timer);
+- if (!p) {
+- /*
+- * If p has just been reaped, we can no
+- * longer get any information about it at all.
+- */
+- rcu_read_unlock();
++ p = timer_lock_sighand(timer, &flags);
++ /*
++ * If p has just been reaped, we can no longer get any information about
++ * it at all.
++ */
++ if (!p)
+ return -ESRCH;
+- }
+
+ /*
+ * Use the to_ktime conversion because that clamps the maximum
+@@ -648,20 +728,6 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
+ */
+ new_expires = ktime_to_ns(timespec64_to_ktime(new->it_value));
+
+- /*
+- * Protect against sighand release/switch in exit/exec and p->cpu_timers
+- * and p->signal->cpu_timers read/write in arm_timer()
+- */
+- sighand = lock_task_sighand(p, &flags);
+- /*
+- * If p has just been reaped, we can no
+- * longer get any information about it at all.
+- */
+- if (unlikely(sighand == NULL)) {
+- rcu_read_unlock();
+- return -ESRCH;
+- }
+-
+ /* Retrieve the current expiry time before disarming the timer */
+ old_expires = cpu_timer_getexpires(ctmr);
+
+@@ -698,7 +764,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
+ /* Retry if the timer expiry is running concurrently */
+ if (unlikely(ret)) {
+ unlock_task_sighand(p, &flags);
+- goto out;
++ return ret;
+ }
+
+ /* Convert relative expiry time to absolute */
+@@ -733,8 +799,6 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
+ */
+ if (!sigev_none && new_expires && now >= new_expires)
+ cpu_timer_fire(timer);
+-out:
+- rcu_read_unlock();
+ return ret;
+ }
+
+@@ -1018,19 +1082,12 @@ static void check_process_timers(struct task_struct *tsk,
+ static bool posix_cpu_timer_rearm(struct k_itimer *timer)
+ {
+ clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
+- struct sighand_struct *sighand;
+ struct task_struct *p;
+ unsigned long flags;
+ u64 now;
+
+- guard(rcu)();
+- p = cpu_timer_task_rcu(timer);
+- if (!p)
+- return true;
+-
+- /* Protect timer list r/w in arm_timer() */
+- sighand = lock_task_sighand(p, &flags);
+- if (unlikely(sighand == NULL))
++ p = timer_lock_sighand(timer, &flags);
++ if (unlikely(!p))
+ return true;
+
+ /*
+--
+2.53.0
+
--- /dev/null
+From a28e4c85d2a7b518fc6c697fe2bd2e8caebb00e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Apr 2026 13:53:56 +0200
+Subject: posix-timers: Expand timer_[re]arm() callbacks with a boolean return
+ value
+
+From: Thomas Gleixner <tglx@kernel.org>
+
+commit 6fdb2677a594ab38eade927919bbd4d9688bfa1c upstream.
+
+In order to catch expiry times which are already in the past the
+timer_arm() and timer_rearm() callbacks need to be able to report back to
+the caller whether the timer has been queued or not.
+
+Change the function signature and let all implementations return true for
+now. While at it simplify posix_cpu_timer_rearm().
+
+No functional change intended.
+
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://patch.msgid.link/20260408114952.130222296@kernel.org
+Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/alarmtimer.c | 6 ++++--
+ kernel/time/posix-cpu-timers.c | 18 ++++++++++--------
+ kernel/time/posix-timers.c | 6 ++++--
+ kernel/time/posix-timers.h | 4 ++--
+ 4 files changed, 20 insertions(+), 14 deletions(-)
+
+diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
+index 189ee8bbc3e650..525df334b15a79 100644
+--- a/kernel/time/alarmtimer.c
++++ b/kernel/time/alarmtimer.c
+@@ -521,12 +521,13 @@ static void alarm_handle_timer(struct alarm *alarm, ktime_t now)
+ * alarm_timer_rearm - Posix timer callback for rearming timer
+ * @timr: Pointer to the posixtimer data struct
+ */
+-static void alarm_timer_rearm(struct k_itimer *timr)
++static bool alarm_timer_rearm(struct k_itimer *timr)
+ {
+ struct alarm *alarm = &timr->it.alarm.alarmtimer;
+
+ timr->it_overrun += alarm_forward_now(alarm, timr->it_interval);
+ alarm_start(alarm, alarm->node.expires);
++ return true;
+ }
+
+ /**
+@@ -582,7 +583,7 @@ static void alarm_timer_wait_running(struct k_itimer *timr)
+ * @absolute: Expiry value is absolute time
+ * @sigev_none: Posix timer does not deliver signals
+ */
+-static void alarm_timer_arm(struct k_itimer *timr, ktime_t expires,
++static bool alarm_timer_arm(struct k_itimer *timr, ktime_t expires,
+ bool absolute, bool sigev_none)
+ {
+ struct alarm *alarm = &timr->it.alarm.alarmtimer;
+@@ -594,6 +595,7 @@ static void alarm_timer_arm(struct k_itimer *timr, ktime_t expires,
+ alarm->node.expires = expires;
+ else
+ alarm_start(&timr->it.alarm.alarmtimer, expires);
++ return true;
+ }
+
+ /**
+diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
+index 99affd9e228ec5..d14523fbc146cd 100644
+--- a/kernel/time/posix-cpu-timers.c
++++ b/kernel/time/posix-cpu-timers.c
+@@ -19,7 +19,7 @@
+
+ #include "posix-timers.h"
+
+-static void posix_cpu_timer_rearm(struct k_itimer *timer);
++static bool posix_cpu_timer_rearm(struct k_itimer *timer);
+
+ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
+ {
+@@ -1011,24 +1011,27 @@ static void check_process_timers(struct task_struct *tsk,
+ /*
+ * This is called from the signal code (via posixtimer_rearm)
+ * when the last timer signal was delivered and we have to reload the timer.
++ *
++ * Return true unconditionally so the core code assumes the timer to be
++ * armed. Otherwise it would requeue the signal.
+ */
+-static void posix_cpu_timer_rearm(struct k_itimer *timer)
++static bool posix_cpu_timer_rearm(struct k_itimer *timer)
+ {
+ clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
+- struct task_struct *p;
+ struct sighand_struct *sighand;
++ struct task_struct *p;
+ unsigned long flags;
+ u64 now;
+
+- rcu_read_lock();
++ guard(rcu)();
+ p = cpu_timer_task_rcu(timer);
+ if (!p)
+- goto out;
++ return true;
+
+ /* Protect timer list r/w in arm_timer() */
+ sighand = lock_task_sighand(p, &flags);
+ if (unlikely(sighand == NULL))
+- goto out;
++ return true;
+
+ /*
+ * Fetch the current sample and update the timer's expiry time.
+@@ -1045,8 +1048,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
+ */
+ arm_timer(timer, p);
+ unlock_task_sighand(p, &flags);
+-out:
+- rcu_read_unlock();
++ return true;
+ }
+
+ /**
+diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
+index 56e17b625c72e8..3082129d836c24 100644
+--- a/kernel/time/posix-timers.c
++++ b/kernel/time/posix-timers.c
+@@ -295,12 +295,13 @@ static inline int timer_overrun_to_int(struct k_itimer *timr)
+ return (int)timr->it_overrun_last;
+ }
+
+-static void common_hrtimer_rearm(struct k_itimer *timr)
++static bool common_hrtimer_rearm(struct k_itimer *timr)
+ {
+ struct hrtimer *timer = &timr->it.real.timer;
+
+ timr->it_overrun += hrtimer_forward_now(timer, timr->it_interval);
+ hrtimer_restart(timer);
++ return true;
+ }
+
+ static bool __posixtimer_deliver_signal(struct kernel_siginfo *info, struct k_itimer *timr)
+@@ -802,7 +803,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
+ return timer_overrun_to_int(scoped_timer);
+ }
+
+-static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires,
++static bool common_hrtimer_arm(struct k_itimer *timr, ktime_t expires,
+ bool absolute, bool sigev_none)
+ {
+ struct hrtimer *timer = &timr->it.real.timer;
+@@ -829,6 +830,7 @@ static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires,
+
+ if (!sigev_none)
+ hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
++ return true;
+ }
+
+ static int common_hrtimer_try_to_cancel(struct k_itimer *timr)
+diff --git a/kernel/time/posix-timers.h b/kernel/time/posix-timers.h
+index 7f259e845d240c..4ea9611dd7165c 100644
+--- a/kernel/time/posix-timers.h
++++ b/kernel/time/posix-timers.h
+@@ -27,11 +27,11 @@ struct k_clock {
+ int (*timer_del)(struct k_itimer *timr);
+ void (*timer_get)(struct k_itimer *timr,
+ struct itimerspec64 *cur_setting);
+- void (*timer_rearm)(struct k_itimer *timr);
++ bool (*timer_rearm)(struct k_itimer *timr);
+ s64 (*timer_forward)(struct k_itimer *timr, ktime_t now);
+ ktime_t (*timer_remaining)(struct k_itimer *timr, ktime_t now);
+ int (*timer_try_to_cancel)(struct k_itimer *timr);
+- void (*timer_arm)(struct k_itimer *timr, ktime_t expires,
++ bool (*timer_arm)(struct k_itimer *timr, ktime_t expires,
+ bool absolute, bool sigev_none);
+ void (*timer_wait_running)(struct k_itimer *timr);
+ };
+--
+2.53.0
+
--- /dev/null
+posix-timers-expand-timer_-re-arm-callbacks-with-a-b.patch
+posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch
+platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
--- /dev/null
+From 34104e1a1950e4b198193e544befd7f3ee530cd3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 23:07:28 +0800
+Subject: platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU
+ hotplug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guixiong Wei <weiguixiong@bytedance.com>
+
+commit 6b63520ed14b17bbe9c2103debbd2152dde1fba3 upstream.
+
+When the last CPU of a legacy uncore die goes offline,
+uncore_freq_remove_die_entry() clears control_cpu. During CPU hotplug
+re-add, uncore_freq_add_entry() still populates sysfs attributes before
+assigning the new control CPU. As a result, the current frequency read
+returns -ENXIO and current_freq_khz is omitted from the recreated sysfs
+group.
+
+Assign control_cpu before the initial read paths and before
+create_attr_group() so sysfs recreation uses the new online CPU. If
+sysfs creation fails, restore control_cpu to -1 to keep the error path
+state consistent.
+
+Fixes: 4d73c6772ab7 ("platform/x86: intel-uncore-freq: Conditionally create attribute for read frequency")
+Cc: stable@vger.kernel.org
+Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Link: https://patch.msgid.link/20260602020752.3126-1-weiguixiong@bytedance.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+[weiguixiong: Adapt to legacy uncore_read() and instance_id naming.]
+Signed-off-by: Guixiong Wei <weiguixiong@bytedance.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../x86/intel/uncore-frequency/uncore-frequency-common.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+index 33bb58dc3f78c3..b362e0170a6256 100644
+--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
++++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+@@ -238,14 +238,19 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu)
+ sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
+ }
+
++ /*
++ * Set the control CPU before any read path so entry recreation after CPU
++ * hotplug can populate read-only attributes from the new online CPU.
++ */
++ data->control_cpu = cpu;
+ uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz);
+
+ ret = create_attr_group(data, data->name);
+ if (ret) {
++ data->control_cpu = -1;
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
+ ida_free(&intel_uncore_ida, data->instance_id);
+ } else {
+- data->control_cpu = cpu;
+ data->valid = true;
+ }
+
+--
+2.53.0
+
--- /dev/null
+platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
--- /dev/null
+From 4bf93941e8f6b5404c661c251b55429dcc11ed32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 22:17:44 +0800
+Subject: platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU
+ hotplug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guixiong Wei <weiguixiong@bytedance.com>
+
+commit 6b63520ed14b17bbe9c2103debbd2152dde1fba3 upstream.
+
+When the last CPU of a legacy uncore die goes offline,
+uncore_freq_remove_die_entry() clears control_cpu. During CPU hotplug
+re-add, uncore_freq_add_entry() still populates sysfs attributes before
+assigning the new control CPU. As a result, the current frequency read
+returns -ENXIO and current_freq_khz is omitted from the recreated sysfs
+group.
+
+Assign control_cpu before the initial read paths and before
+create_attr_group() so sysfs recreation uses the new online CPU. If
+sysfs creation fails, restore control_cpu to -1 to keep the error path
+state consistent.
+
+Fixes: 4d73c6772ab7 ("platform/x86: intel-uncore-freq: Conditionally create attribute for read frequency")
+Cc: stable@vger.kernel.org
+Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Link: https://patch.msgid.link/20260602020752.3126-1-weiguixiong@bytedance.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Guixiong Wei <weiguixiong@bytedance.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../x86/intel/uncore-frequency/uncore-frequency-common.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+index 7070c94324e0ed..f8137ee92e4754 100644
+--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
++++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+@@ -275,15 +275,20 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu)
+ data->package_id, data->die_id);
+ }
+
++ /*
++ * Set the control CPU before any read path so entry recreation after CPU
++ * hotplug can populate read-only attributes from the new online CPU.
++ */
++ data->control_cpu = cpu;
+ uncore_read(data, &data->initial_min_freq_khz, UNCORE_INDEX_MIN_FREQ);
+ uncore_read(data, &data->initial_max_freq_khz, UNCORE_INDEX_MAX_FREQ);
+
+ ret = create_attr_group(data, data->name);
+ if (ret) {
++ data->control_cpu = -1;
+ if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
+ ida_free(&intel_uncore_ida, data->instance_id);
+ } else {
+- data->control_cpu = cpu;
+ data->valid = true;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 1ab09f47aef9a808bc1163d31f7caa9ff1076572 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 15:04:03 +0000
+Subject: sched_ext: Skip ops.set_weight() for disabled tasks
+
+From: Kuba Piecuch <jpiecuch@google.com>
+
+commit 0e2f4ab68a89fad42e0f5a9ff4b740738e7aa1d6 upstream.
+
+When switching a task's sched_class away from sched_ext, we get the
+following sequence of events in __sched_setscheduler():
+
+sched_change_begin()
+ switched_from_scx()
+ scx_disable_task(p)
+ ops.disable(p)
+__setscheduler_params()
+ set_load_weight()
+ reweight_task_scx(p)
+ ops.set_weight(p)
+p->sched_class = next_class;
+sched_change_end()
+ ...
+
+Notably, ops.set_weight() is called _after_ ops.disable().
+This violates the expected semantics of the callbacks, the expectation
+being that ops.disable() can only be followed by ops.exit_task() or
+ops.enable().
+
+Skipping the weight adjustment for disabled tasks should be harmless
+since the weight will be recalculated in scx_enable_task() if the task
+ever rejoins SCX.
+
+Fixes: 637b0682821b ("sched: Fold sched_class::switch{ing,ed}_{to,from}() into the change pattern")
+Cc: stable@vger.kernel.org # v6.19+
+Signed-off-by: Kuba Piecuch <jpiecuch@google.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/ext.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
+index 5d2d19473a82e8..8429bebc21a19a 100644
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -3904,6 +3904,17 @@ static void reweight_task_scx(struct rq *rq, struct task_struct *p,
+ if (task_dead_and_done(p))
+ return;
+
++ /*
++ * When switching sched_class away from SCX, reweight_task_scx()
++ * is called _after_ scx_disable_task(). Skip calling ops.set_weight()
++ * since the BPF scheduler may have already forgotten the task in
++ * ops.disable().
++ * p->scx.weight will be recalculated in scx_enable_task() if the task
++ * ever returns to SCX class.
++ */
++ if (scx_get_task_state(p) != SCX_TASK_ENABLED)
++ return;
++
+ p->scx.weight = sched_weight_to_cgroup(scale_load_down(lw->weight));
+ if (SCX_HAS_OP(sch, set_weight))
+ SCX_CALL_OP_TASK(sch, set_weight, rq, p, p->scx.weight);
+--
+2.53.0
+
--- /dev/null
+platform-x86-intel-uncore-freq-fix-current_freq_khz-.patch
+sched_ext-skip-ops.set_weight-for-disabled-tasks.patch