From: Sasha Levin Date: Sun, 9 Mar 2025 19:40:21 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v5.4.291~91 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=881e69b022c1e9623564642317c9387d4ee305af;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/alsa-usx2y-validate-nrpacks-module-parameter-on-prob.patch b/queue-6.1/alsa-usx2y-validate-nrpacks-module-parameter-on-prob.patch new file mode 100644 index 0000000000..4fd1bdee72 --- /dev/null +++ b/queue-6.1/alsa-usx2y-validate-nrpacks-module-parameter-on-prob.patch @@ -0,0 +1,135 @@ +From d65d058e7f43d30d424810f727acd1f8dc7e8b63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 13:04:13 +0300 +Subject: ALSA: usx2y: validate nrpacks module parameter on probe + +From: Murad Masimov + +[ Upstream commit 172a0f509723fe4741d4b8e9190cf434b18320d8 ] + +The module parameter defines number of iso packets per one URB. User is +allowed to set any value to the parameter of type int, which can lead to +various kinds of weird and incorrect behavior like integer overflows, +truncations, etc. Number of packets should be a small non-negative number. + +Since this parameter is read-only, its value can be validated on driver +probe. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Murad Masimov +Link: https://patch.msgid.link/20250303100413.835-1-m.masimov@mt-integration.ru +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/usx2y/usbusx2y.c | 11 +++++++++++ + sound/usb/usx2y/usbusx2y.h | 26 ++++++++++++++++++++++++++ + sound/usb/usx2y/usbusx2yaudio.c | 27 --------------------------- + 3 files changed, 37 insertions(+), 27 deletions(-) + +diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c +index 4c4ce0319d624..0fe989a633769 100644 +--- a/sound/usb/usx2y/usbusx2y.c ++++ b/sound/usb/usx2y/usbusx2y.c +@@ -151,6 +151,12 @@ static int snd_usx2y_card_used[SNDRV_CARDS]; + static void snd_usx2y_card_private_free(struct snd_card *card); + static void usx2y_unlinkseq(struct snd_usx2y_async_seq *s); + ++#ifdef USX2Y_NRPACKS_VARIABLE ++int nrpacks = USX2Y_NRPACKS; /* number of packets per urb */ ++module_param(nrpacks, int, 0444); ++MODULE_PARM_DESC(nrpacks, "Number of packets per URB."); ++#endif ++ + /* + * pipe 4 is used for switching the lamps, setting samplerate, volumes .... + */ +@@ -433,6 +439,11 @@ static int snd_usx2y_probe(struct usb_interface *intf, + struct snd_card *card; + int err; + ++#ifdef USX2Y_NRPACKS_VARIABLE ++ if (nrpacks < 0 || nrpacks > USX2Y_NRPACKS_MAX) ++ return -EINVAL; ++#endif ++ + if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || + (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && + le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && +diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h +index 8d82f5cc2fe1c..0538c457921e6 100644 +--- a/sound/usb/usx2y/usbusx2y.h ++++ b/sound/usb/usx2y/usbusx2y.h +@@ -7,6 +7,32 @@ + + #define NRURBS 2 + ++/* Default value used for nr of packs per urb. ++ * 1 to 4 have been tested ok on uhci. ++ * To use 3 on ohci, you'd need a patch: ++ * look for "0000425-linux-2.6.9-rc4-mm1_ohci-hcd.patch.gz" on ++ * "https://bugtrack.alsa-project.org/alsa-bug/bug_view_page.php?bug_id=0000425" ++ * ++ * 1, 2 and 4 work out of the box on ohci, if I recall correctly. ++ * Bigger is safer operation, smaller gives lower latencies. ++ */ ++#define USX2Y_NRPACKS 4 ++ ++#define USX2Y_NRPACKS_MAX 1024 ++ ++/* If your system works ok with this module's parameter ++ * nrpacks set to 1, you might as well comment ++ * this define out, and thereby produce smaller, faster code. ++ * You'd also set USX2Y_NRPACKS to 1 then. ++ */ ++#define USX2Y_NRPACKS_VARIABLE 1 ++ ++#ifdef USX2Y_NRPACKS_VARIABLE ++extern int nrpacks; ++#define nr_of_packs() nrpacks ++#else ++#define nr_of_packs() USX2Y_NRPACKS ++#endif + + #define URBS_ASYNC_SEQ 10 + #define URB_DATA_LEN_ASYNC_SEQ 32 +diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c +index 5197599e7aa61..98d0e8edc9832 100644 +--- a/sound/usb/usx2y/usbusx2yaudio.c ++++ b/sound/usb/usx2y/usbusx2yaudio.c +@@ -28,33 +28,6 @@ + #include "usx2y.h" + #include "usbusx2y.h" + +-/* Default value used for nr of packs per urb. +- * 1 to 4 have been tested ok on uhci. +- * To use 3 on ohci, you'd need a patch: +- * look for "0000425-linux-2.6.9-rc4-mm1_ohci-hcd.patch.gz" on +- * "https://bugtrack.alsa-project.org/alsa-bug/bug_view_page.php?bug_id=0000425" +- * +- * 1, 2 and 4 work out of the box on ohci, if I recall correctly. +- * Bigger is safer operation, smaller gives lower latencies. +- */ +-#define USX2Y_NRPACKS 4 +- +-/* If your system works ok with this module's parameter +- * nrpacks set to 1, you might as well comment +- * this define out, and thereby produce smaller, faster code. +- * You'd also set USX2Y_NRPACKS to 1 then. +- */ +-#define USX2Y_NRPACKS_VARIABLE 1 +- +-#ifdef USX2Y_NRPACKS_VARIABLE +-static int nrpacks = USX2Y_NRPACKS; /* number of packets per urb */ +-#define nr_of_packs() nrpacks +-module_param(nrpacks, int, 0444); +-MODULE_PARM_DESC(nrpacks, "Number of packets per URB."); +-#else +-#define nr_of_packs() USX2Y_NRPACKS +-#endif +- + static int usx2y_urb_capt_retire(struct snd_usx2y_substream *subs) + { + struct urb *urb = subs->completed_urb; +-- +2.39.5 + diff --git a/queue-6.1/be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch b/queue-6.1/be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch new file mode 100644 index 0000000000..81b2476288 --- /dev/null +++ b/queue-6.1/be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch @@ -0,0 +1,951 @@ +From 5a423fd96605f08ec6e9861e62a8f530886c4807 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 18:41:29 +0200 +Subject: be2net: fix sleeping while atomic bugs in be_ndo_bridge_getlink + +From: Nikolay Aleksandrov + +[ Upstream commit 1a82d19ca2d6835904ee71e2d40fd331098f94a0 ] + +Partially revert commit b71724147e73 ("be2net: replace polling with +sleeping in the FW completion path") w.r.t mcc mutex it introduces and the +use of usleep_range. The be2net be_ndo_bridge_getlink() callback is +called with rcu_read_lock, so this code has been broken for a long time. +Both the mutex_lock and the usleep_range can cause the issue Ian Kumlien +reported[1]. The call path is: +be_ndo_bridge_getlink -> be_cmd_get_hsw_config -> be_mcc_notify_wait -> +be_mcc_wait_compl -> usleep_range() + +[1] https://lore.kernel.org/netdev/CAA85sZveppNgEVa_FD+qhOMtG_AavK9_mFiU+jWrMtXmwqefGA@mail.gmail.com/ + +Tested-by: Ian Kumlien +Fixes: b71724147e73 ("be2net: replace polling with sleeping in the FW completion path") +Signed-off-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250227164129.1201164-1-razor@blackwall.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/emulex/benet/be.h | 2 +- + drivers/net/ethernet/emulex/benet/be_cmds.c | 197 ++++++++++---------- + drivers/net/ethernet/emulex/benet/be_main.c | 2 +- + 3 files changed, 100 insertions(+), 101 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h +index 61fe9625bed1f..06f42e5b5149f 100644 +--- a/drivers/net/ethernet/emulex/benet/be.h ++++ b/drivers/net/ethernet/emulex/benet/be.h +@@ -562,7 +562,7 @@ struct be_adapter { + struct be_dma_mem mbox_mem_alloced; + + struct be_mcc_obj mcc_obj; +- struct mutex mcc_lock; /* For serializing mcc cmds to BE card */ ++ spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ + spinlock_t mcc_cq_lock; + + u16 cfg_num_rx_irqs; /* configured via set-channels */ +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 08ec84cd21c04..d00f4e29c9d88 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -573,7 +573,7 @@ int be_process_mcc(struct be_adapter *adapter) + /* Wait till no more pending mcc requests are present */ + static int be_mcc_wait_compl(struct be_adapter *adapter) + { +-#define mcc_timeout 12000 /* 12s timeout */ ++#define mcc_timeout 120000 /* 12s timeout */ + int i, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + +@@ -587,7 +587,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) + + if (atomic_read(&mcc_obj->q.used) == 0) + break; +- usleep_range(500, 1000); ++ udelay(100); + } + if (i == mcc_timeout) { + dev_err(&adapter->pdev->dev, "FW not responding\n"); +@@ -865,7 +865,7 @@ static bool use_mcc(struct be_adapter *adapter) + static int be_cmd_lock(struct be_adapter *adapter) + { + if (use_mcc(adapter)) { +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + return 0; + } else { + return mutex_lock_interruptible(&adapter->mbox_lock); +@@ -876,7 +876,7 @@ static int be_cmd_lock(struct be_adapter *adapter) + static void be_cmd_unlock(struct be_adapter *adapter) + { + if (use_mcc(adapter)) +- return mutex_unlock(&adapter->mcc_lock); ++ return spin_unlock_bh(&adapter->mcc_lock); + else + return mutex_unlock(&adapter->mbox_lock); + } +@@ -1046,7 +1046,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, + struct be_cmd_req_mac_query *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1075,7 +1075,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1087,7 +1087,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, const u8 *mac_addr, + struct be_cmd_req_pmac_add *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1112,7 +1112,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, const u8 *mac_addr, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + + if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST) + status = -EPERM; +@@ -1130,7 +1130,7 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) + if (pmac_id == -1) + return 0; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1150,7 +1150,7 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) + status = be_mcc_notify_wait(adapter); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1413,7 +1413,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, + struct be_dma_mem *q_mem = &rxq->dma_mem; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1443,7 +1443,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1507,7 +1507,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) + struct be_cmd_req_q_destroy *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1524,7 +1524,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) + q->created = false; + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1592,7 +1592,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) + struct be_cmd_req_hdr *hdr; + int status = 0; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1620,7 +1620,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) + adapter->stats_cmd_sent = true; + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1636,7 +1636,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, + CMD_SUBSYSTEM_ETH)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1659,7 +1659,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, + adapter->stats_cmd_sent = true; + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1696,7 +1696,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, + struct be_cmd_req_link_status *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + if (link_status) + *link_status = LINK_DOWN; +@@ -1735,7 +1735,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1746,7 +1746,7 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) + struct be_cmd_req_get_cntl_addnl_attribs *req; + int status = 0; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1761,7 +1761,7 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) + + status = be_mcc_notify(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1810,7 +1810,7 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf) + if (!get_fat_cmd.va) + return -ENOMEM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + while (total_size) { + buf_size = min(total_size, (u32)60*1024); +@@ -1848,9 +1848,9 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf) + log_offset += buf_size; + } + err: ++ spin_unlock_bh(&adapter->mcc_lock); + dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size, + get_fat_cmd.va, get_fat_cmd.dma); +- mutex_unlock(&adapter->mcc_lock); + return status; + } + +@@ -1861,7 +1861,7 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter) + struct be_cmd_req_get_fw_version *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1884,7 +1884,7 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter) + sizeof(adapter->fw_on_flash)); + } + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1898,7 +1898,7 @@ static int __be_cmd_modify_eqd(struct be_adapter *adapter, + struct be_cmd_req_modify_eq_delay *req; + int status = 0, i; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1921,7 +1921,7 @@ static int __be_cmd_modify_eqd(struct be_adapter *adapter, + + status = be_mcc_notify(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1948,7 +1948,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, + struct be_cmd_req_vlan_config *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -1970,7 +1970,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -1981,7 +1981,7 @@ static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) + struct be_cmd_req_rx_filter *req = mem->va; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2014,7 +2014,7 @@ static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2045,7 +2045,7 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2065,7 +2065,7 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) + status = be_mcc_notify_wait(adapter); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + + if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED) + return -EOPNOTSUPP; +@@ -2084,7 +2084,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2107,7 +2107,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2188,7 +2188,7 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, + if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) + return 0; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2213,7 +2213,7 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2225,7 +2225,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, + struct be_cmd_req_enable_disable_beacon *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2246,7 +2246,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, + status = be_mcc_notify_wait(adapter); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2257,7 +2257,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) + struct be_cmd_req_get_beacon_state *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2281,7 +2281,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2305,7 +2305,7 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, + return -ENOMEM; + } + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2327,7 +2327,7 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, + memcpy(data, resp->page_data + off, len); + } + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); + return status; + } +@@ -2344,7 +2344,7 @@ static int lancer_cmd_write_object(struct be_adapter *adapter, + void *ctxt = NULL; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + adapter->flash_status = 0; + + wrb = wrb_from_mccq(adapter); +@@ -2386,7 +2386,7 @@ static int lancer_cmd_write_object(struct be_adapter *adapter, + if (status) + goto err_unlock; + +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + + if (!wait_for_completion_timeout(&adapter->et_cmd_compl, + msecs_to_jiffies(60000))) +@@ -2405,7 +2405,7 @@ static int lancer_cmd_write_object(struct be_adapter *adapter, + return status; + + err_unlock: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2459,7 +2459,7 @@ static int lancer_cmd_delete_object(struct be_adapter *adapter, + struct be_mcc_wrb *wrb; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2477,7 +2477,7 @@ static int lancer_cmd_delete_object(struct be_adapter *adapter, + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2490,7 +2490,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, + struct lancer_cmd_resp_read_object *resp; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2524,7 +2524,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, + } + + err_unlock: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2536,7 +2536,7 @@ static int be_cmd_write_flashrom(struct be_adapter *adapter, + struct be_cmd_write_flashrom *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + adapter->flash_status = 0; + + wrb = wrb_from_mccq(adapter); +@@ -2561,7 +2561,7 @@ static int be_cmd_write_flashrom(struct be_adapter *adapter, + if (status) + goto err_unlock; + +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + + if (!wait_for_completion_timeout(&adapter->et_cmd_compl, + msecs_to_jiffies(40000))) +@@ -2572,7 +2572,7 @@ static int be_cmd_write_flashrom(struct be_adapter *adapter, + return status; + + err_unlock: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -2583,7 +2583,7 @@ static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + struct be_mcc_wrb *wrb; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -2610,7 +2610,7 @@ static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + memcpy(flashed_crc, req->crc, 4); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3216,7 +3216,7 @@ int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, + struct be_cmd_req_acpi_wol_magic_config *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3233,7 +3233,7 @@ int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, + status = be_mcc_notify_wait(adapter); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3248,7 +3248,7 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3271,7 +3271,7 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + if (status) + goto err_unlock; + +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + + if (!wait_for_completion_timeout(&adapter->et_cmd_compl, + msecs_to_jiffies(SET_LB_MODE_TIMEOUT))) +@@ -3280,7 +3280,7 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + return status; + + err_unlock: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3297,7 +3297,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3323,7 +3323,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, + if (status) + goto err; + +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + + wait_for_completion(&adapter->et_cmd_compl); + resp = embedded_payload(wrb); +@@ -3331,7 +3331,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, + + return status; + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3347,7 +3347,7 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3381,7 +3381,7 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3392,7 +3392,7 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter, + struct be_cmd_req_seeprom_read *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3408,7 +3408,7 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter, + status = be_mcc_notify_wait(adapter); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3423,7 +3423,7 @@ int be_cmd_get_phy_info(struct be_adapter *adapter) + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3468,7 +3468,7 @@ int be_cmd_get_phy_info(struct be_adapter *adapter) + } + dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3478,7 +3478,7 @@ static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) + struct be_cmd_req_set_qos *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3498,7 +3498,7 @@ static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) + status = be_mcc_notify_wait(adapter); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3610,7 +3610,7 @@ int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, + struct be_cmd_req_get_fn_privileges *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3642,7 +3642,7 @@ int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3654,7 +3654,7 @@ int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, + struct be_cmd_req_set_fn_privileges *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3674,7 +3674,7 @@ int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3706,7 +3706,7 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, + return -ENOMEM; + } + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3770,7 +3770,7 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, + } + + out: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size, + get_mac_list_cmd.va, get_mac_list_cmd.dma); + return status; +@@ -3830,7 +3830,7 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, + if (!cmd.va) + return -ENOMEM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3852,7 +3852,7 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, + + err: + dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3888,7 +3888,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3929,7 +3929,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, + status = be_mcc_notify_wait(adapter); + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -3943,7 +3943,7 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, + int status; + u16 vid; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -3990,7 +3990,7 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -4189,7 +4189,7 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, + struct be_cmd_req_set_ext_fat_caps *req; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -4205,7 +4205,7 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -4683,7 +4683,7 @@ int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) + if (iface == 0xFFFFFFFF) + return -1; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -4700,7 +4700,7 @@ int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -4734,7 +4734,7 @@ int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, + struct be_cmd_resp_get_iface_list *resp; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -4755,7 +4755,7 @@ int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, + } + + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -4849,7 +4849,7 @@ int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) + if (BEx_chip(adapter)) + return 0; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -4867,7 +4867,7 @@ int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) + req->enable = 1; + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -4940,7 +4940,7 @@ __be_cmd_set_logical_link_config(struct be_adapter *adapter, + u32 link_config = 0; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -4968,7 +4968,7 @@ __be_cmd_set_logical_link_config(struct be_adapter *adapter, + + status = be_mcc_notify_wait(adapter); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -4999,8 +4999,7 @@ int be_cmd_set_features(struct be_adapter *adapter) + struct be_mcc_wrb *wrb; + int status; + +- if (mutex_lock_interruptible(&adapter->mcc_lock)) +- return -1; ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -5038,7 +5037,7 @@ int be_cmd_set_features(struct be_adapter *adapter) + dev_info(&adapter->pdev->dev, + "Adapter does not support HW error recovery\n"); + +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + +@@ -5052,7 +5051,7 @@ int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, + struct be_cmd_resp_hdr *resp; + int status; + +- mutex_lock(&adapter->mcc_lock); ++ spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { +@@ -5075,7 +5074,7 @@ int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, + memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length); + be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length); + err: +- mutex_unlock(&adapter->mcc_lock); ++ spin_unlock_bh(&adapter->mcc_lock); + return status; + } + EXPORT_SYMBOL(be_roce_mcc_cmd); +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index b0a85c9b952b9..173625a108861 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -5672,8 +5672,8 @@ static int be_drv_init(struct be_adapter *adapter) + } + + mutex_init(&adapter->mbox_lock); +- mutex_init(&adapter->mcc_lock); + mutex_init(&adapter->rx_filter_lock); ++ spin_lock_init(&adapter->mcc_lock); + spin_lock_init(&adapter->mcc_cq_lock); + init_completion(&adapter->et_cmd_compl); + +-- +2.39.5 + diff --git a/queue-6.1/bluetooth-btusb-initialize-.owner-field-of-force_pol.patch b/queue-6.1/bluetooth-btusb-initialize-.owner-field-of-force_pol.patch new file mode 100644 index 0000000000..5503241644 --- /dev/null +++ b/queue-6.1/bluetooth-btusb-initialize-.owner-field-of-force_pol.patch @@ -0,0 +1,35 @@ +From 18ebb1c05d7bb55985d22ac24e7e0d3b797a0617 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 22:32:59 +0100 +Subject: bluetooth: btusb: Initialize .owner field of force_poll_sync_fops + +From: Salah Triki + +[ Upstream commit cbf85b9cb80bec6345ffe0368dfff98386f4714f ] + +Initialize .owner field of force_poll_sync_fops to THIS_MODULE in order to +prevent btusb from being unloaded while its operations are in use. + +Fixes: 800fe5ec302e ("Bluetooth: btusb: Add support for queuing during polling interval") +Signed-off-by: Salah Triki +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 4c9747de0d6de..25adb3ac40eb8 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -3769,6 +3769,7 @@ static ssize_t force_poll_sync_write(struct file *file, + } + + static const struct file_operations force_poll_sync_fops = { ++ .owner = THIS_MODULE, + .open = simple_open, + .read = force_poll_sync_read, + .write = force_poll_sync_write, +-- +2.39.5 + diff --git a/queue-6.1/caif_virtio-fix-wrong-pointer-check-in-cfv_probe.patch b/queue-6.1/caif_virtio-fix-wrong-pointer-check-in-cfv_probe.patch new file mode 100644 index 0000000000..9df6da0905 --- /dev/null +++ b/queue-6.1/caif_virtio-fix-wrong-pointer-check-in-cfv_probe.patch @@ -0,0 +1,43 @@ +From dbc022a3d933d1ba57b14dc39446c5416a890921 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 23:46:27 +0500 +Subject: caif_virtio: fix wrong pointer check in cfv_probe() + +From: Vitaliy Shevtsov + +[ Upstream commit a466fd7e9fafd975949e5945e2f70c33a94b1a70 ] + +del_vqs() frees virtqueues, therefore cfv->vq_tx pointer should be checked +for NULL before calling it, not cfv->vdev. Also the current implementation +is redundant because the pointer cfv->vdev is dereferenced before it is +checked for NULL. + +Fix this by checking cfv->vq_tx for NULL instead of cfv->vdev before +calling del_vqs(). + +Fixes: 0d2e1a2926b1 ("caif_virtio: Introduce caif over virtio") +Signed-off-by: Vitaliy Shevtsov +Reviewed-by: Gerhard Engleder +Link: https://patch.msgid.link/20250227184716.4715-1-v.shevtsov@mt-integration.ru +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/caif/caif_virtio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c +index 0b0f234b0b508..a8b9ada7526c7 100644 +--- a/drivers/net/caif/caif_virtio.c ++++ b/drivers/net/caif/caif_virtio.c +@@ -745,7 +745,7 @@ static int cfv_probe(struct virtio_device *vdev) + + if (cfv->vr_rx) + vdev->vringh_config->del_vrhs(cfv->vdev); +- if (cfv->vdev) ++ if (cfv->vq_tx) + vdev->config->del_vqs(cfv->vdev); + free_netdev(netdev); + return err; +-- +2.39.5 + diff --git a/queue-6.1/drm-sched-fix-preprocessor-guard.patch b/queue-6.1/drm-sched-fix-preprocessor-guard.patch new file mode 100644 index 0000000000..371033f0c1 --- /dev/null +++ b/queue-6.1/drm-sched-fix-preprocessor-guard.patch @@ -0,0 +1,48 @@ +From bb2c7e38bae981cffaa94bb2e1ddd4eac5318373 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 13:41:50 +0100 +Subject: drm/sched: Fix preprocessor guard + +From: Philipp Stanner + +[ Upstream commit 23e0832d6d7be2d3c713f9390c060b6f1c48bf36 ] + +When writing the header guard for gpu_scheduler_trace.h, a typo, +apparently, occurred. + +Fix the typo and document the scope of the guard. + +Fixes: 353da3c520b4 ("drm/amdgpu: add tracepoint for scheduler (v2)") +Reviewed-by: Tvrtko Ursulin +Signed-off-by: Philipp Stanner +Link: https://patchwork.freedesktop.org/patch/msgid/20250218124149.118002-2-phasta@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/scheduler/gpu_scheduler_trace.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h b/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h +index 3143ecaaff862..f7f10e97ac055 100644 +--- a/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h ++++ b/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h +@@ -21,7 +21,7 @@ + * + */ + +-#if !defined(_GPU_SCHED_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) ++#if !defined(_GPU_SCHED_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) + #define _GPU_SCHED_TRACE_H_ + + #include +@@ -106,7 +106,7 @@ TRACE_EVENT(drm_sched_job_wait_dep, + __entry->seqno) + ); + +-#endif ++#endif /* _GPU_SCHED_TRACE_H_ */ + + /* This part must be outside protection */ + #undef TRACE_INCLUDE_PATH +-- +2.39.5 + diff --git a/queue-6.1/exfat-fix-soft-lockup-in-exfat_clear_bitmap.patch b/queue-6.1/exfat-fix-soft-lockup-in-exfat_clear_bitmap.patch new file mode 100644 index 0000000000..4880586166 --- /dev/null +++ b/queue-6.1/exfat-fix-soft-lockup-in-exfat_clear_bitmap.patch @@ -0,0 +1,129 @@ +From 20ba83c0a56b47627813109409008d82d072024d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 12:55:55 +0900 +Subject: exfat: fix soft lockup in exfat_clear_bitmap + +From: Namjae Jeon + +[ Upstream commit 9da33619e0ca53627641bc97d1b93ec741299111 ] + +bitmap clear loop will take long time in __exfat_free_cluster() +if data size of file/dir enty is invalid. +If cluster bit in bitmap is already clear, stop clearing bitmap go to +out of loop. + +Fixes: 31023864e67a ("exfat: add fat entry operations") +Reported-by: Kun Hu , Jiaji Qin +Reviewed-by: Sungjong Seo +Signed-off-by: Namjae Jeon +Signed-off-by: Sasha Levin +--- + fs/exfat/balloc.c | 10 ++++++++-- + fs/exfat/exfat_fs.h | 2 +- + fs/exfat/fatent.c | 11 +++++++---- + 3 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c +index 5b547a5963808..32209acd51be4 100644 +--- a/fs/exfat/balloc.c ++++ b/fs/exfat/balloc.c +@@ -160,7 +160,7 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync) + return 0; + } + +-void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) ++int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) + { + int i, b; + unsigned int ent_idx; +@@ -169,13 +169,17 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) + struct exfat_mount_options *opts = &sbi->options; + + if (!is_valid_cluster(sbi, clu)) +- return; ++ return -EIO; + + ent_idx = CLUSTER_TO_BITMAP_ENT(clu); + i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); + b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx); + ++ if (!test_bit_le(b, sbi->vol_amap[i]->b_data)) ++ return -EIO; ++ + clear_bit_le(b, sbi->vol_amap[i]->b_data); ++ + exfat_update_bh(sbi->vol_amap[i], sync); + + if (opts->discard) { +@@ -190,6 +194,8 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) + opts->discard = 0; + } + } ++ ++ return 0; + } + + /* +diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h +index c79c78bf265ba..5a1251207ab22 100644 +--- a/fs/exfat/exfat_fs.h ++++ b/fs/exfat/exfat_fs.h +@@ -419,7 +419,7 @@ int exfat_count_num_clusters(struct super_block *sb, + int exfat_load_bitmap(struct super_block *sb); + void exfat_free_bitmap(struct exfat_sb_info *sbi); + int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync); +-void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync); ++int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync); + unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu); + int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count); + int exfat_trim_fs(struct inode *inode, struct fstrim_range *range); +diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c +index fe007ae2f23c8..220ab671a8156 100644 +--- a/fs/exfat/fatent.c ++++ b/fs/exfat/fatent.c +@@ -175,6 +175,7 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain + BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu)); + + if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { ++ int err; + unsigned int last_cluster = p_chain->dir + p_chain->size - 1; + do { + bool sync = false; +@@ -189,7 +190,9 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain + cur_cmap_i = next_cmap_i; + } + +- exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); ++ err = exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); ++ if (err) ++ break; + clu++; + num_clusters++; + } while (num_clusters < p_chain->size); +@@ -210,12 +213,13 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain + cur_cmap_i = next_cmap_i; + } + +- exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); ++ if (exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)))) ++ break; + clu = n_clu; + num_clusters++; + + if (err) +- goto dec_used_clus; ++ break; + + if (num_clusters >= sbi->num_clusters - EXFAT_FIRST_CLUSTER) { + /* +@@ -229,7 +233,6 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain + } while (clu != EXFAT_EOF_CLUSTER); + } + +-dec_used_clus: + sbi->used_clusters -= num_clusters; + return 0; + } +-- +2.39.5 + diff --git a/queue-6.1/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch b/queue-6.1/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch new file mode 100644 index 0000000000..8316d13542 --- /dev/null +++ b/queue-6.1/fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch @@ -0,0 +1,63 @@ +From 6edd967c49cb625da20260c0598c07268495e6e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 07:33:58 -1000 +Subject: fs/pipe: do not open-code pipe head/tail logic in FIONREAD + +From: Linus Torvalds + +[ Upstream commit d810d4c27bf34c719243bab9feb0d843edc09fd7 ] + +Rasmus points out that we do indeed have other cases of breakage from +the type changes that were introduced on 32-bit targets in order to read +the pipe head and tail values atomically (commit 3d252160b818: "fs/pipe: +Read pipe->{head,tail} atomically outside pipe->mutex"). + +Fix it up by using the proper helper functions that now deal with the +pipe buffer index types properly. This makes the code simpler and more +obvious. + +The compiler does the CSE and loop hoisting of the pipe ring size +masking that we used to do manually, so open-coding this was never a +good idea. + +Reported-by: Rasmus Villemoes +Link: https://lore.kernel.org/all/87cyeu5zgk.fsf@prevas.dk/ +Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg Nesterov +Cc: Mateusz Guzik +Cc: K Prateek Nayak +Cc: Swapnil Sapkal +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/pipe.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/fs/pipe.c b/fs/pipe.c +index fd0c4fc4bd70f..658144268f552 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -610,7 +610,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) + static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { + struct pipe_inode_info *pipe = filp->private_data; +- unsigned int count, head, tail, mask; ++ unsigned int count, head, tail; + + switch (cmd) { + case FIONREAD: +@@ -618,10 +618,9 @@ static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + count = 0; + head = pipe->head; + tail = pipe->tail; +- mask = pipe->ring_size - 1; + +- while (tail != head) { +- count += pipe->bufs[tail & mask].len; ++ while (!pipe_empty(head, tail)) { ++ count += pipe_buf(pipe, tail)->len; + tail++; + } + __pipe_unlock(pipe); +-- +2.39.5 + diff --git a/queue-6.1/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch b/queue-6.1/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch new file mode 100644 index 0000000000..72ce532194 --- /dev/null +++ b/queue-6.1/fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch @@ -0,0 +1,78 @@ +From e8aa712c6c159d7d8973c71684b35381c5753dca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 07:53:25 -1000 +Subject: fs/pipe: fix pipe buffer index use in FUSE + +From: Linus Torvalds + +[ Upstream commit ebb0f38bb47f74b29e267babdbcd2c47d5292aa8 ] + +This was another case that Rasmus pointed out where the direct access to +the pipe head and tail pointers broke on 32-bit configurations due to +the type changes. + +As with the pipe FIONREAD case, fix it by using the appropriate helper +functions that deal with the right pipe index sizing. + +Reported-by: Rasmus Villemoes +Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/ +Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg > +Cc: Mateusz Guzik +Cc: K Prateek Nayak +Cc: Swapnil Sapkal +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/fuse/dev.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 7e0d4f08a0cf5..cb3fa178ff8c9 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1965,7 +1965,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + struct file *out, loff_t *ppos, + size_t len, unsigned int flags) + { +- unsigned int head, tail, mask, count; ++ unsigned int head, tail, count; + unsigned nbuf; + unsigned idx; + struct pipe_buffer *bufs; +@@ -1982,8 +1982,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + + head = pipe->head; + tail = pipe->tail; +- mask = pipe->ring_size - 1; +- count = head - tail; ++ count = pipe_occupancy(head, tail); + + bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL); + if (!bufs) { +@@ -1993,8 +1992,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + + nbuf = 0; + rem = 0; +- for (idx = tail; idx != head && rem < len; idx++) +- rem += pipe->bufs[idx & mask].len; ++ for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++) ++ rem += pipe_buf(pipe, idx)->len; + + ret = -EINVAL; + if (rem < len) +@@ -2005,10 +2004,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + struct pipe_buffer *ibuf; + struct pipe_buffer *obuf; + +- if (WARN_ON(nbuf >= count || tail == head)) ++ if (WARN_ON(nbuf >= count || pipe_empty(head, tail))) + goto out_free; + +- ibuf = &pipe->bufs[tail & mask]; ++ ibuf = pipe_buf(pipe, tail); + obuf = &bufs[nbuf]; + + if (rem >= ibuf->len) { +-- +2.39.5 + diff --git a/queue-6.1/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch b/queue-6.1/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch new file mode 100644 index 0000000000..1f3ffc0d19 --- /dev/null +++ b/queue-6.1/fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch @@ -0,0 +1,48 @@ +From 2b95e27376134413c4b8b93820c41239d328dc43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 07:08:09 -1000 +Subject: fs/pipe: Fix pipe_occupancy() with 16-bit indexes + +From: Linus Torvalds + +[ Upstream commit c27c66afc449b80f3b4b84d123358c0248f2cf63 ] + +The pipe_occupancy() logic implicitly relied on the natural unsigned +modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' +case, since any arithmetic will be done in 'int' (and here we had also +made it 'unsigned int' due to the function call boundary). + +So make the modulo arithmetic explicit by casting the result to the +proper type. + +Cc: Oleg Nesterov +Cc: Mateusz Guzik +Cc: Manfred Spraul +Cc: Christian Brauner +Cc: Swapnil Sapkal +Cc: Alexey Gladkov +Cc: K Prateek Nayak +Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ +Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + include/linux/pipe_fs_i.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h +index dfd056dfb994c..7f4ee79286d64 100644 +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) + */ + static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) + { +- return head - tail; ++ return (pipe_index_t)(head - tail); + } + + /** +-- +2.39.5 + diff --git a/queue-6.1/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch b/queue-6.1/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch new file mode 100644 index 0000000000..11dba016c2 --- /dev/null +++ b/queue-6.1/fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch @@ -0,0 +1,220 @@ +From 3c72aff3fa022e1353f317772908d05a5695fdc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 13:51:38 +0000 +Subject: fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex + +From: Linus Torvalds + +[ Upstream commit 3d252160b818045f3a152b13756f6f37ca34639d ] + +pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" +and "pipe->tail" outside of "pipe->mutex" critical section. When the +head and the tail are read individually in that order, there is a window +for interruption between the two reads in which both the head and the +tail can be updated by concurrent readers and writers. + +One of the problematic scenarios observed with hackbench running +multiple groups on a large server on a particular pipe inode is as +follows: + + pipe->head = 36 + pipe->tail = 36 + + hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* + hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] + hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* + hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* + + hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* + hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] + ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) + + hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* + hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] + hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* + hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* + + hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* + hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] + hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* + + hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* + hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] + hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* + hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* + + ... CPU 206 switches back to writer + hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] + hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes + hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* + + [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] + +The unsigned arithmetic in pipe_occupancy() wraps around when +"pipe->tail > pipe->head" leading to pipe_full() returning true despite +the pipe being empty. + +The case of genuine wraparound of "pipe->head" is handled since pipe +buffer has data allowing readers to make progress until the pipe->tail +wraps too after which the reader will wakeup a sleeping writer, however, +mistaking the pipe to be full when it is in fact empty can lead to +readers and writers waiting on each other indefinitely. + +This issue became more problematic and surfaced as a hang in hackbench +after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up +the writer if the pipe is still full") significantly reduced the number +of spurious wakeups of writers that had previously helped mask the +issue. + +To avoid missing any updates between the reads of "pipe->head" and +"pipe->write", unionize the two with a single unsigned long +"pipe->head_tail" member that can be loaded atomically. + +Using "pipe->head_tail" to read the head and the tail ensures the +lockless checks do not miss any updates to the head or the tail and +since those two are only updated under "pipe->mutex", it ensures that +the head is always ahead of, or equal to the tail resulting in correct +calculations. + + [ prateek: commit log, testing on x86 platforms. ] + +Reported-and-debugged-by: Swapnil Sapkal +Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ +Reported-by: Alexey Gladkov +Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ +Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") +Tested-by: Swapnil Sapkal +Reviewed-by: Oleg Nesterov +Tested-by: Alexey Gladkov +Signed-off-by: K Prateek Nayak +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/pipe.c | 19 ++++++++----------- + include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- + 2 files changed, 45 insertions(+), 13 deletions(-) + +diff --git a/fs/pipe.c b/fs/pipe.c +index aa8e6ffe1cb58..fd0c4fc4bd70f 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -220,11 +220,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { + /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ + static inline bool pipe_readable(const struct pipe_inode_info *pipe) + { +- unsigned int head = READ_ONCE(pipe->head); +- unsigned int tail = READ_ONCE(pipe->tail); ++ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; + unsigned int writers = READ_ONCE(pipe->writers); + +- return !pipe_empty(head, tail) || !writers; ++ return !pipe_empty(idx.head, idx.tail) || !writers; + } + + static ssize_t +@@ -404,11 +403,10 @@ static inline int is_packetized(struct file *file) + /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ + static inline bool pipe_writable(const struct pipe_inode_info *pipe) + { +- unsigned int head = READ_ONCE(pipe->head); +- unsigned int tail = READ_ONCE(pipe->tail); ++ union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; + unsigned int max_usage = READ_ONCE(pipe->max_usage); + +- return !pipe_full(head, tail, max_usage) || ++ return !pipe_full(idx.head, idx.tail, max_usage) || + !READ_ONCE(pipe->readers); + } + +@@ -655,7 +653,7 @@ pipe_poll(struct file *filp, poll_table *wait) + { + __poll_t mask; + struct pipe_inode_info *pipe = filp->private_data; +- unsigned int head, tail; ++ union pipe_index idx; + + /* Epoll has some historical nasty semantics, this enables them */ + WRITE_ONCE(pipe->poll_usage, true); +@@ -676,19 +674,18 @@ pipe_poll(struct file *filp, poll_table *wait) + * if something changes and you got it wrong, the poll + * table entry will wake you up and fix it. + */ +- head = READ_ONCE(pipe->head); +- tail = READ_ONCE(pipe->tail); ++ idx.head_tail = READ_ONCE(pipe->head_tail); + + mask = 0; + if (filp->f_mode & FMODE_READ) { +- if (!pipe_empty(head, tail)) ++ if (!pipe_empty(idx.head, idx.tail)) + mask |= EPOLLIN | EPOLLRDNORM; + if (!pipe->writers && filp->f_version != pipe->w_counter) + mask |= EPOLLHUP; + } + + if (filp->f_mode & FMODE_WRITE) { +- if (!pipe_full(head, tail, pipe->max_usage)) ++ if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) + mask |= EPOLLOUT | EPOLLWRNORM; + /* + * Most Unices do not set EPOLLERR for FIFOs but on Linux they +diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h +index 1f1e7ae953205..dfd056dfb994c 100644 +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -31,6 +31,33 @@ struct pipe_buffer { + unsigned long private; + }; + ++/* ++ * Really only alpha needs 32-bit fields, but ++ * might as well do it for 64-bit architectures ++ * since that's what we've historically done, ++ * and it makes 'head_tail' always be a simple ++ * 'unsigned long'. ++ */ ++#ifdef CONFIG_64BIT ++typedef unsigned int pipe_index_t; ++#else ++typedef unsigned short pipe_index_t; ++#endif ++ ++/* ++ * We have to declare this outside 'struct pipe_inode_info', ++ * but then we can't use 'union pipe_index' for an anonymous ++ * union, so we end up having to duplicate this declaration ++ * below. Annoying. ++ */ ++union pipe_index { ++ unsigned long head_tail; ++ struct { ++ pipe_index_t head; ++ pipe_index_t tail; ++ }; ++}; ++ + /** + * struct pipe_inode_info - a linux kernel pipe + * @mutex: mutex protecting the whole thing +@@ -58,8 +85,16 @@ struct pipe_buffer { + struct pipe_inode_info { + struct mutex mutex; + wait_queue_head_t rd_wait, wr_wait; +- unsigned int head; +- unsigned int tail; ++ ++ /* This has to match the 'union pipe_index' above */ ++ union { ++ unsigned long head_tail; ++ struct { ++ pipe_index_t head; ++ pipe_index_t tail; ++ }; ++ }; ++ + unsigned int max_usage; + unsigned int ring_size; + #ifdef CONFIG_WATCH_QUEUE +-- +2.39.5 + diff --git a/queue-6.1/gpio-rcar-fix-missing-of_node_put-call.patch b/queue-6.1/gpio-rcar-fix-missing-of_node_put-call.patch new file mode 100644 index 0000000000..0cee13d06f --- /dev/null +++ b/queue-6.1/gpio-rcar-fix-missing-of_node_put-call.patch @@ -0,0 +1,47 @@ +From 0c9b050101370833869296e736b4a936d305aed0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 16:37:50 +0000 +Subject: gpio: rcar: Fix missing of_node_put() call + +From: Fabrizio Castro + +[ Upstream commit 391b41f983bf7ff853de44704d8e14e7cc648a9b ] + +of_parse_phandle_with_fixed_args() requires its caller to +call into of_node_put() on the node pointer from the output +structure, but such a call is currently missing. + +Call into of_node_put() to rectify that. + +Fixes: 159f8a0209af ("gpio-rcar: Add DT support") +Signed-off-by: Fabrizio Castro +Reviewed-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20250305163753.34913-2-fabrizio.castro.jz@renesas.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-rcar.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c +index fd35e4611cc6d..ab200e6250108 100644 +--- a/drivers/gpio/gpio-rcar.c ++++ b/drivers/gpio/gpio-rcar.c +@@ -469,7 +469,12 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins) + p->info = *info; + + ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); +- *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; ++ if (ret) { ++ *npins = RCAR_MAX_GPIO_PER_BANK; ++ } else { ++ *npins = args.args[2]; ++ of_node_put(args.np); ++ } + + if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { + dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n", +-- +2.39.5 + diff --git a/queue-6.1/hid-google-fix-unused-variable-warning-under-config_.patch b/queue-6.1/hid-google-fix-unused-variable-warning-under-config_.patch new file mode 100644 index 0000000000..11c172f8f2 --- /dev/null +++ b/queue-6.1/hid-google-fix-unused-variable-warning-under-config_.patch @@ -0,0 +1,50 @@ +From ffd5f328b2ebba8278ae80440a62d00d74304000 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 00:50:13 +0800 +Subject: HID: google: fix unused variable warning under !CONFIG_ACPI + +From: Yu-Chun Lin + +[ Upstream commit 4bd0725c09f377ffaf22b834241f6c050742e4fc ] + +As reported by the kernel test robot, the following warning occurs: + +>> drivers/hid/hid-google-hammer.c:261:36: warning: 'cbas_ec_acpi_ids' defined but not used [-Wunused-const-variable=] + 261 | static const struct acpi_device_id cbas_ec_acpi_ids[] = { + | ^~~~~~~~~~~~~~~~ + +The 'cbas_ec_acpi_ids' array is only used when CONFIG_ACPI is enabled. +Wrapping its definition and 'MODULE_DEVICE_TABLE' in '#ifdef CONFIG_ACPI' +prevents a compiler warning when ACPI is disabled. + +Fixes: eb1aac4c8744f75 ("HID: google: add support tablet mode switch for Whiskers") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202501201141.jctFH5eB-lkp@intel.com/ +Signed-off-by: Yu-Chun Lin +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-google-hammer.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c +index c6bdb9c4ef3e0..d25291ed900d0 100644 +--- a/drivers/hid/hid-google-hammer.c ++++ b/drivers/hid/hid-google-hammer.c +@@ -269,11 +269,13 @@ static int cbas_ec_remove(struct platform_device *pdev) + return 0; + } + ++#ifdef CONFIG_ACPI + static const struct acpi_device_id cbas_ec_acpi_ids[] = { + { "GOOG000B", 0 }, + { } + }; + MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids); ++#endif + + #ifdef CONFIG_OF + static const struct of_device_id cbas_ec_of_match[] = { +-- +2.39.5 + diff --git a/queue-6.1/hid-intel-ish-hid-fix-use-after-free-issue-in-ishtp_.patch b/queue-6.1/hid-intel-ish-hid-fix-use-after-free-issue-in-ishtp_.patch new file mode 100644 index 0000000000..3e4b5a3ec6 --- /dev/null +++ b/queue-6.1/hid-intel-ish-hid-fix-use-after-free-issue-in-ishtp_.patch @@ -0,0 +1,55 @@ +From eb9d3fb72f9d15f2c0a00d137ee70c4711f934e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 14:37:30 +0800 +Subject: HID: intel-ish-hid: Fix use-after-free issue in ishtp_hid_remove() + +From: Zhang Lixu + +[ Upstream commit 07583a0010696a17fb0942e0b499a62785c5fc9f ] + +The system can experience a random crash a few minutes after the driver is +removed. This issue occurs due to improper handling of memory freeing in +the ishtp_hid_remove() function. + +The function currently frees the `driver_data` directly within the loop +that destroys the HID devices, which can lead to accessing freed memory. +Specifically, `hid_destroy_device()` uses `driver_data` when it calls +`hid_ishtp_set_feature()` to power off the sensor, so freeing +`driver_data` beforehand can result in accessing invalid memory. + +This patch resolves the issue by storing the `driver_data` in a temporary +variable before calling `hid_destroy_device()`, and then freeing the +`driver_data` after the device is destroyed. + +Fixes: 0b28cb4bcb17 ("HID: intel-ish-hid: ISH HID client driver") +Signed-off-by: Zhang Lixu +Acked-by: Srinivas Pandruvada +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/intel-ish-hid/ishtp-hid.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.c b/drivers/hid/intel-ish-hid/ishtp-hid.c +index 14c271d7d8a94..0377dac3fc9a0 100644 +--- a/drivers/hid/intel-ish-hid/ishtp-hid.c ++++ b/drivers/hid/intel-ish-hid/ishtp-hid.c +@@ -261,12 +261,14 @@ int ishtp_hid_probe(unsigned int cur_hid_dev, + */ + void ishtp_hid_remove(struct ishtp_cl_data *client_data) + { ++ void *data; + int i; + + for (i = 0; i < client_data->num_hid_devices; ++i) { + if (client_data->hid_sensor_hubs[i]) { +- kfree(client_data->hid_sensor_hubs[i]->driver_data); ++ data = client_data->hid_sensor_hubs[i]->driver_data; + hid_destroy_device(client_data->hid_sensor_hubs[i]); ++ kfree(data); + client_data->hid_sensor_hubs[i] = NULL; + } + } +-- +2.39.5 + diff --git a/queue-6.1/hwmon-ad7314-validate-leading-zero-bits-and-return-e.patch b/queue-6.1/hwmon-ad7314-validate-leading-zero-bits-and-return-e.patch new file mode 100644 index 0000000000..acfa8ee41b --- /dev/null +++ b/queue-6.1/hwmon-ad7314-validate-leading-zero-bits-and-return-e.patch @@ -0,0 +1,65 @@ +From d5268c19d74892b6744d18d315e2b92e3a7a33f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 09:19:04 +0000 +Subject: hwmon: (ad7314) Validate leading zero bits and return error + +From: Erik Schumacher + +[ Upstream commit e278d5e8aef4c0a1d9a9fa8b8910d713a89aa800 ] + +Leading zero bits are sent on the bus before the temperature value is +transmitted. If any of these bits are high, the connection might be +unstable or there could be no AD7314 / ADT730x (or compatible) at all. +Return -EIO in that case. + +Signed-off-by: Erik Schumacher +Fixes: 4f3a659581cab ("hwmon: AD7314 driver (ported from IIO)") +Link: https://lore.kernel.org/r/24a50c2981a318580aca8f50d23be7987b69ea00.camel@iris-sensing.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/ad7314.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c +index 7802bbf5f9587..59424103f6348 100644 +--- a/drivers/hwmon/ad7314.c ++++ b/drivers/hwmon/ad7314.c +@@ -22,11 +22,13 @@ + */ + #define AD7314_TEMP_MASK 0x7FE0 + #define AD7314_TEMP_SHIFT 5 ++#define AD7314_LEADING_ZEROS_MASK BIT(15) + + /* + * ADT7301 and ADT7302 temperature masks + */ + #define ADT7301_TEMP_MASK 0x3FFF ++#define ADT7301_LEADING_ZEROS_MASK (BIT(15) | BIT(14)) + + enum ad7314_variant { + adt7301, +@@ -65,12 +67,20 @@ static ssize_t ad7314_temperature_show(struct device *dev, + return ret; + switch (spi_get_device_id(chip->spi_dev)->driver_data) { + case ad7314: ++ if (ret & AD7314_LEADING_ZEROS_MASK) { ++ /* Invalid read-out, leading zero part is missing */ ++ return -EIO; ++ } + data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_SHIFT; + data = sign_extend32(data, 9); + + return sprintf(buf, "%d\n", 250 * data); + case adt7301: + case adt7302: ++ if (ret & ADT7301_LEADING_ZEROS_MASK) { ++ /* Invalid read-out, leading zero part is missing */ ++ return -EIO; ++ } + /* + * Documented as a 13 bit twos complement register + * with a sign bit - which is a 14 bit 2's complement +-- +2.39.5 + diff --git a/queue-6.1/hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch b/queue-6.1/hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch new file mode 100644 index 0000000000..923a41062c --- /dev/null +++ b/queue-6.1/hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch @@ -0,0 +1,37 @@ +From c944117e348a050803c8ad15607042d77f9748bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 07:57:33 -0500 +Subject: hwmon: fix a NULL vs IS_ERR_OR_NULL() check in xgene_hwmon_probe() + +From: Xinghuo Chen + +[ Upstream commit 10fce7ebe888fa8c97eee7e317a47e7603e5e78d ] + +The devm_memremap() function returns error pointers on error, +it doesn't return NULL. + +Fixes: c7cefce03e69 ("hwmon: (xgene) access mailbox as RAM") +Signed-off-by: Xinghuo Chen +Link: https://lore.kernel.org/r/tencent_9AD8E7683EC29CAC97496B44F3F865BA070A@qq.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/xgene-hwmon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c +index 78d9f52e2a719..207084d55044a 100644 +--- a/drivers/hwmon/xgene-hwmon.c ++++ b/drivers/hwmon/xgene-hwmon.c +@@ -712,7 +712,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev) + goto out; + } + +- if (!ctx->pcc_comm_addr) { ++ if (IS_ERR_OR_NULL(ctx->pcc_comm_addr)) { + dev_err(&pdev->dev, + "Failed to ioremap PCC comm region\n"); + rc = -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.1/hwmon-ntc_thermistor-fix-the-ncpxxxh103-sensor-table.patch b/queue-6.1/hwmon-ntc_thermistor-fix-the-ncpxxxh103-sensor-table.patch new file mode 100644 index 0000000000..905541b113 --- /dev/null +++ b/queue-6.1/hwmon-ntc_thermistor-fix-the-ncpxxxh103-sensor-table.patch @@ -0,0 +1,108 @@ +From fe02916220cafaaf0b9c1318301053dca4f995e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 13:57:53 +0100 +Subject: hwmon: (ntc_thermistor) Fix the ncpXXxh103 sensor table + +From: Maud Spierings + +[ Upstream commit 1c7932d5ae0f5c22fa52ac811b4c427bbca5aff5 ] + +I could not find a single table that has the values currently present in +the table, change it to the actual values that can be found in [1]/[2] +and [3] (page 15 column 2) + +[1]: https://www.murata.com/products/productdetail?partno=NCP15XH103F03RC +[2]: https://www.murata.com/products/productdata/8796836626462/NTHCG83.txt?1437969843000 +[3]: https://nl.mouser.com/datasheet/2/281/r44e-522712.pdf + +Fixes: 54ce3a0d8011 ("hwmon: (ntc_thermistor) Add support for ncpXXxh103") +Signed-off-by: Maud Spierings +Link: https://lore.kernel.org/r/20250227-ntc_thermistor_fixes-v1-3-70fa73200b52@gocontroll.com +Reviewed-by: Linus Walleij +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/ntc_thermistor.c | 66 +++++++++++++++++----------------- + 1 file changed, 33 insertions(+), 33 deletions(-) + +diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c +index 4efbacce5d0ca..6bb1900b021c2 100644 +--- a/drivers/hwmon/ntc_thermistor.c ++++ b/drivers/hwmon/ntc_thermistor.c +@@ -181,40 +181,40 @@ static const struct ntc_compensation ncpXXwf104[] = { + }; + + static const struct ntc_compensation ncpXXxh103[] = { +- { .temp_c = -40, .ohm = 247565 }, +- { .temp_c = -35, .ohm = 181742 }, +- { .temp_c = -30, .ohm = 135128 }, +- { .temp_c = -25, .ohm = 101678 }, +- { .temp_c = -20, .ohm = 77373 }, +- { .temp_c = -15, .ohm = 59504 }, +- { .temp_c = -10, .ohm = 46222 }, +- { .temp_c = -5, .ohm = 36244 }, +- { .temp_c = 0, .ohm = 28674 }, +- { .temp_c = 5, .ohm = 22878 }, +- { .temp_c = 10, .ohm = 18399 }, +- { .temp_c = 15, .ohm = 14910 }, +- { .temp_c = 20, .ohm = 12169 }, ++ { .temp_c = -40, .ohm = 195652 }, ++ { .temp_c = -35, .ohm = 148171 }, ++ { .temp_c = -30, .ohm = 113347 }, ++ { .temp_c = -25, .ohm = 87559 }, ++ { .temp_c = -20, .ohm = 68237 }, ++ { .temp_c = -15, .ohm = 53650 }, ++ { .temp_c = -10, .ohm = 42506 }, ++ { .temp_c = -5, .ohm = 33892 }, ++ { .temp_c = 0, .ohm = 27219 }, ++ { .temp_c = 5, .ohm = 22021 }, ++ { .temp_c = 10, .ohm = 17926 }, ++ { .temp_c = 15, .ohm = 14674 }, ++ { .temp_c = 20, .ohm = 12081 }, + { .temp_c = 25, .ohm = 10000 }, +- { .temp_c = 30, .ohm = 8271 }, +- { .temp_c = 35, .ohm = 6883 }, +- { .temp_c = 40, .ohm = 5762 }, +- { .temp_c = 45, .ohm = 4851 }, +- { .temp_c = 50, .ohm = 4105 }, +- { .temp_c = 55, .ohm = 3492 }, +- { .temp_c = 60, .ohm = 2985 }, +- { .temp_c = 65, .ohm = 2563 }, +- { .temp_c = 70, .ohm = 2211 }, +- { .temp_c = 75, .ohm = 1915 }, +- { .temp_c = 80, .ohm = 1666 }, +- { .temp_c = 85, .ohm = 1454 }, +- { .temp_c = 90, .ohm = 1275 }, +- { .temp_c = 95, .ohm = 1121 }, +- { .temp_c = 100, .ohm = 990 }, +- { .temp_c = 105, .ohm = 876 }, +- { .temp_c = 110, .ohm = 779 }, +- { .temp_c = 115, .ohm = 694 }, +- { .temp_c = 120, .ohm = 620 }, +- { .temp_c = 125, .ohm = 556 }, ++ { .temp_c = 30, .ohm = 8315 }, ++ { .temp_c = 35, .ohm = 6948 }, ++ { .temp_c = 40, .ohm = 5834 }, ++ { .temp_c = 45, .ohm = 4917 }, ++ { .temp_c = 50, .ohm = 4161 }, ++ { .temp_c = 55, .ohm = 3535 }, ++ { .temp_c = 60, .ohm = 3014 }, ++ { .temp_c = 65, .ohm = 2586 }, ++ { .temp_c = 70, .ohm = 2228 }, ++ { .temp_c = 75, .ohm = 1925 }, ++ { .temp_c = 80, .ohm = 1669 }, ++ { .temp_c = 85, .ohm = 1452 }, ++ { .temp_c = 90, .ohm = 1268 }, ++ { .temp_c = 95, .ohm = 1110 }, ++ { .temp_c = 100, .ohm = 974 }, ++ { .temp_c = 105, .ohm = 858 }, ++ { .temp_c = 110, .ohm = 758 }, ++ { .temp_c = 115, .ohm = 672 }, ++ { .temp_c = 120, .ohm = 596 }, ++ { .temp_c = 125, .ohm = 531 }, + }; + + /* +-- +2.39.5 + diff --git a/queue-6.1/hwmon-pmbus-initialise-page-count-in-pmbus_identify.patch b/queue-6.1/hwmon-pmbus-initialise-page-count-in-pmbus_identify.patch new file mode 100644 index 0000000000..8afbdb63d3 --- /dev/null +++ b/queue-6.1/hwmon-pmbus-initialise-page-count-in-pmbus_identify.patch @@ -0,0 +1,49 @@ +From 95a68a5ab9782a634146f73313b4c6bea50599ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 22:24:55 +0000 +Subject: hwmon: (pmbus) Initialise page count in pmbus_identify() + +From: Titus Rwantare + +[ Upstream commit 6b6e2e8fd0de3fa7c6f4f8fe6841b01770b2e7bc ] + +The `pmbus_identify()` function fails to correctly determine the number +of supported pages on PMBus devices. This occurs because `info->pages` +is implicitly zero-initialised, and `pmbus_set_page()` does not perform +writes to the page register if `info->pages` is not yet initialised. +Without this patch, `info->pages` is always set to the maximum after +scanning. + +This patch initialises `info->pages` to `PMBUS_PAGES` before the probing +loop, enabling `pmbus_set_page()` writes to make it out onto the bus +correctly identifying the number of pages. `PMBUS_PAGES` seemed like a +reasonable non-zero number because that's the current result of the +identification process. + +Testing was done with a PMBus device in QEMU. + +Signed-off-by: Titus Rwantare +Fixes: 442aba78728e7 ("hwmon: PMBus device driver") +Link: https://lore.kernel.org/r/20250227222455.2583468-1-titusr@google.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/pmbus/pmbus.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c +index d0d386990af5e..6366610a90827 100644 +--- a/drivers/hwmon/pmbus/pmbus.c ++++ b/drivers/hwmon/pmbus/pmbus.c +@@ -103,6 +103,8 @@ static int pmbus_identify(struct i2c_client *client, + if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + ++ info->pages = PMBUS_PAGES; ++ + for (page = 1; page < PMBUS_PAGES; page++) { + if (pmbus_set_page(client, page, 0xff) < 0) + break; +-- +2.39.5 + diff --git a/queue-6.1/llc-do-not-use-skb_get-before-dev_queue_xmit.patch b/queue-6.1/llc-do-not-use-skb_get-before-dev_queue_xmit.patch new file mode 100644 index 0000000000..fa25891963 --- /dev/null +++ b/queue-6.1/llc-do-not-use-skb_get-before-dev_queue_xmit.patch @@ -0,0 +1,166 @@ +From 95660cc4f92905f04b5ea50a272f3e8fc7ed21b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 08:26:42 +0000 +Subject: llc: do not use skb_get() before dev_queue_xmit() + +From: Eric Dumazet + +[ Upstream commit 64e6a754d33d31aa844b3ee66fb93ac84ca1565e ] + +syzbot is able to crash hosts [1], using llc and devices +not supporting IFF_TX_SKB_SHARING. + +In this case, e1000 driver calls eth_skb_pad(), while +the skb is shared. + +Simply replace skb_get() by skb_clone() in net/llc/llc_s_ac.c + +Note that e1000 driver might have an issue with pktgen, +because it does not clear IFF_TX_SKB_SHARING, this is an +orthogonal change. + +We need to audit other skb_get() uses in net/llc. + +[1] + +kernel BUG at net/core/skbuff.c:2178 ! +Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI +CPU: 0 UID: 0 PID: 16371 Comm: syz.2.2764 Not tainted 6.14.0-rc4-syzkaller-00052-gac9c34d1e45a #0 +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 + RIP: 0010:pskb_expand_head+0x6ce/0x1240 net/core/skbuff.c:2178 +Call Trace: + + __skb_pad+0x18a/0x610 net/core/skbuff.c:2466 + __skb_put_padto include/linux/skbuff.h:3843 [inline] + skb_put_padto include/linux/skbuff.h:3862 [inline] + eth_skb_pad include/linux/etherdevice.h:656 [inline] + e1000_xmit_frame+0x2d99/0x5800 drivers/net/ethernet/intel/e1000/e1000_main.c:3128 + __netdev_start_xmit include/linux/netdevice.h:5151 [inline] + netdev_start_xmit include/linux/netdevice.h:5160 [inline] + xmit_one net/core/dev.c:3806 [inline] + dev_hard_start_xmit+0x9a/0x7b0 net/core/dev.c:3822 + sch_direct_xmit+0x1ae/0xc30 net/sched/sch_generic.c:343 + __dev_xmit_skb net/core/dev.c:4045 [inline] + __dev_queue_xmit+0x13d4/0x43e0 net/core/dev.c:4621 + dev_queue_xmit include/linux/netdevice.h:3313 [inline] + llc_sap_action_send_test_c+0x268/0x320 net/llc/llc_s_ac.c:144 + llc_exec_sap_trans_actions net/llc/llc_sap.c:153 [inline] + llc_sap_next_state net/llc/llc_sap.c:182 [inline] + llc_sap_state_process+0x239/0x510 net/llc/llc_sap.c:209 + llc_ui_sendmsg+0xd0d/0x14e0 net/llc/af_llc.c:993 + sock_sendmsg_nosec net/socket.c:718 [inline] + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+da65c993ae113742a25f@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/67c020c0.050a0220.222324.0011.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/llc/llc_s_ac.c | 49 +++++++++++++++++++++++++--------------------- + 1 file changed, 27 insertions(+), 22 deletions(-) + +diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c +index 06fb8e6944b06..7a0cae9a81114 100644 +--- a/net/llc/llc_s_ac.c ++++ b/net/llc/llc_s_ac.c +@@ -24,7 +24,7 @@ + #include + #include + #include +- ++#include + + /** + * llc_sap_action_unitdata_ind - forward UI PDU to network layer +@@ -40,6 +40,26 @@ int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb) + return 0; + } + ++static int llc_prepare_and_xmit(struct sk_buff *skb) ++{ ++ struct llc_sap_state_ev *ev = llc_sap_ev(skb); ++ struct sk_buff *nskb; ++ int rc; ++ ++ rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); ++ if (rc) ++ return rc; ++ ++ nskb = skb_clone(skb, GFP_ATOMIC); ++ if (!nskb) ++ return -ENOMEM; ++ ++ if (skb->sk) ++ skb_set_owner_w(nskb, skb->sk); ++ ++ return dev_queue_xmit(nskb); ++} ++ + /** + * llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer + * @sap: SAP +@@ -52,17 +72,12 @@ int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb) + int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) + { + struct llc_sap_state_ev *ev = llc_sap_ev(skb); +- int rc; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap, + ev->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_ui_cmd(skb); +- rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); +- if (likely(!rc)) { +- skb_get(skb); +- rc = dev_queue_xmit(skb); +- } +- return rc; ++ ++ return llc_prepare_and_xmit(skb); + } + + /** +@@ -77,17 +92,12 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) + int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) + { + struct llc_sap_state_ev *ev = llc_sap_ev(skb); +- int rc; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_U_XID, ev->saddr.lsap, + ev->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); +- rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); +- if (likely(!rc)) { +- skb_get(skb); +- rc = dev_queue_xmit(skb); +- } +- return rc; ++ ++ return llc_prepare_and_xmit(skb); + } + + /** +@@ -133,17 +143,12 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) + int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) + { + struct llc_sap_state_ev *ev = llc_sap_ev(skb); +- int rc; + + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap, + ev->daddr.lsap, LLC_PDU_CMD); + llc_pdu_init_as_test_cmd(skb); +- rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); +- if (likely(!rc)) { +- skb_get(skb); +- rc = dev_queue_xmit(skb); +- } +- return rc; ++ ++ return llc_prepare_and_xmit(skb); + } + + int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) +-- +2.39.5 + diff --git a/queue-6.1/mm-pass-info-not-iter-into-filemap_get_pages.patch b/queue-6.1/mm-pass-info-not-iter-into-filemap_get_pages.patch new file mode 100644 index 0000000000..563f3adb5a --- /dev/null +++ b/queue-6.1/mm-pass-info-not-iter-into-filemap_get_pages.patch @@ -0,0 +1,126 @@ +From 9915cc269582726b40edced5c3024243c6118ced Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Feb 2023 18:18:17 +0000 +Subject: mm: Pass info, not iter, into filemap_get_pages() + +From: David Howells + +[ Upstream commit dd5b9d003ebcb469de05f967af7164e6b9450ca2 ] + +filemap_get_pages() and a number of functions that it calls take an +iterator to provide two things: the number of bytes to be got from the file +specified and whether partially uptodate pages are allowed. Change these +functions so that this information is passed in directly. This allows it +to be called without having an iterator to hand. + +Signed-off-by: David Howells +Reviewed-by: Christoph Hellwig +Reviewed-by: Jens Axboe +cc: Christoph Hellwig +cc: Matthew Wilcox +cc: Al Viro +cc: David Hildenbrand +cc: John Hubbard +cc: linux-mm@kvack.org +cc: linux-block@vger.kernel.org +cc: linux-fsdevel@vger.kernel.org +Signed-off-by: Steve French +Stable-dep-of: d810d4c27bf3 ("fs/pipe: do not open-code pipe head/tail logic in FIONREAD") +Signed-off-by: Sasha Levin +--- + mm/filemap.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/mm/filemap.c b/mm/filemap.c +index 78bf403473fb6..f57bc92e9b46f 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2503,21 +2503,19 @@ static int filemap_read_folio(struct file *file, filler_t filler, + } + + static bool filemap_range_uptodate(struct address_space *mapping, +- loff_t pos, struct iov_iter *iter, struct folio *folio) ++ loff_t pos, size_t count, struct folio *folio, ++ bool need_uptodate) + { +- int count; +- + if (folio_test_uptodate(folio)) + return true; + /* pipes can't handle partially uptodate pages */ +- if (iov_iter_is_pipe(iter)) ++ if (need_uptodate) + return false; + if (!mapping->a_ops->is_partially_uptodate) + return false; + if (mapping->host->i_blkbits >= folio_shift(folio)) + return false; + +- count = iter->count; + if (folio_pos(folio) > pos) { + count -= folio_pos(folio) - pos; + pos = 0; +@@ -2529,8 +2527,8 @@ static bool filemap_range_uptodate(struct address_space *mapping, + } + + static int filemap_update_page(struct kiocb *iocb, +- struct address_space *mapping, struct iov_iter *iter, +- struct folio *folio) ++ struct address_space *mapping, size_t count, ++ struct folio *folio, bool need_uptodate) + { + int error; + +@@ -2564,7 +2562,8 @@ static int filemap_update_page(struct kiocb *iocb, + goto unlock; + + error = 0; +- if (filemap_range_uptodate(mapping, iocb->ki_pos, iter, folio)) ++ if (filemap_range_uptodate(mapping, iocb->ki_pos, count, folio, ++ need_uptodate)) + goto unlock; + + error = -EAGAIN; +@@ -2640,8 +2639,8 @@ static int filemap_readahead(struct kiocb *iocb, struct file *file, + return 0; + } + +-static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter, +- struct folio_batch *fbatch) ++static int filemap_get_pages(struct kiocb *iocb, size_t count, ++ struct folio_batch *fbatch, bool need_uptodate) + { + struct file *filp = iocb->ki_filp; + struct address_space *mapping = filp->f_mapping; +@@ -2652,7 +2651,7 @@ static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter, + int err = 0; + + /* "last_index" is the index of the page beyond the end of the read */ +- last_index = DIV_ROUND_UP(iocb->ki_pos + iter->count, PAGE_SIZE); ++ last_index = DIV_ROUND_UP(iocb->ki_pos + count, PAGE_SIZE); + retry: + if (fatal_signal_pending(current)) + return -EINTR; +@@ -2685,7 +2684,8 @@ static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter, + if ((iocb->ki_flags & IOCB_WAITQ) && + folio_batch_count(fbatch) > 1) + iocb->ki_flags |= IOCB_NOWAIT; +- err = filemap_update_page(iocb, mapping, iter, folio); ++ err = filemap_update_page(iocb, mapping, count, folio, ++ need_uptodate); + if (err) + goto err; + } +@@ -2755,7 +2755,8 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, + if (unlikely(iocb->ki_pos >= i_size_read(inode))) + break; + +- error = filemap_get_pages(iocb, iter, &fbatch); ++ error = filemap_get_pages(iocb, iter->count, &fbatch, ++ iov_iter_is_pipe(iter)); + if (error < 0) + break; + +-- +2.39.5 + diff --git a/queue-6.1/net-gso-fix-ownership-in-__udp_gso_segment.patch b/queue-6.1/net-gso-fix-ownership-in-__udp_gso_segment.patch new file mode 100644 index 0000000000..84f160ec60 --- /dev/null +++ b/queue-6.1/net-gso-fix-ownership-in-__udp_gso_segment.patch @@ -0,0 +1,73 @@ +From 95345858bb2746f8f50a77bd3f9e3571b084cc71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 18:13:42 +0100 +Subject: net: gso: fix ownership in __udp_gso_segment + +From: Antoine Tenart + +[ Upstream commit ee01b2f2d7d0010787c2343463965bbc283a497f ] + +In __udp_gso_segment the skb destructor is removed before segmenting the +skb but the socket reference is kept as-is. This is an issue if the +original skb is later orphaned as we can hit the following bug: + + kernel BUG at ./include/linux/skbuff.h:3312! (skb_orphan) + RIP: 0010:ip_rcv_core+0x8b2/0xca0 + Call Trace: + ip_rcv+0xab/0x6e0 + __netif_receive_skb_one_core+0x168/0x1b0 + process_backlog+0x384/0x1100 + __napi_poll.constprop.0+0xa1/0x370 + net_rx_action+0x925/0xe50 + +The above can happen following a sequence of events when using +OpenVSwitch, when an OVS_ACTION_ATTR_USERSPACE action precedes an +OVS_ACTION_ATTR_OUTPUT action: + +1. OVS_ACTION_ATTR_USERSPACE is handled (in do_execute_actions): the skb + goes through queue_gso_packets and then __udp_gso_segment, where its + destructor is removed. +2. The segments' data are copied and sent to userspace. +3. OVS_ACTION_ATTR_OUTPUT is handled (in do_execute_actions) and the + same original skb is sent to its path. +4. If it later hits skb_orphan, we hit the bug. + +Fix this by also removing the reference to the socket in +__udp_gso_segment. + +Fixes: ad405857b174 ("udp: better wmem accounting on gso") +Signed-off-by: Antoine Tenart +Link: https://patch.msgid.link/20250226171352.258045-1-atenart@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/udp_offload.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index 1456c8c2b8dbd..2f1f038b0dc1b 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -314,13 +314,17 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, + + /* clear destructor to avoid skb_segment assigning it to tail */ + copy_dtor = gso_skb->destructor == sock_wfree; +- if (copy_dtor) ++ if (copy_dtor) { + gso_skb->destructor = NULL; ++ gso_skb->sk = NULL; ++ } + + segs = skb_segment(gso_skb, features); + if (IS_ERR_OR_NULL(segs)) { +- if (copy_dtor) ++ if (copy_dtor) { + gso_skb->destructor = sock_wfree; ++ gso_skb->sk = sk; ++ } + return segs; + } + +-- +2.39.5 + diff --git a/queue-6.1/net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch b/queue-6.1/net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch new file mode 100644 index 0000000000..8f9740f46e --- /dev/null +++ b/queue-6.1/net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch @@ -0,0 +1,42 @@ +From 64f5ca2bd02d7925ce43eaa677abce3dd771c76a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 18:52:58 +0800 +Subject: net: hns3: make sure ptp clock is unregister and freed if + hclge_ptp_get_cycle returns an error + +From: Peiyang Wang + +[ Upstream commit b7365eab39831487a84e63a9638209b68dc54008 ] + +During the initialization of ptp, hclge_ptp_get_cycle might return an error +and returned directly without unregister clock and free it. To avoid that, +call hclge_ptp_destroy_clock to unregist and free clock if +hclge_ptp_get_cycle failed. + +Fixes: 8373cd38a888 ("net: hns3: change the method of obtaining default ptp cycle") +Signed-off-by: Peiyang Wang +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250228105258.1243461-1-shaojijie@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +index 0f06f95b09bc2..4d4cea1f50157 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +@@ -496,7 +496,7 @@ int hclge_ptp_init(struct hclge_dev *hdev) + + ret = hclge_ptp_get_cycle(hdev); + if (ret) +- return ret; ++ goto out; + } + + ret = hclge_ptp_int_en(hdev, true); +-- +2.39.5 + diff --git a/queue-6.1/net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch b/queue-6.1/net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch new file mode 100644 index 0000000000..5a6b2234da --- /dev/null +++ b/queue-6.1/net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch @@ -0,0 +1,41 @@ +From 63420b61676092254097b3979ad03f0f70d281fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 19:10:39 +0100 +Subject: net: ipv6: fix dst ref loop in ila lwtunnel + +From: Justin Iurman + +[ Upstream commit 0e7633d7b95b67f1758aea19f8e85621c5f506a3 ] + +This patch follows commit 92191dd10730 ("net: ipv6: fix dst ref loops in +rpl, seg6 and ioam6 lwtunnels") and, on a second thought, the same patch +is also needed for ila (even though the config that triggered the issue +was pathological, but still, we don't want that to happen). + +Fixes: 79ff2fc31e0f ("ila: Cache a route to translated address") +Cc: Tom Herbert +Signed-off-by: Justin Iurman +Link: https://patch.msgid.link/20250304181039.35951-1-justin.iurman@uliege.be +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv6/ila/ila_lwt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c +index 9d37f7164e732..6d37dda3d26fc 100644 +--- a/net/ipv6/ila/ila_lwt.c ++++ b/net/ipv6/ila/ila_lwt.c +@@ -88,7 +88,8 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) + goto drop; + } + +- if (ilwt->connected) { ++ /* cache only if we don't create a dst reference loop */ ++ if (ilwt->connected && orig_dst->lwtstate != dst->lwtstate) { + local_bh_disable(); + dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr); + local_bh_enable(); +-- +2.39.5 + diff --git a/queue-6.1/net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch b/queue-6.1/net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch new file mode 100644 index 0000000000..fd0c64d190 --- /dev/null +++ b/queue-6.1/net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch @@ -0,0 +1,37 @@ +From eb47dbb11a97325c6327b31584584b7d433f69ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 09:16:55 +0100 +Subject: net: ipv6: fix missing dst ref drop in ila lwtunnel + +From: Justin Iurman + +[ Upstream commit 5da15a9c11c1c47ef573e6805b60a7d8a1687a2a ] + +Add missing skb_dst_drop() to drop reference to the old dst before +adding the new dst to the skb. + +Fixes: 79ff2fc31e0f ("ila: Cache a route to translated address") +Cc: Tom Herbert +Signed-off-by: Justin Iurman +Link: https://patch.msgid.link/20250305081655.19032-1-justin.iurman@uliege.be +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv6/ila/ila_lwt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c +index 6d37dda3d26fc..7397f764c66cc 100644 +--- a/net/ipv6/ila/ila_lwt.c ++++ b/net/ipv6/ila/ila_lwt.c +@@ -96,6 +96,7 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) + } + } + ++ skb_dst_drop(skb); + skb_dst_set(skb, dst); + return dst_output(net, sk, skb); + +-- +2.39.5 + diff --git a/queue-6.1/net-timestamp-support-tcp-gso-case-for-a-few-missing.patch b/queue-6.1/net-timestamp-support-tcp-gso-case-for-a-few-missing.patch new file mode 100644 index 0000000000..11182c3f06 --- /dev/null +++ b/queue-6.1/net-timestamp-support-tcp-gso-case-for-a-few-missing.patch @@ -0,0 +1,73 @@ +From dfb7e635f73a53335e053acffc46ba9d7c7de78b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 08:44:29 +0800 +Subject: net-timestamp: support TCP GSO case for a few missing flags + +From: Jason Xing + +[ Upstream commit 3c9231ea6497dfc50ac0ef69fff484da27d0df66 ] + +When I read through the TSO codes, I found out that we probably +miss initializing the tx_flags of last seg when TSO is turned +off, which means at the following points no more timestamp +(for this last one) will be generated. There are three flags +to be handled in this patch: +1. SKBTX_HW_TSTAMP +2. SKBTX_BPF +3. SKBTX_SCHED_TSTAMP +Note that SKBTX_BPF[1] was added in 6.14.0-rc2 by commit +6b98ec7e882af ("bpf: Add BPF_SOCK_OPS_TSTAMP_SCHED_CB callback") +and only belongs to net-next branch material for now. The common +issue of the above three flags can be fixed by this single patch. + +This patch initializes the tx_flags to SKBTX_ANY_TSTAMP like what +the UDP GSO does to make the newly segmented last skb inherit the +tx_flags so that requested timestamp will be generated in each +certain layer, or else that last one has zero value of tx_flags +which leads to no timestamp at all. + +Fixes: 4ed2d765dfacc ("net-timestamp: TCP timestamping") +Signed-off-by: Jason Xing +Reviewed-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_offload.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c +index 72a645bf05c92..ce84073e0b7bb 100644 +--- a/net/ipv4/tcp_offload.c ++++ b/net/ipv4/tcp_offload.c +@@ -12,12 +12,15 @@ + #include + #include + +-static void tcp_gso_tstamp(struct sk_buff *skb, unsigned int ts_seq, ++static void tcp_gso_tstamp(struct sk_buff *skb, struct sk_buff *gso_skb, + unsigned int seq, unsigned int mss) + { ++ u32 flags = skb_shinfo(gso_skb)->tx_flags & SKBTX_ANY_TSTAMP; ++ u32 ts_seq = skb_shinfo(gso_skb)->tskey; ++ + while (skb) { + if (before(ts_seq, seq + mss)) { +- skb_shinfo(skb)->tx_flags |= SKBTX_SW_TSTAMP; ++ skb_shinfo(skb)->tx_flags |= flags; + skb_shinfo(skb)->tskey = ts_seq; + return; + } +@@ -119,8 +122,8 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, + th = tcp_hdr(skb); + seq = ntohl(th->seq); + +- if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_SW_TSTAMP)) +- tcp_gso_tstamp(segs, skb_shinfo(gso_skb)->tskey, seq, mss); ++ if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_ANY_TSTAMP)) ++ tcp_gso_tstamp(segs, gso_skb, seq, mss); + + newcheck = ~csum_fold(csum_add(csum_unfold(th->check), delta)); + +-- +2.39.5 + diff --git a/queue-6.1/nvmet-tcp-fix-a-possible-sporadic-response-drops-in-.patch b/queue-6.1/nvmet-tcp-fix-a-possible-sporadic-response-drops-in-.patch new file mode 100644 index 0000000000..09e6687603 --- /dev/null +++ b/queue-6.1/nvmet-tcp-fix-a-possible-sporadic-response-drops-in-.patch @@ -0,0 +1,71 @@ +From 0085697b42a2e7d6ca9650f163458772800379a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 09:28:12 +0200 +Subject: nvmet-tcp: Fix a possible sporadic response drops in weakly ordered + arch + +From: Meir Elisha + +[ Upstream commit a16f88964c647103dad7743a484b216d488a6352 ] + +The order in which queue->cmd and rcv_state are updated is crucial. +If these assignments are reordered by the compiler, the worker might not +get queued in nvmet_tcp_queue_response(), hanging the IO. to enforce the +the correct reordering, set rcv_state using smp_store_release(). + +Fixes: bdaf13279192 ("nvmet-tcp: fix a segmentation fault during io parsing error") + +Signed-off-by: Meir Elisha +Reviewed-by: Sagi Grimberg +Signed-off-by: Keith Busch +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/tcp.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index 81574500a57c7..125e22bd34e2a 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -520,10 +520,16 @@ static void nvmet_tcp_queue_response(struct nvmet_req *req) + struct nvmet_tcp_cmd *cmd = + container_of(req, struct nvmet_tcp_cmd, req); + struct nvmet_tcp_queue *queue = cmd->queue; ++ enum nvmet_tcp_recv_state queue_state; ++ struct nvmet_tcp_cmd *queue_cmd; + struct nvme_sgl_desc *sgl; + u32 len; + +- if (unlikely(cmd == queue->cmd)) { ++ /* Pairs with store_release in nvmet_prepare_receive_pdu() */ ++ queue_state = smp_load_acquire(&queue->rcv_state); ++ queue_cmd = READ_ONCE(queue->cmd); ++ ++ if (unlikely(cmd == queue_cmd)) { + sgl = &cmd->req.cmd->common.dptr.sgl; + len = le32_to_cpu(sgl->length); + +@@ -532,7 +538,7 @@ static void nvmet_tcp_queue_response(struct nvmet_req *req) + * Avoid using helpers, this might happen before + * nvmet_req_init is completed. + */ +- if (queue->rcv_state == NVMET_TCP_RECV_PDU && ++ if (queue_state == NVMET_TCP_RECV_PDU && + len && len <= cmd->req.port->inline_data_size && + nvme_is_write(cmd->req.cmd)) + return; +@@ -784,8 +790,9 @@ static void nvmet_prepare_receive_pdu(struct nvmet_tcp_queue *queue) + { + queue->offset = 0; + queue->left = sizeof(struct nvme_tcp_hdr); +- queue->cmd = NULL; +- queue->rcv_state = NVMET_TCP_RECV_PDU; ++ WRITE_ONCE(queue->cmd, NULL); ++ /* Ensure rcv_state is visible only after queue->cmd is set */ ++ smp_store_release(&queue->rcv_state, NVMET_TCP_RECV_PDU); + } + + static void nvmet_tcp_free_crypto(struct nvmet_tcp_queue *queue) +-- +2.39.5 + diff --git a/queue-6.1/ppp-fix-kmsan-uninit-value-warning-with-bpf.patch b/queue-6.1/ppp-fix-kmsan-uninit-value-warning-with-bpf.patch new file mode 100644 index 0000000000..4c00c40f18 --- /dev/null +++ b/queue-6.1/ppp-fix-kmsan-uninit-value-warning-with-bpf.patch @@ -0,0 +1,121 @@ +From 48e3135ac20d5ca74a1cbb21b3e70fcc0a100f65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 22:14:08 +0800 +Subject: ppp: Fix KMSAN uninit-value warning with bpf + +From: Jiayuan Chen + +[ Upstream commit 4c2d14c40a68678d885eab4008a0129646805bae ] + +Syzbot caught an "KMSAN: uninit-value" warning [1], which is caused by the +ppp driver not initializing a 2-byte header when using socket filter. + +The following code can generate a PPP filter BPF program: +''' +struct bpf_program fp; +pcap_t *handle; +handle = pcap_open_dead(DLT_PPP_PPPD, 65535); +pcap_compile(handle, &fp, "ip and outbound", 0, 0); +bpf_dump(&fp, 1); +''' +Its output is: +''' +(000) ldh [2] +(001) jeq #0x21 jt 2 jf 5 +(002) ldb [0] +(003) jeq #0x1 jt 4 jf 5 +(004) ret #65535 +(005) ret #0 +''' +Wen can find similar code at the following link: +https://github.com/ppp-project/ppp/blob/master/pppd/options.c#L1680 +The maintainer of this code repository is also the original maintainer +of the ppp driver. + +As you can see the BPF program skips 2 bytes of data and then reads the +'Protocol' field to determine if it's an IP packet. Then it read the first +byte of the first 2 bytes to determine the direction. + +The issue is that only the first byte indicating direction is initialized +in current ppp driver code while the second byte is not initialized. + +For normal BPF programs generated by libpcap, uninitialized data won't be +used, so it's not a problem. However, for carefully crafted BPF programs, +such as those generated by syzkaller [2], which start reading from offset +0, the uninitialized data will be used and caught by KMSAN. + +[1] https://syzkaller.appspot.com/bug?extid=853242d9c9917165d791 +[2] https://syzkaller.appspot.com/text?tag=ReproC&x=11994913980000 + +Cc: Paul Mackerras +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+853242d9c9917165d791@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/bpf/000000000000dea025060d6bc3bc@google.com/ +Signed-off-by: Jiayuan Chen +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250228141408.393864-1-jiayuan.chen@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index de14e89619c5e..67d9efb054434 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -72,6 +72,17 @@ + #define PPP_PROTO_LEN 2 + #define PPP_LCP_HDRLEN 4 + ++/* The filter instructions generated by libpcap are constructed ++ * assuming a four-byte PPP header on each packet, where the last ++ * 2 bytes are the protocol field defined in the RFC and the first ++ * byte of the first 2 bytes indicates the direction. ++ * The second byte is currently unused, but we still need to initialize ++ * it to prevent crafted BPF programs from reading them which would ++ * cause reading of uninitialized data. ++ */ ++#define PPP_FILTER_OUTBOUND_TAG 0x0100 ++#define PPP_FILTER_INBOUND_TAG 0x0000 ++ + /* + * An instance of /dev/ppp can be associated with either a ppp + * interface unit or a ppp channel. In both cases, file->private_data +@@ -1762,10 +1773,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + + if (proto < 0x8000) { + #ifdef CONFIG_PPP_FILTER +- /* check if we should pass this packet */ +- /* the filter instructions are constructed assuming +- a four-byte PPP header on each packet */ +- *(u8 *)skb_push(skb, 2) = 1; ++ /* check if the packet passes the pass and active filters. ++ * See comment for PPP_FILTER_OUTBOUND_TAG above. ++ */ ++ *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { + if (ppp->debug & 1) +@@ -2482,14 +2493,13 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + /* network protocol frame - give it to the kernel */ + + #ifdef CONFIG_PPP_FILTER +- /* check if the packet passes the pass and active filters */ +- /* the filter instructions are constructed assuming +- a four-byte PPP header on each packet */ + if (ppp->pass_filter || ppp->active_filter) { + if (skb_unclone(skb, GFP_ATOMIC)) + goto err; +- +- *(u8 *)skb_push(skb, 2) = 0; ++ /* Check if the packet passes the pass and active filters. ++ * See comment for PPP_FILTER_INBOUND_TAG above. ++ */ ++ *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { + if (ppp->debug & 1) +-- +2.39.5 + diff --git a/queue-6.1/sched-fair-fix-potential-memory-corruption-in-child_.patch b/queue-6.1/sched-fair-fix-potential-memory-corruption-in-child_.patch new file mode 100644 index 0000000000..b1a3b92ef5 --- /dev/null +++ b/queue-6.1/sched-fair-fix-potential-memory-corruption-in-child_.patch @@ -0,0 +1,70 @@ +From 237df032fdd52377c1daa36f548a31ce67b55014 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 21:40:31 +0000 +Subject: sched/fair: Fix potential memory corruption in child_cfs_rq_on_list + +From: Zecheng Li + +[ Upstream commit 3b4035ddbfc8e4521f85569998a7569668cccf51 ] + +child_cfs_rq_on_list attempts to convert a 'prev' pointer to a cfs_rq. +This 'prev' pointer can originate from struct rq's leaf_cfs_rq_list, +making the conversion invalid and potentially leading to memory +corruption. Depending on the relative positions of leaf_cfs_rq_list and +the task group (tg) pointer within the struct, this can cause a memory +fault or access garbage data. + +The issue arises in list_add_leaf_cfs_rq, where both +cfs_rq->leaf_cfs_rq_list and rq->leaf_cfs_rq_list are added to the same +leaf list. Also, rq->tmp_alone_branch can be set to rq->leaf_cfs_rq_list. + +This adds a check `if (prev == &rq->leaf_cfs_rq_list)` after the main +conditional in child_cfs_rq_on_list. This ensures that the container_of +operation will convert a correct cfs_rq struct. + +This check is sufficient because only cfs_rqs on the same CPU are added +to the list, so verifying the 'prev' pointer against the current rq's list +head is enough. + +Fixes a potential memory corruption issue that due to current struct +layout might not be manifesting as a crash but could lead to unpredictable +behavior when the layout changes. + +Fixes: fdaba61ef8a2 ("sched/fair: Ensure that the CFS parent is added after unthrottling") +Signed-off-by: Zecheng Li +Reviewed-and-tested-by: K Prateek Nayak +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Vincent Guittot +Link: https://lore.kernel.org/r/20250304214031.2882646-1-zecheng@google.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index eedbe66e05273..d30e0936cfecc 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -3550,15 +3550,17 @@ static inline bool child_cfs_rq_on_list(struct cfs_rq *cfs_rq) + { + struct cfs_rq *prev_cfs_rq; + struct list_head *prev; ++ struct rq *rq = rq_of(cfs_rq); + + if (cfs_rq->on_list) { + prev = cfs_rq->leaf_cfs_rq_list.prev; + } else { +- struct rq *rq = rq_of(cfs_rq); +- + prev = rq->tmp_alone_branch; + } + ++ if (prev == &rq->leaf_cfs_rq_list) ++ return false; ++ + prev_cfs_rq = container_of(prev, struct cfs_rq, leaf_cfs_rq_list); + + return (prev_cfs_rq->tg->parent == cfs_rq->tg); +-- +2.39.5 + diff --git a/queue-6.1/series b/queue-6.1/series index bb7b9d57b6..bc7d0eeec0 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -34,3 +34,35 @@ s390-traps-fix-test_monitor_call-inline-assembly.patch block-fix-conversion-of-gpt-partition-name-to-7-bit.patch mm-page_alloc-fix-uninitialized-variable.patch mm-don-t-skip-arch_sync_kernel_mappings-in-error-paths.patch +wifi-iwlwifi-limit-printed-string-from-fw-file.patch +hid-google-fix-unused-variable-warning-under-config_.patch +hid-intel-ish-hid-fix-use-after-free-issue-in-ishtp_.patch +bluetooth-btusb-initialize-.owner-field-of-force_pol.patch +nvmet-tcp-fix-a-possible-sporadic-response-drops-in-.patch +net-gso-fix-ownership-in-__udp_gso_segment.patch +caif_virtio-fix-wrong-pointer-check-in-cfv_probe.patch +hwmon-pmbus-initialise-page-count-in-pmbus_identify.patch +hwmon-ntc_thermistor-fix-the-ncpxxxh103-sensor-table.patch +hwmon-ad7314-validate-leading-zero-bits-and-return-e.patch +alsa-usx2y-validate-nrpacks-module-parameter-on-prob.patch +llc-do-not-use-skb_get-before-dev_queue_xmit.patch +hwmon-fix-a-null-vs-is_err_or_null-check-in-xgene_hw.patch +drm-sched-fix-preprocessor-guard.patch +be2net-fix-sleeping-while-atomic-bugs-in-be_ndo_brid.patch +net-hns3-make-sure-ptp-clock-is-unregister-and-freed.patch +fs-pipe-read-pipe-head-tail-atomically-outside-pipe-.patch +ppp-fix-kmsan-uninit-value-warning-with-bpf.patch +vlan-enforce-underlying-device-type.patch +x86-sgx-fix-size-overflows-in-sgx_encl_create.patch +exfat-fix-soft-lockup-in-exfat_clear_bitmap.patch +net-timestamp-support-tcp-gso-case-for-a-few-missing.patch +ublk-set_params-properly-check-if-parameters-can-be-.patch +sched-fair-fix-potential-memory-corruption-in-child_.patch +fs-pipe-fix-pipe_occupancy-with-16-bit-indexes.patch +net-ipv6-fix-dst-ref-loop-in-ila-lwtunnel.patch +net-ipv6-fix-missing-dst-ref-drop-in-ila-lwtunnel.patch +gpio-rcar-fix-missing-of_node_put-call.patch +mm-pass-info-not-iter-into-filemap_get_pages.patch +splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch +fs-pipe-do-not-open-code-pipe-head-tail-logic-in-fio.patch +fs-pipe-fix-pipe-buffer-index-use-in-fuse.patch diff --git a/queue-6.1/splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch b/queue-6.1/splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch new file mode 100644 index 0000000000..3cc168b84f --- /dev/null +++ b/queue-6.1/splice-add-a-func-to-do-a-splice-from-a-buffered-fil.patch @@ -0,0 +1,270 @@ +From 3a1796e9eecebb93a9e2b6cb7112a480f36ed913 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Feb 2023 15:01:42 +0000 +Subject: splice: Add a func to do a splice from a buffered file without + ITER_PIPE + +From: David Howells + +[ Upstream commit 07073eb01c5f630344bc1c3e56b0e0d94aedf919 ] + +Provide a function to do splice read from a buffered file, pulling the +folios out of the pagecache directly by calling filemap_get_pages() to do +any required reading and then pasting the returned folios into the pipe. + +A helper function is provided to do the actual folio pasting and will +handle multipage folios by splicing as many of the relevant subpages as +will fit into the pipe. + +The code is loosely based on filemap_read() and might belong in +mm/filemap.c with that as it needs to use filemap_get_pages(). + +Signed-off-by: David Howells +Reviewed-by: Jens Axboe +cc: Christoph Hellwig +cc: Al Viro +cc: David Hildenbrand +cc: John Hubbard +cc: linux-mm@kvack.org +cc: linux-block@vger.kernel.org +cc: linux-fsdevel@vger.kernel.org +Signed-off-by: Steve French +Stable-dep-of: d810d4c27bf3 ("fs/pipe: do not open-code pipe head/tail logic in FIONREAD") +Signed-off-by: Sasha Levin +--- + include/linux/fs.h | 3 + + include/linux/pipe_fs_i.h | 20 ++++++ + lib/iov_iter.c | 6 -- + mm/filemap.c | 129 ++++++++++++++++++++++++++++++++++++++ + mm/internal.h | 6 ++ + 5 files changed, 158 insertions(+), 6 deletions(-) + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 0d32634c5cf0d..ef117325b2552 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3289,6 +3289,9 @@ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb, + struct iov_iter *iter); + + /* fs/splice.c */ ++ssize_t filemap_splice_read(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, ++ size_t len, unsigned int flags); + extern ssize_t generic_file_splice_read(struct file *, loff_t *, + struct pipe_inode_info *, size_t, unsigned int); + extern ssize_t iter_file_splice_write(struct pipe_inode_info *, +diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h +index 7f4ee79286d64..bfa381f175907 100644 +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -207,6 +207,26 @@ static inline bool pipe_full(unsigned int head, unsigned int tail, + return pipe_occupancy(head, tail) >= limit; + } + ++/** ++ * pipe_buf - Return the pipe buffer for the specified slot in the pipe ring ++ * @pipe: The pipe to access ++ * @slot: The slot of interest ++ */ ++static inline struct pipe_buffer *pipe_buf(const struct pipe_inode_info *pipe, ++ unsigned int slot) ++{ ++ return &pipe->bufs[slot & (pipe->ring_size - 1)]; ++} ++ ++/** ++ * pipe_head_buf - Return the pipe buffer at the head of the pipe ring ++ * @pipe: The pipe to access ++ */ ++static inline struct pipe_buffer *pipe_head_buf(const struct pipe_inode_info *pipe) ++{ ++ return pipe_buf(pipe, pipe->head); ++} ++ + /** + * pipe_buf_get - get a reference to a pipe_buffer + * @pipe: the pipe that the buffer belongs to +diff --git a/lib/iov_iter.c b/lib/iov_iter.c +index c3ca28ca68a65..d2d5e41082fe8 100644 +--- a/lib/iov_iter.c ++++ b/lib/iov_iter.c +@@ -186,12 +186,6 @@ static int copyin(void *to, const void __user *from, size_t n) + return res; + } + +-static inline struct pipe_buffer *pipe_buf(const struct pipe_inode_info *pipe, +- unsigned int slot) +-{ +- return &pipe->bufs[slot & (pipe->ring_size - 1)]; +-} +- + #ifdef PIPE_PARANOIA + static bool sanity(const struct iov_iter *i) + { +diff --git a/mm/filemap.c b/mm/filemap.c +index f57bc92e9b46f..ce5e1e443b1c9 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -42,6 +42,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include "internal.h" +@@ -2915,6 +2917,133 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) + } + EXPORT_SYMBOL(generic_file_read_iter); + ++/* ++ * Splice subpages from a folio into a pipe. ++ */ ++size_t splice_folio_into_pipe(struct pipe_inode_info *pipe, ++ struct folio *folio, loff_t fpos, size_t size) ++{ ++ struct page *page; ++ size_t spliced = 0, offset = offset_in_folio(folio, fpos); ++ ++ page = folio_page(folio, offset / PAGE_SIZE); ++ size = min(size, folio_size(folio) - offset); ++ offset %= PAGE_SIZE; ++ ++ while (spliced < size && ++ !pipe_full(pipe->head, pipe->tail, pipe->max_usage)) { ++ struct pipe_buffer *buf = pipe_head_buf(pipe); ++ size_t part = min_t(size_t, PAGE_SIZE - offset, size - spliced); ++ ++ *buf = (struct pipe_buffer) { ++ .ops = &page_cache_pipe_buf_ops, ++ .page = page, ++ .offset = offset, ++ .len = part, ++ }; ++ folio_get(folio); ++ pipe->head++; ++ page++; ++ spliced += part; ++ offset = 0; ++ } ++ ++ return spliced; ++} ++ ++/* ++ * Splice folios from the pagecache of a buffered (ie. non-O_DIRECT) file into ++ * a pipe. ++ */ ++ssize_t filemap_splice_read(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, ++ size_t len, unsigned int flags) ++{ ++ struct folio_batch fbatch; ++ struct kiocb iocb; ++ size_t total_spliced = 0, used, npages; ++ loff_t isize, end_offset; ++ bool writably_mapped; ++ int i, error = 0; ++ ++ init_sync_kiocb(&iocb, in); ++ iocb.ki_pos = *ppos; ++ ++ /* Work out how much data we can actually add into the pipe */ ++ used = pipe_occupancy(pipe->head, pipe->tail); ++ npages = max_t(ssize_t, pipe->max_usage - used, 0); ++ len = min_t(size_t, len, npages * PAGE_SIZE); ++ ++ folio_batch_init(&fbatch); ++ ++ do { ++ cond_resched(); ++ ++ if (*ppos >= i_size_read(file_inode(in))) ++ break; ++ ++ iocb.ki_pos = *ppos; ++ error = filemap_get_pages(&iocb, len, &fbatch, true); ++ if (error < 0) ++ break; ++ ++ /* ++ * i_size must be checked after we know the pages are Uptodate. ++ * ++ * Checking i_size after the check allows us to calculate ++ * the correct value for "nr", which means the zero-filled ++ * part of the page is not copied back to userspace (unless ++ * another truncate extends the file - this is desired though). ++ */ ++ isize = i_size_read(file_inode(in)); ++ if (unlikely(*ppos >= isize)) ++ break; ++ end_offset = min_t(loff_t, isize, *ppos + len); ++ ++ /* ++ * Once we start copying data, we don't want to be touching any ++ * cachelines that might be contended: ++ */ ++ writably_mapped = mapping_writably_mapped(in->f_mapping); ++ ++ for (i = 0; i < folio_batch_count(&fbatch); i++) { ++ struct folio *folio = fbatch.folios[i]; ++ size_t n; ++ ++ if (folio_pos(folio) >= end_offset) ++ goto out; ++ folio_mark_accessed(folio); ++ ++ /* ++ * If users can be writing to this folio using arbitrary ++ * virtual addresses, take care of potential aliasing ++ * before reading the folio on the kernel side. ++ */ ++ if (writably_mapped) ++ flush_dcache_folio(folio); ++ ++ n = min_t(loff_t, len, isize - *ppos); ++ n = splice_folio_into_pipe(pipe, folio, *ppos, n); ++ if (!n) ++ goto out; ++ len -= n; ++ total_spliced += n; ++ *ppos += n; ++ in->f_ra.prev_pos = *ppos; ++ if (pipe_full(pipe->head, pipe->tail, pipe->max_usage)) ++ goto out; ++ } ++ ++ folio_batch_release(&fbatch); ++ } while (len); ++ ++out: ++ folio_batch_release(&fbatch); ++ file_accessed(in); ++ ++ return total_spliced ? total_spliced : error; ++} ++ + static inline loff_t folio_seek_hole_data(struct xa_state *xas, + struct address_space *mapping, struct folio *folio, + loff_t start, loff_t end, bool seek_data) +diff --git a/mm/internal.h b/mm/internal.h +index 16a4a9aece304..5e3f3749527f6 100644 +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -841,6 +841,12 @@ struct migration_target_control { + gfp_t gfp_mask; + }; + ++/* ++ * mm/filemap.c ++ */ ++size_t splice_folio_into_pipe(struct pipe_inode_info *pipe, ++ struct folio *folio, loff_t fpos, size_t size); ++ + /* + * mm/vmalloc.c + */ +-- +2.39.5 + diff --git a/queue-6.1/ublk-set_params-properly-check-if-parameters-can-be-.patch b/queue-6.1/ublk-set_params-properly-check-if-parameters-can-be-.patch new file mode 100644 index 0000000000..87a82eff46 --- /dev/null +++ b/queue-6.1/ublk-set_params-properly-check-if-parameters-can-be-.patch @@ -0,0 +1,54 @@ +From 1863c61cd98b881a86e3ea34a44bc671c88e09ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 14:34:26 -0700 +Subject: ublk: set_params: properly check if parameters can be applied + +From: Uday Shankar + +[ Upstream commit 5ac60242b0173be83709603ebaf27a473f16c4e4 ] + +The parameters set by the set_params call are only applied to the block +device in the start_dev call. So if a device has already been started, a +subsequently issued set_params on that device will not have the desired +effect, and should return an error. There is an existing check for this +- set_params fails on devices in the LIVE state. But this check is not +sufficient to cover the recovery case. In this case, the device will be +in the QUIESCED or FAIL_IO states, so set_params will succeed. But this +success is misleading, because the parameters will not be applied, since +the device has already been started (by a previous ublk server). The bit +UB_STATE_USED is set on completion of the start_dev; use it to detect +and fail set_params commands which arrive too late to be applied (after +start_dev). + +Signed-off-by: Uday Shankar +Fixes: 0aa73170eba5 ("ublk_drv: add SET_PARAMS/GET_PARAMS control command") +Reviewed-by: Ming Lei +Link: https://lore.kernel.org/r/20250304-set_params-v1-1-17b5e0887606@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/ublk_drv.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index 35580ad45ce6e..f2a99e5d304dd 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -1873,9 +1873,12 @@ static int ublk_ctrl_set_params(struct ublk_device *ub, + if (ph.len > sizeof(struct ublk_params)) + ph.len = sizeof(struct ublk_params); + +- /* parameters can only be changed when device isn't live */ + mutex_lock(&ub->mutex); +- if (ub->dev_info.state == UBLK_S_DEV_LIVE) { ++ if (test_bit(UB_STATE_USED, &ub->state)) { ++ /* ++ * Parameters can only be changed when device hasn't ++ * been started yet ++ */ + ret = -EACCES; + } else if (copy_from_user(&ub->params, argp, ph.len)) { + ret = -EFAULT; +-- +2.39.5 + diff --git a/queue-6.1/vlan-enforce-underlying-device-type.patch b/queue-6.1/vlan-enforce-underlying-device-type.patch new file mode 100644 index 0000000000..fed5f94798 --- /dev/null +++ b/queue-6.1/vlan-enforce-underlying-device-type.patch @@ -0,0 +1,69 @@ +From bffad1ea4cb5e251319702a7d55ed70e5c5d3374 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 16:56:19 +0100 +Subject: vlan: enforce underlying device type + +From: Oscar Maes + +[ Upstream commit b33a534610067ade2bdaf2052900aaad99701353 ] + +Currently, VLAN devices can be created on top of non-ethernet devices. + +Besides the fact that it doesn't make much sense, this also causes a +bug which leaks the address of a kernel function to usermode. + +When creating a VLAN device, we initialize GARP (garp_init_applicant) +and MRP (mrp_init_applicant) for the underlying device. + +As part of the initialization process, we add the multicast address of +each applicant to the underlying device, by calling dev_mc_add. + +__dev_mc_add uses dev->addr_len to determine the length of the new +multicast address. + +This causes an out-of-bounds read if dev->addr_len is greater than 6, +since the multicast addresses provided by GARP and MRP are only 6 +bytes long. + +This behaviour can be reproduced using the following commands: + +ip tunnel add gretest mode ip6gre local ::1 remote ::2 dev lo +ip l set up dev gretest +ip link add link gretest name vlantest type vlan id 100 + +Then, the following command will display the address of garp_pdu_rcv: + +ip maddr show | grep 01:80:c2:00:00:21 + +Fix the bug by enforcing the type of the underlying device during VLAN +device initialization. + +Fixes: 22bedad3ce11 ("net: convert multicast list to list_head") +Reported-by: syzbot+91161fe81857b396c8a0@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/000000000000ca9a81061a01ec20@google.com/ +Signed-off-by: Oscar Maes +Reviewed-by: Jiri Pirko +Link: https://patch.msgid.link/20250303155619.8918-1-oscmaes92@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/8021q/vlan.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c +index e40aa3e3641cb..b477ba37a6991 100644 +--- a/net/8021q/vlan.c ++++ b/net/8021q/vlan.c +@@ -131,7 +131,8 @@ int vlan_check_real_dev(struct net_device *real_dev, + { + const char *name = real_dev->name; + +- if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { ++ if (real_dev->features & NETIF_F_VLAN_CHALLENGED || ++ real_dev->type != ARPHRD_ETHER) { + pr_info("VLANs not supported on %s\n", name); + NL_SET_ERR_MSG_MOD(extack, "VLANs not supported on device"); + return -EOPNOTSUPP; +-- +2.39.5 + diff --git a/queue-6.1/wifi-iwlwifi-limit-printed-string-from-fw-file.patch b/queue-6.1/wifi-iwlwifi-limit-printed-string-from-fw-file.patch new file mode 100644 index 0000000000..ef94dab95f --- /dev/null +++ b/queue-6.1/wifi-iwlwifi-limit-printed-string-from-fw-file.patch @@ -0,0 +1,43 @@ +From 853c2f656920b6d0625d1ef0436c51c135a2c160 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 14:34:51 +0200 +Subject: wifi: iwlwifi: limit printed string from FW file + +From: Johannes Berg + +[ Upstream commit e0dc2c1bef722cbf16ae557690861e5f91208129 ] + +There's no guarantee here that the file is always with a +NUL-termination, so reading the string may read beyond the +end of the TLV. If that's the last TLV in the file, it can +perhaps even read beyond the end of the file buffer. + +Fix that by limiting the print format to the size of the +buffer we have. + +Fixes: aee1b6385e29 ("iwlwifi: support fseq tlv and print fseq version") +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250209143303.cb5f9d0c2f5d.Idec695d53c6c2234aade306f7647b576c7e3d928@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +index 024c37062a60b..789393aa68cd8 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +@@ -1141,7 +1141,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, + + if (tlv_len != sizeof(*fseq_ver)) + goto invalid_tlv_len; +- IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %s\n", ++ IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n", + fseq_ver->version); + } + break; +-- +2.39.5 + diff --git a/queue-6.1/x86-sgx-fix-size-overflows-in-sgx_encl_create.patch b/queue-6.1/x86-sgx-fix-size-overflows-in-sgx_encl_create.patch new file mode 100644 index 0000000000..51b125db7c --- /dev/null +++ b/queue-6.1/x86-sgx-fix-size-overflows-in-sgx_encl_create.patch @@ -0,0 +1,55 @@ +From ce0b07c43684f9703536d0807d819a99b8fba630 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 07:00:05 +0200 +Subject: x86/sgx: Fix size overflows in sgx_encl_create() + +From: Jarkko Sakkinen + +[ Upstream commit 0d3e0dfd68fb9e6b0ec865be9f3377cc3ff55733 ] + +The total size calculated for EPC can overflow u64 given the added up page +for SECS. Further, the total size calculated for shmem can overflow even +when the EPC size stays within limits of u64, given that it adds the extra +space for 128 byte PCMD structures (one for each page). + +Address this by pre-evaluating the micro-architectural requirement of +SGX: the address space size must be power of two. This is eventually +checked up by ECREATE but the pre-check has the additional benefit of +making sure that there is some space for additional data. + +Fixes: 888d24911787 ("x86/sgx: Add SGX_IOC_ENCLAVE_CREATE") +Reported-by: Dan Carpenter +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Ingo Molnar +Acked-by: Dave Hansen +Cc: Peter Zijlstra +Cc: "H. Peter Anvin" +Link: https://lore.kernel.org/r/20250305050006.43896-1-jarkko@kernel.org + +Closes: https://lore.kernel.org/linux-sgx/c87e01a0-e7dd-4749-a348-0980d3444f04@stanley.mountain/ +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/sgx/ioctl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c +index da8b8ea6b063d..9634ac0fef1df 100644 +--- a/arch/x86/kernel/cpu/sgx/ioctl.c ++++ b/arch/x86/kernel/cpu/sgx/ioctl.c +@@ -64,6 +64,13 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) + struct file *backing; + long ret; + ++ /* ++ * ECREATE would detect this too, but checking here also ensures ++ * that the 'encl_size' calculations below can never overflow. ++ */ ++ if (!is_power_of_2(secs->size)) ++ return -EINVAL; ++ + va_page = sgx_encl_grow(encl, true); + if (IS_ERR(va_page)) + return PTR_ERR(va_page); +-- +2.39.5 +