diff --git a/SOURCES/1285-xen-privcmd-fix-double-free-via-vma-splitting.patch b/SOURCES/1285-xen-privcmd-fix-double-free-via-vma-splitting.patch new file mode 100644 index 000000000..bbefc28bf --- /dev/null +++ b/SOURCES/1285-xen-privcmd-fix-double-free-via-vma-splitting.patch @@ -0,0 +1,59 @@ +From 2b985d3a024b9e8c24e21671b34e855569763808 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Fri, 10 Apr 2026 09:20:04 +0200 +Subject: [PATCH] xen/privcmd: fix double free via VMA splitting + +commit 24daca4fc07f3ff8cd0e3f629cd982187f48436a upstream. + +privcmd_vm_ops defines .close (privcmd_close), but neither .may_split +nor .open. When userspace does a partial munmap() on a privcmd mapping, +the kernel splits the VMA via __split_vma(). Since may_split is NULL, +the split is allowed. vm_area_dup() copies vm_private_data (a pages +array allocated in alloc_empty_pages()) into the new VMA without any +fixup, because there is no .open callback. + +Both VMAs now point to the same pages array. When the unmapped portion +is closed, privcmd_close() calls: + - xen_unmap_domain_gfn_range() + - xen_free_unpopulated_pages() + - kvfree(pages) + +The surviving VMA still holds the dangling pointer. When it is later +destroyed, the same sequence runs again, which leads to a double free. + +Fix this issue by adding a .may_split callback denying the VMA split. + +This is XSA-487 / CVE-2026-31787 + +Fixes: d71f513985c2 ("xen: privcmd: support autotranslated physmap guests.") +Reported-by: Atharva Vartak +Suggested-by: Atharva Vartak +Signed-off-by: Juergen Gross +Reviewed-by: Jan Beulich +Signed-off-by: Greg Kroah-Hartman + +diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c +index 8d0f4f2..a867792 100644 +--- a/drivers/xen/privcmd.c ++++ b/drivers/xen/privcmd.c +@@ -914,6 +914,12 @@ static void privcmd_close(struct vm_area_struct *vma) + kfree(pages); + } + ++static int privcmd_may_split(struct vm_area_struct *area, unsigned long addr) ++{ ++ /* Forbid splitting, avoids double free via privcmd_close(). */ ++ return -EINVAL; ++} ++ + static vm_fault_t privcmd_fault(struct vm_fault *vmf) + { + printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n", +@@ -925,6 +931,7 @@ static vm_fault_t privcmd_fault(struct vm_fault *vmf) + + static const struct vm_operations_struct privcmd_vm_ops = { + .close = privcmd_close, ++ .may_split = privcmd_may_split, + .fault = privcmd_fault + }; + diff --git a/SOURCES/1286-bluetooth-hci-sync-fix-stack-buffer-overflow-in-hci-le-big-c.patch b/SOURCES/1286-bluetooth-hci-sync-fix-stack-buffer-overflow-in-hci-le-big-c.patch new file mode 100644 index 000000000..580f5bc10 --- /dev/null +++ b/SOURCES/1286-bluetooth-hci-sync-fix-stack-buffer-overflow-in-hci-le-big-c.patch @@ -0,0 +1,60 @@ +From 3eefd9e9213a567e4b2121832ee201264486407c Mon Sep 17 00:00:00 2001 +From: CKI Backport Bot +Date: Fri, 1 May 2026 23:14:11 +0000 +Subject: [PATCH] Bluetooth: hci_sync: fix stack buffer overflow in + hci_le_big_create_sync +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +JIRA: https://redhat.atlassian.net/browse/RHEL-172859 +CVE: CVE-2026-31772 + +commit bc39a094730ce062fa034a529c93147c096cb488 +Author: hkbinbin +Date: Tue Mar 31 05:39:16 2026 +0000 + + Bluetooth: hci_sync: fix stack buffer overflow in hci_le_big_create_sync + + hci_le_big_create_sync() uses DEFINE_FLEX to allocate a + struct hci_cp_le_big_create_sync on the stack with room for 0x11 (17) + BIS entries. However, conn->num_bis can hold up to HCI_MAX_ISO_BIS (31) + entries — validated against ISO_MAX_NUM_BIS (0x1f) in the caller + hci_conn_big_create_sync(). When conn->num_bis is between 18 and 31, + the memcpy that copies conn->bis into cp->bis writes up to 14 bytes + past the stack buffer, corrupting adjacent stack memory. + + This is trivially reproducible: binding an ISO socket with + bc_num_bis = ISO_MAX_NUM_BIS (31) and calling listen() will + eventually trigger hci_le_big_create_sync() from the HCI command + sync worker, causing a KASAN-detectable stack-out-of-bounds write: + + BUG: KASAN: stack-out-of-bounds in hci_le_big_create_sync+0x256/0x3b0 + Write of size 31 at addr ffffc90000487b48 by task kworker/u9:0/71 + + Fix this by changing the DEFINE_FLEX count from the incorrect 0x11 to + HCI_MAX_ISO_BIS, which matches the maximum number of BIS entries that + conn->bis can actually carry. + + Fixes: 42ecf1947135 ("Bluetooth: ISO: Do not emit LE BIG Create Sync if previous is pending") + Cc: stable@vger.kernel.org + Signed-off-by: hkbinbin + Reviewed-by: Paul Menzel + Signed-off-by: Luiz Augusto von Dentz + +Signed-off-by: CKI Backport Bot + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index e302afc..b571278 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -7126,7 +7126,8 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err) + + static int hci_le_big_create_sync(struct hci_dev *hdev, void *data) + { +- DEFINE_FLEX(struct hci_cp_le_big_create_sync, cp, bis, num_bis, 0x11); ++ DEFINE_FLEX(struct hci_cp_le_big_create_sync, cp, bis, num_bis, ++ HCI_MAX_ISO_BIS); + struct hci_conn *conn = data; + struct bt_iso_qos *qos = &conn->iso_qos; + int err; diff --git a/SOURCES/1287-can-isotp-fix-tx-buf-use-after-free-in-isotp-sendmsg.patch b/SOURCES/1287-can-isotp-fix-tx-buf-use-after-free-in-isotp-sendmsg.patch new file mode 100644 index 000000000..202bc1c83 --- /dev/null +++ b/SOURCES/1287-can-isotp-fix-tx-buf-use-after-free-in-isotp-sendmsg.patch @@ -0,0 +1,77 @@ +From 424e95d62110cdbc8fd12b40918f37e408e35a92 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Thu, 19 Mar 2026 16:47:45 +0100 +Subject: [PATCH] can: isotp: fix tx.buf use-after-free in isotp_sendmsg() + +isotp_sendmsg() uses only cmpxchg() on so->tx.state to serialize access +to so->tx.buf. isotp_release() waits for ISOTP_IDLE via +wait_event_interruptible() and then calls kfree(so->tx.buf). + +If a signal interrupts the wait_event_interruptible() inside close() +while tx.state is ISOTP_SENDING, the loop exits early and release +proceeds to force ISOTP_SHUTDOWN and continues to kfree(so->tx.buf) +while sendmsg may still be reading so->tx.buf for the final CAN frame +in isotp_fill_dataframe(). + +The so->tx.buf can be allocated once when the standard tx.buf length needs +to be extended. Move the kfree() of this potentially extended tx.buf to +sk_destruct time when either isotp_sendmsg() and isotp_release() are done. + +Fixes: 96d1c81e6a04 ("can: isotp: add module parameter for maximum pdu size") +Cc: stable@vger.kernel.org +Reported-by: Ali Norouzi +Co-developed-by: Ali Norouzi +Signed-off-by: Ali Norouzi +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260319-fix-can-gw-and-can-isotp-v2-2-c45d52c6d2d8@pengutronix.de +Signed-off-by: Marc Kleine-Budde + +diff --git a/net/can/isotp.c b/net/can/isotp.c +index 7363470..311f0af 100644 +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -1229,12 +1229,6 @@ static int isotp_release(struct socket *sock) + so->ifindex = 0; + so->bound = 0; + +- if (so->rx.buf != so->rx.sbuf) +- kfree(so->rx.buf); +- +- if (so->tx.buf != so->tx.sbuf) +- kfree(so->tx.buf); +- + sock_orphan(sk); + sock->sk = NULL; + +@@ -1602,6 +1596,21 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg, + return NOTIFY_DONE; + } + ++static void isotp_sock_destruct(struct sock *sk) ++{ ++ struct isotp_sock *so = isotp_sk(sk); ++ ++ /* do the standard CAN sock destruct work */ ++ can_sock_destruct(sk); ++ ++ /* free potential extended PDU buffers */ ++ if (so->rx.buf != so->rx.sbuf) ++ kfree(so->rx.buf); ++ ++ if (so->tx.buf != so->tx.sbuf) ++ kfree(so->tx.buf); ++} ++ + static int isotp_init(struct sock *sk) + { + struct isotp_sock *so = isotp_sk(sk); +@@ -1648,6 +1657,9 @@ static int isotp_init(struct sock *sk) + list_add_tail(&so->notifier, &isotp_notifier_list); + spin_unlock(&isotp_notifier_lock); + ++ /* re-assign default can_sock_destruct() reference */ ++ sk->sk_destruct = isotp_sock_destruct; ++ + return 0; + } + diff --git a/SOURCES/1288-dpll-add-pin-operational-state.patch b/SOURCES/1288-dpll-add-pin-operational-state.patch new file mode 100644 index 000000000..e3e414737 --- /dev/null +++ b/SOURCES/1288-dpll-add-pin-operational-state.patch @@ -0,0 +1,279 @@ +From 781c8893a5da8522ae4ded93e5ef3adbe9559300 Mon Sep 17 00:00:00 2001 +From: Ivan Vecera +Date: Tue, 28 Apr 2026 17:49:06 +0200 +Subject: [PATCH] dpll: add pin operational state + +Add pin-operstate enum and operstate_on_dpll_get callback to report +the actual hardware status of a pin with respect to its parent DPLL +device. Unlike pin-state (which reflects administrative intent set +by the user), operstate reflects what the hardware is actually doing. + +Defined operational states: + - active: pin is qualified and actively used by the DPLL + - standby: pin is qualified but not actively used by the DPLL + - no-signal: pin does not have a valid signal + - qual-failed: pin signal failed qualification + +The operstate is reported inside the pin-parent-device nested +attribute alongside the existing state and phase-offset attributes. + +Signed-off-by: Ivan Vecera +Reviewed-by: Jiri Pirko +Reviewed-by: Vadim Fedorenko +Reviewed-by: Petr Oros +Link: https://patch.msgid.link/20260428154907.2820654-2-ivecera@redhat.com +Signed-off-by: Paolo Abeni + +diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst +index 93c191b..37eaef7 100644 +--- a/Documentation/driver-api/dpll.rst ++++ b/Documentation/driver-api/dpll.rst +@@ -65,35 +65,43 @@ request, where user provides attributes that result in single pin match. + Pin selection + ============= + +-In general, selected pin (the one which signal is driving the dpll +-device) can be obtained from ``DPLL_A_PIN_STATE`` attribute, and only +-one pin shall be in ``DPLL_PIN_STATE_CONNECTED`` state for any dpll +-device. ++Pin state (``DPLL_A_PIN_STATE``) reflects the administrative intent set ++by the user. Pin operational state (``DPLL_A_PIN_OPERSTATE``) reflects ++what the hardware is actually doing with the pin. + + Pin selection can be done either manually or automatically, depending + on hardware capabilities and active dpll device work mode + (``DPLL_A_MODE`` attribute). The consequence is that there are +-differences for each mode in terms of available pin states, as well as +-for the states the user can request for a dpll device. ++differences for each mode in terms of available pin states the user can ++request for a dpll device. + +-In manual mode (``DPLL_MODE_MANUAL``) the user can request or receive +-one of following pin states: ++In manual mode (``DPLL_MODE_MANUAL``) the user can request one of ++following pin states: + +-- ``DPLL_PIN_STATE_CONNECTED`` - the pin is used to drive dpll device +-- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not used to drive dpll ++- ``DPLL_PIN_STATE_CONNECTED`` - the pin is selected to drive dpll + device ++- ``DPLL_PIN_STATE_DISCONNECTED`` - the pin is not selected to drive ++ dpll device + +-In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request or +-receive one of following pin states: ++In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can request one of ++following pin states: + + - ``DPLL_PIN_STATE_SELECTABLE`` - the pin shall be considered as valid + input for automatic selection algorithm + - ``DPLL_PIN_STATE_DISCONNECTED`` - the pin shall be not considered as + a valid input for automatic selection algorithm + +-In automatic mode (``DPLL_MODE_AUTOMATIC``) the user can only receive +-pin state ``DPLL_PIN_STATE_CONNECTED`` once automatic selection +-algorithm locks a dpll device with one of the inputs. ++The actual hardware status of a pin is reported via the operational ++state (``DPLL_A_PIN_OPERSTATE``) attribute nested under the parent ++device: ++ ++- ``DPLL_PIN_OPERSTATE_ACTIVE`` - pin is qualified and actively used ++ by the DPLL ++- ``DPLL_PIN_OPERSTATE_STANDBY`` - pin is qualified but not actively ++ used by the DPLL ++- ``DPLL_PIN_OPERSTATE_NO_SIGNAL`` - pin does not have a valid signal ++- ``DPLL_PIN_OPERSTATE_QUAL_FAILED`` - pin signal failed qualification ++ checks + + Shared pins + =========== +diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml +index cb5da35..a47d7da 100644 +--- a/Documentation/netlink/specs/dpll.yaml ++++ b/Documentation/netlink/specs/dpll.yaml +@@ -212,6 +212,27 @@ definitions: + name: selectable + doc: pin enabled for automatic input selection + render-max: true ++ - ++ type: enum ++ name: pin-operstate ++ doc: | ++ defines possible operational states of a pin with respect to its ++ parent DPLL device, valid values for DPLL_A_PIN_OPERSTATE attribute ++ entries: ++ - ++ name: active ++ doc: pin is qualified and actively used by the DPLL ++ value: 1 ++ - ++ name: standby ++ doc: pin is qualified but not actively used by the DPLL ++ - ++ name: no-signal ++ doc: pin does not have a valid signal ++ - ++ name: qual-failed ++ doc: pin signal failed qualification (e.g. frequency or phase monitor) ++ render-max: true + - + type: flags + name: pin-capabilities +@@ -488,6 +509,14 @@ attribute-sets: + Value of (DPLL_A_PIN_MEASURED_FREQUENCY % + DPLL_PIN_MEASURED_FREQUENCY_DIVIDER) is a fractional part + of a measured frequency value. ++ - ++ name: operstate ++ type: u32 ++ enum: pin-operstate ++ doc: | ++ Operational state of the pin with respect to its parent DPLL ++ device. Unlike state (which reflects the administrative intent), ++ operstate reflects the actual hardware status. + + - + name: pin-parent-device +@@ -501,6 +530,8 @@ attribute-sets: + name: prio + - + name: state ++ - ++ name: operstate + - + name: phase-offset + - +diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c +index 0ff1658..ea63602 100644 +--- a/drivers/dpll/dpll_netlink.c ++++ b/drivers/dpll/dpll_netlink.c +@@ -324,6 +324,30 @@ dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin, + return 0; + } + ++static int ++dpll_msg_add_pin_operstate(struct sk_buff *msg, struct dpll_pin *pin, ++ struct dpll_pin_ref *ref, ++ struct netlink_ext_ack *extack) ++{ ++ const struct dpll_pin_ops *ops = dpll_pin_ops(ref); ++ struct dpll_device *dpll = ref->dpll; ++ enum dpll_pin_operstate operstate; ++ int ret; ++ ++ if (!ops->operstate_on_dpll_get) ++ return 0; ++ ret = ops->operstate_on_dpll_get(pin, ++ dpll_pin_on_dpll_priv(dpll, pin), ++ dpll, dpll_priv(dpll), ++ &operstate, extack); ++ if (ret) ++ return ret; ++ if (nla_put_u32(msg, DPLL_A_PIN_OPERSTATE, operstate)) ++ return -EMSGSIZE; ++ ++ return 0; ++} ++ + static int + dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin, + struct dpll_pin_ref *ref, +@@ -650,6 +674,9 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin, + if (ret) + goto nest_cancel; + ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack); ++ if (ret) ++ goto nest_cancel; ++ ret = dpll_msg_add_pin_operstate(msg, pin, ref, extack); + if (ret) + goto nest_cancel; + ret = dpll_msg_add_pin_prio(msg, pin, ref, extack); +diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c +index da92aa8..6439884 100644 +--- a/drivers/dpll/dpll_nl.c ++++ b/drivers/dpll/dpll_nl.c +@@ -11,11 +11,12 @@ + #include + + /* Common nested types */ +-const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1] = { ++const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1] = { + [DPLL_A_PIN_PARENT_ID] = { .type = NLA_U32, }, + [DPLL_A_PIN_DIRECTION] = NLA_POLICY_RANGE(NLA_U32, 1, 2), + [DPLL_A_PIN_PRIO] = { .type = NLA_U32, }, + [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3), ++ [DPLL_A_PIN_OPERSTATE] = NLA_POLICY_RANGE(NLA_U32, 1, 4), + [DPLL_A_PIN_PHASE_OFFSET] = { .type = NLA_S64, }, + }; + +diff --git a/drivers/dpll/dpll_nl.h b/drivers/dpll/dpll_nl.h +index 3da10cf..8cf3b73 100644 +--- a/drivers/dpll/dpll_nl.h ++++ b/drivers/dpll/dpll_nl.h +@@ -12,7 +12,7 @@ + #include + + /* Common nested types */ +-extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_PHASE_OFFSET + 1]; ++extern const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + 1]; + extern const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1]; + extern const struct nla_policy dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1]; + +diff --git a/include/linux/dpll.h b/include/linux/dpll.h +index 7f8fa58..c5e333a 100644 +--- a/include/linux/dpll.h ++++ b/include/linux/dpll.h +@@ -96,6 +96,12 @@ struct dpll_pin_ops { + const struct dpll_device *dpll, + void *dpll_priv, enum dpll_pin_state *state, + struct netlink_ext_ack *extack); ++ int (*operstate_on_dpll_get)(const struct dpll_pin *pin, ++ void *pin_priv, ++ const struct dpll_device *dpll, ++ void *dpll_priv, ++ enum dpll_pin_operstate *operstate, ++ struct netlink_ext_ack *extack); + int (*state_on_pin_set)(const struct dpll_pin *pin, void *pin_priv, + const struct dpll_pin *parent_pin, + void *parent_pin_priv, +diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h +index 93614cc..aa45b79 100644 +--- a/include/uapi/linux/dpll.h ++++ b/include/uapi/linux/dpll.h +@@ -177,6 +177,28 @@ enum dpll_pin_state { + DPLL_PIN_STATE_MAX = (__DPLL_PIN_STATE_MAX - 1) + }; + ++/** ++ * enum dpll_pin_operstate - defines possible operational states of a pin with ++ * respect to its parent DPLL device, valid values for DPLL_A_PIN_OPERSTATE ++ * attribute ++ * @DPLL_PIN_OPERSTATE_ACTIVE: pin is qualified and actively used by the DPLL ++ * @DPLL_PIN_OPERSTATE_STANDBY: pin is qualified but not actively used by the ++ * DPLL ++ * @DPLL_PIN_OPERSTATE_NO_SIGNAL: pin does not have a valid signal ++ * @DPLL_PIN_OPERSTATE_QUAL_FAILED: pin signal failed qualification (e.g. ++ * frequency or phase monitor) ++ */ ++enum dpll_pin_operstate { ++ DPLL_PIN_OPERSTATE_ACTIVE = 1, ++ DPLL_PIN_OPERSTATE_STANDBY, ++ DPLL_PIN_OPERSTATE_NO_SIGNAL, ++ DPLL_PIN_OPERSTATE_QUAL_FAILED, ++ ++ /* private: */ ++ __DPLL_PIN_OPERSTATE_MAX, ++ DPLL_PIN_OPERSTATE_MAX = (__DPLL_PIN_OPERSTATE_MAX - 1) ++}; ++ + /** + * enum dpll_pin_capabilities - defines possible capabilities of a pin, valid + * flags on DPLL_A_PIN_CAPABILITIES attribute +@@ -256,6 +278,7 @@ enum dpll_a_pin { + DPLL_A_PIN_PHASE_ADJUST_GRAN, + DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, + DPLL_A_PIN_MEASURED_FREQUENCY, ++ DPLL_A_PIN_OPERSTATE, + + __DPLL_A_PIN_MAX, + DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1) diff --git a/SOURCES/1289-dpll-zl3073x-implement-pin-operational-state-reporting.patch b/SOURCES/1289-dpll-zl3073x-implement-pin-operational-state-reporting.patch new file mode 100644 index 000000000..1ebd88503 --- /dev/null +++ b/SOURCES/1289-dpll-zl3073x-implement-pin-operational-state-reporting.patch @@ -0,0 +1,239 @@ +From c53f8f8dce776e032b1a11fb4d9b6e12bb63d958 Mon Sep 17 00:00:00 2001 +From: Ivan Vecera +Date: Tue, 28 Apr 2026 17:49:07 +0200 +Subject: [PATCH] dpll: zl3073x: implement pin operational state reporting + +Implement operstate_on_dpll_get callback for input pins to report +the actual hardware status: + + - active: pin is the currently locked reference + - standby: signal is valid but pin is not actively used + - no-signal: reference monitor reports Loss of Signal (LOS) + - qual-failed: reference monitor reports a qualification failure + (SCM, CFM, GST, PFM, eSync or Split-XO) + +Separate administrative state (state_on_dpll_get) from operational +state: admin state now reports purely the user-requested intent +(connected in reflock mode, selectable in auto mode). + +Switch periodic monitoring to track operstate changes instead of +the mixed admin/oper state that was previously reported. + +Add ref_mon_status bit definitions to regs.h. + +Signed-off-by: Ivan Vecera +Reviewed-by: Petr Oros +Link: https://patch.msgid.link/20260428154907.2820654-3-ivecera@redhat.com +Signed-off-by: Paolo Abeni + +diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c +index 55195dc..2c8bd21 100644 +--- a/drivers/dpll/zl3073x/dpll.c ++++ b/drivers/dpll/zl3073x/dpll.c +@@ -38,7 +38,7 @@ + * @prio: pin priority <0, 14> + * @esync_control: embedded sync is controllable + * @phase_gran: phase adjustment granularity +- * @pin_state: last saved pin state ++ * @operstate: last saved operational state + * @phase_offset: last saved pin phase offset + * @freq_offset: last saved fractional frequency offset + * @measured_freq: last saved measured frequency +@@ -55,7 +55,7 @@ struct zl3073x_dpll_pin { + u8 prio; + bool esync_control; + s32 phase_gran; +- enum dpll_pin_state pin_state; ++ enum dpll_pin_operstate operstate; + s64 phase_offset; + s64 freq_offset; + u32 measured_freq; +@@ -500,46 +500,41 @@ zl3073x_dpll_input_pin_phase_adjust_set(const struct dpll_pin *dpll_pin, + } + + /** +- * zl3073x_dpll_ref_state_get - get status for given input pin ++ * zl3073x_dpll_ref_operstate_get - get operational state for input pin + * @pin: pointer to pin +- * @state: place to store status ++ * @operstate: place to store operational state + * +- * Checks current status for the given input pin and stores the value +- * to @state. ++ * Returns the actual hardware state of the pin: whether it is actively ++ * used by the DPLL, has no signal, failed qualification, or is simply ++ * not in use. + * + * Return: 0 on success, <0 on error + */ + static int +-zl3073x_dpll_ref_state_get(struct zl3073x_dpll_pin *pin, +- enum dpll_pin_state *state) ++zl3073x_dpll_ref_operstate_get(struct zl3073x_dpll_pin *pin, ++ enum dpll_pin_operstate *operstate) + { + struct zl3073x_dpll *zldpll = pin->dpll; + struct zl3073x_dev *zldev = zldpll->dev; +- const struct zl3073x_chan *chan; +- u8 ref; +- +- chan = zl3073x_chan_state_get(zldev, zldpll->id); +- ref = zl3073x_input_pin_ref_get(pin->id); ++ const struct zl3073x_ref *ref; ++ u8 ref_id; + +- /* Check if the pin reference is connected */ +- if (ref == zl3073x_dpll_connected_ref_get(zldpll)) { +- *state = DPLL_PIN_STATE_CONNECTED; +- return 0; +- } ++ ref_id = zl3073x_input_pin_ref_get(pin->id); + +- /* If the DPLL is running in automatic mode and the reference is +- * selectable and its monitor does not report any error then report +- * pin as selectable. +- */ +- if (zl3073x_chan_mode_get(chan) == ZL_DPLL_MODE_REFSEL_MODE_AUTO && +- zl3073x_dev_ref_is_status_ok(zldev, ref) && +- zl3073x_chan_ref_is_selectable(chan, ref)) { +- *state = DPLL_PIN_STATE_SELECTABLE; ++ /* Check if this pin is the currently locked reference */ ++ if (ref_id == zl3073x_dpll_connected_ref_get(zldpll)) { ++ *operstate = DPLL_PIN_OPERSTATE_ACTIVE; + return 0; + } + +- /* Otherwise report the pin as disconnected */ +- *state = DPLL_PIN_STATE_DISCONNECTED; ++ /* Check reference monitor status */ ++ ref = zl3073x_ref_state_get(zldev, ref_id); ++ if (ref->mon_status & ZL_REF_MON_STATUS_LOS) ++ *operstate = DPLL_PIN_OPERSTATE_NO_SIGNAL; ++ else if (!zl3073x_ref_is_status_ok(ref)) ++ *operstate = DPLL_PIN_OPERSTATE_QUAL_FAILED; ++ else ++ *operstate = DPLL_PIN_OPERSTATE_STANDBY; + + return 0; + } +@@ -551,10 +546,48 @@ zl3073x_dpll_input_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin, + void *dpll_priv, + enum dpll_pin_state *state, + struct netlink_ext_ack *extack) ++{ ++ struct zl3073x_dpll *zldpll = dpll_priv; ++ struct zl3073x_dpll_pin *pin = pin_priv; ++ const struct zl3073x_chan *chan; ++ u8 mode, ref; ++ ++ chan = zl3073x_chan_state_get(zldpll->dev, zldpll->id); ++ ref = zl3073x_input_pin_ref_get(pin->id); ++ mode = zl3073x_chan_mode_get(chan); ++ ++ switch (mode) { ++ case ZL_DPLL_MODE_REFSEL_MODE_REFLOCK: ++ if (ref == zl3073x_chan_ref_get(chan)) ++ *state = DPLL_PIN_STATE_CONNECTED; ++ else ++ *state = DPLL_PIN_STATE_DISCONNECTED; ++ break; ++ case ZL_DPLL_MODE_REFSEL_MODE_AUTO: ++ if (zl3073x_chan_ref_is_selectable(chan, ref)) ++ *state = DPLL_PIN_STATE_SELECTABLE; ++ else ++ *state = DPLL_PIN_STATE_DISCONNECTED; ++ break; ++ default: ++ *state = DPLL_PIN_STATE_DISCONNECTED; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int ++zl3073x_dpll_input_pin_operstate_on_dpll_get(const struct dpll_pin *dpll_pin, ++ void *pin_priv, ++ const struct dpll_device *dpll, ++ void *dpll_priv, ++ enum dpll_pin_operstate *operstate, ++ struct netlink_ext_ack *extack) + { + struct zl3073x_dpll_pin *pin = pin_priv; + +- return zl3073x_dpll_ref_state_get(pin, state); ++ return zl3073x_dpll_ref_operstate_get(pin, operstate); + } + + static int +@@ -1248,6 +1281,7 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = { + .frequency_get = zl3073x_dpll_input_pin_frequency_get, + .frequency_set = zl3073x_dpll_input_pin_frequency_set, + .measured_freq_get = zl3073x_dpll_input_pin_measured_freq_get, ++ .operstate_on_dpll_get = zl3073x_dpll_input_pin_operstate_on_dpll_get, + .phase_offset_get = zl3073x_dpll_input_pin_phase_offset_get, + .phase_adjust_get = zl3073x_dpll_input_pin_phase_adjust_get, + .phase_adjust_set = zl3073x_dpll_input_pin_phase_adjust_set, +@@ -1663,7 +1697,7 @@ zl3073x_dpll_pin_phase_offset_check(struct zl3073x_dpll_pin *pin) + * 2) For other pins use appropriate ref_phase register if the phase + * monitor feature is enabled. + */ +- if (pin->pin_state == DPLL_PIN_STATE_CONNECTED) ++ if (pin->operstate == DPLL_PIN_OPERSTATE_ACTIVE) + reg = ZL_REG_DPLL_PHASE_ERR_DATA(zldpll->id); + else if (zldpll->phase_monitor) + reg = ZL_REG_REF_PHASE(ref_id); +@@ -1828,7 +1862,7 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll) + } + + list_for_each_entry(pin, &zldpll->pins, list) { +- enum dpll_pin_state state; ++ enum dpll_pin_operstate operstate; + bool pin_changed = false; + + /* Output pins change checks are not necessary because output +@@ -1837,18 +1871,18 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll) + if (!zl3073x_dpll_is_input_pin(pin)) + continue; + +- rc = zl3073x_dpll_ref_state_get(pin, &state); ++ rc = zl3073x_dpll_ref_operstate_get(pin, &operstate); + if (rc) { + dev_err(dev, +- "Failed to get %s on DPLL%u state: %pe\n", ++ "Failed to get %s on DPLL%u oper state: %pe\n", + pin->label, zldpll->id, ERR_PTR(rc)); + return; + } + +- if (state != pin->pin_state) { +- dev_dbg(dev, "%s state changed: %u->%u\n", pin->label, +- pin->pin_state, state); +- pin->pin_state = state; ++ if (operstate != pin->operstate) { ++ dev_dbg(dev, "%s oper state changed: %u->%u\n", ++ pin->label, pin->operstate, operstate); ++ pin->operstate = operstate; + pin_changed = true; + } + +diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h +index d425dc6..8015808 100644 +--- a/drivers/dpll/zl3073x/regs.h ++++ b/drivers/dpll/zl3073x/regs.h +@@ -98,7 +98,14 @@ + + #define ZL_REG_REF_MON_STATUS(_idx) \ + ZL_REG_IDX(_idx, 2, 0x02, 1, ZL3073X_NUM_REFS, 1) +-#define ZL_REF_MON_STATUS_OK 0 /* all bits zeroed */ ++#define ZL_REF_MON_STATUS_OK 0 ++#define ZL_REF_MON_STATUS_LOS BIT(0) ++#define ZL_REF_MON_STATUS_SCM BIT(1) ++#define ZL_REF_MON_STATUS_CFM BIT(2) ++#define ZL_REF_MON_STATUS_GST BIT(3) ++#define ZL_REF_MON_STATUS_PFM BIT(4) ++#define ZL_REF_MON_STATUS_ESYNC BIT(6) ++#define ZL_REF_MON_STATUS_SPLIT_XO BIT(7) + + #define ZL_REG_DPLL_MON_STATUS(_idx) \ + ZL_REG_IDX(_idx, 2, 0x10, 1, ZL3073X_MAX_CHANNELS, 1) diff --git a/SOURCES/1290-dpll-add-fractional-frequency-offset-to-pin-parent-device.patch b/SOURCES/1290-dpll-add-fractional-frequency-offset-to-pin-parent-device.patch new file mode 100644 index 000000000..4d6b43359 --- /dev/null +++ b/SOURCES/1290-dpll-add-fractional-frequency-offset-to-pin-parent-device.patch @@ -0,0 +1,354 @@ +From 9c11fcb2e9a54d0f1467380831e2e4bb68f7498d Mon Sep 17 00:00:00 2001 +From: Ivan Vecera +Date: Mon, 11 May 2026 17:58:15 +0200 +Subject: [PATCH] dpll: add fractional frequency offset to pin-parent-device + +Add both fractional-frequency-offset (PPM) and +fractional-frequency-offset-ppt (PPT) attributes to the +pin-parent-device nested attribute set, alongside the existing +top-level pin attributes. Both carry the same measurement at +different precisions. + +Introduce enum dpll_ffo_type and struct dpll_ffo_param to +distinguish FFO contexts: DPLL_FFO_PORT_RXTX_RATE for the RX vs +TX symbol rate offset reported at the top level, and +DPLL_FFO_PIN_DEVICE for the pin vs parent DPLL offset reported +in the pin-parent-device nest. + +Add a supported_ffo bitmask to struct dpll_pin_ops so drivers +declare which FFO types they support. The core only calls ffo_get +for types the driver has opted into, eliminating the need for +per-driver NULL pointer guards. Validate at pin registration time +that supported_ffo is not set without an ffo_get callback. + +Update mlx5 (DPLL_FFO_PORT_RXTX_RATE) and zl3073x +(DPLL_FFO_PORT_RXTX_RATE) drivers to use the new API. + +Add documentation for both FFO types to dpll.rst. + +Changes v3 -> v4: +- Replace dpll=NULL overloading with enum dpll_ffo_type and + struct dpll_ffo_param (Jakub Kicinski) +- Add supported_ffo opt-in bitmask in dpll_pin_ops for fail-close + driver validation (Jakub Kicinski) +- Add WARN_ON in dpll_pin_register for supported_ffo without + ffo_get callback + +Reviewed-by: Jiri Pirko +Signed-off-by: Ivan Vecera +Link: https://patch.msgid.link/20260511155816.99936-2-ivecera@redhat.com +Signed-off-by: Jakub Kicinski + +diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst +index 37eaef7..bae1476 100644 +--- a/Documentation/driver-api/dpll.rst ++++ b/Documentation/driver-api/dpll.rst +@@ -258,6 +258,26 @@ in the ``DPLL_A_PIN_PHASE_OFFSET`` attribute. + ``DPLL_A_PHASE_OFFSET_MONITOR`` attr state of a feature + =============================== ======================== + ++Fractional frequency offset ++=========================== ++ ++The fractional frequency offset (FFO) is reported through two attributes ++that carry the same measurement at different precisions: ++ ++- ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET`` in PPM (parts per million) ++- ``DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT`` in PPT (parts per trillion) ++ ++Both attributes appear at the top level of a pin and inside each ++``pin-parent-device`` nest. Two FFO types are defined: ++ ++- ``DPLL_FFO_PORT_RXTX_RATE`` - RX vs TX symbol rate offset (top-level) ++- ``DPLL_FFO_PIN_DEVICE`` - pin vs parent DPLL offset (per-parent) ++ ++The driver declares which types it supports via the ``supported_ffo`` ++bitmask in ``struct dpll_pin_ops``. The core only calls the ``ffo_get`` ++callback for types the driver has opted into. The requested type is ++passed to the driver in the ``struct dpll_ffo_param``. ++ + Frequency monitor + ================= + +diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml +index a47d7da..4ba8adc 100644 +--- a/Documentation/netlink/specs/dpll.yaml ++++ b/Documentation/netlink/specs/dpll.yaml +@@ -448,12 +448,14 @@ attribute-sets: + name: fractional-frequency-offset + type: sint + doc: | +- The FFO (Fractional Frequency Offset) between the RX and TX +- symbol rate on the media associated with the pin: +- (rx_frequency-tx_frequency)/rx_frequency ++ The FFO (Fractional Frequency Offset) of the pin. ++ At top level this represents the RX vs TX symbol rate ++ offset on the media associated with the pin. Inside ++ the pin-parent-device nest it represents the frequency ++ offset between the pin and its parent DPLL device. + Value is in PPM (parts per million). +- This may be implemented for example for pin of type +- PIN_TYPE_SYNCE_ETH_PORT. ++ This is a lower-precision version of ++ fractional-frequency-offset-ppt. + - + name: esync-frequency + type: u64 +@@ -492,12 +494,14 @@ attribute-sets: + name: fractional-frequency-offset-ppt + type: sint + doc: | +- The FFO (Fractional Frequency Offset) of the pin with respect to +- the nominal frequency. +- Value = (frequency_measured - frequency_nominal) / frequency_nominal ++ The FFO (Fractional Frequency Offset) of the pin. ++ At top level this represents the RX vs TX symbol rate ++ offset on the media associated with the pin. Inside ++ the pin-parent-device nest it represents the frequency ++ offset between the pin and its parent DPLL device. + Value is in PPT (parts per trillion, 10^-12). +- Note: This attribute provides higher resolution than the standard +- fractional-frequency-offset (which is in PPM). ++ This is a higher-precision version of ++ fractional-frequency-offset. + - + name: measured-frequency + type: u64 +@@ -534,6 +538,10 @@ attribute-sets: + name: operstate + - + name: phase-offset ++ - ++ name: fractional-frequency-offset ++ - ++ name: fractional-frequency-offset-ppt + - + name: pin-parent-pin + subset-of: pin +diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c +index 84e1b63..8b260a3 100644 +--- a/drivers/dpll/dpll_core.c ++++ b/drivers/dpll/dpll_core.c +@@ -883,7 +883,8 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, + WARN_ON(!ops->direction_get) || + WARN_ON(ops->measured_freq_get && + (!dpll_device_ops(dpll)->freq_monitor_get || +- !dpll_device_ops(dpll)->freq_monitor_set))) ++ !dpll_device_ops(dpll)->freq_monitor_set)) || ++ WARN_ON(ops->supported_ffo && !ops->ffo_get)) + return -EINVAL; + + mutex_lock(&dpll_lock); +diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c +index ea63602..6a4ddd7 100644 +--- a/drivers/dpll/dpll_netlink.c ++++ b/drivers/dpll/dpll_netlink.c +@@ -417,31 +417,34 @@ dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin, + + static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin, + struct dpll_pin_ref *ref, ++ enum dpll_ffo_type type, + struct netlink_ext_ack *extack) + { + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); +- struct dpll_device *dpll = ref->dpll; +- s64 ffo; ++ struct dpll_ffo_param ffo = { .type = type }; + int ret; + +- if (!ops->ffo_get) +- return 0; +- ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(dpll, pin), +- dpll, dpll_priv(dpll), &ffo, extack); ++ /* RHEL: To maintain backward compatibility with older binary modules, ++ * we must accept a value of zero for .supported_ffo when the type is ++ * DPLL_FFO_PORT_RXTX_RATE. ++ */ ++ if (!ops->ffo_get || ++ !((ops->supported_ffo & BIT(type)) || ++ (!ops->supported_ffo && type == DPLL_FFO_PORT_RXTX_RATE))) ++ return 0; ++ ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(ref->dpll, pin), ++ ref->dpll, dpll_priv(ref->dpll), &ffo, extack); + if (ret) { + if (ret == -ENODATA) + return 0; + return ret; + } +- /* Put the FFO value in PPM to preserve compatibility with older +- * programs. +- */ +- ret = nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, +- div_s64(ffo, 1000000)); +- if (ret) ++ if (nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, ++ div_s64(ffo.ffo, 1000000))) + return -EMSGSIZE; +- return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, +- ffo); ++ return nla_put_sint(msg, ++ DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, ++ ffo.ffo); + } + + static int dpll_msg_add_measured_freq(struct sk_buff *msg, struct dpll_pin *pin, +@@ -686,6 +689,10 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin, + if (ret) + goto nest_cancel; + ret = dpll_msg_add_phase_offset(msg, pin, ref, extack); ++ if (ret) ++ goto nest_cancel; ++ ret = dpll_msg_add_ffo(msg, pin, ref, ++ DPLL_FFO_PIN_DEVICE, extack); + if (ret) + goto nest_cancel; + nla_nest_end(msg, attr); +@@ -748,7 +755,8 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin, + ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack); + if (ret) + return ret; +- ret = dpll_msg_add_ffo(msg, pin, ref, extack); ++ ret = dpll_msg_add_ffo(msg, pin, ref, ++ DPLL_FFO_PORT_RXTX_RATE, extack); + if (ret) + return ret; + ret = dpll_msg_add_measured_freq(msg, pin, ref, extack); +diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c +index 6439884..268999d 100644 +--- a/drivers/dpll/dpll_nl.c ++++ b/drivers/dpll/dpll_nl.c +@@ -18,6 +18,8 @@ const struct nla_policy dpll_pin_parent_device_nl_policy[DPLL_A_PIN_OPERSTATE + + [DPLL_A_PIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 3), + [DPLL_A_PIN_OPERSTATE] = NLA_POLICY_RANGE(NLA_U32, 1, 4), + [DPLL_A_PIN_PHASE_OFFSET] = { .type = NLA_S64, }, ++ [DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET] = { .type = NLA_SINT, }, ++ [DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT] = { .type = NLA_SINT, }, + }; + + const struct nla_policy dpll_pin_parent_pin_nl_policy[DPLL_A_PIN_STATE + 1] = { +diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c +index 2c8bd21..b159dff 100644 +--- a/drivers/dpll/zl3073x/dpll.c ++++ b/drivers/dpll/zl3073x/dpll.c +@@ -295,11 +295,12 @@ zl3073x_dpll_input_pin_ref_sync_set(const struct dpll_pin *dpll_pin, + static int + zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv, + const struct dpll_device *dpll, void *dpll_priv, +- s64 *ffo, struct netlink_ext_ack *extack) ++ struct dpll_ffo_param *ffo, ++ struct netlink_ext_ack *extack) + { + struct zl3073x_dpll_pin *pin = pin_priv; + +- *ffo = pin->freq_offset; ++ ffo->ffo = pin->freq_offset; + + return 0; + } +@@ -1274,6 +1275,7 @@ zl3073x_dpll_freq_monitor_set(const struct dpll_device *dpll, + } + + static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = { ++ .supported_ffo = BIT(DPLL_FFO_PORT_RXTX_RATE), + .direction_get = zl3073x_dpll_pin_direction_get, + .esync_get = zl3073x_dpll_input_pin_esync_get, + .esync_set = zl3073x_dpll_input_pin_esync_set, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +index 3981dd8..3756c02 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +@@ -300,7 +300,8 @@ static int mlx5_dpll_state_on_dpll_set(const struct dpll_pin *pin, + + static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv, + const struct dpll_device *dpll, void *dpll_priv, +- s64 *ffo, struct netlink_ext_ack *extack) ++ struct dpll_ffo_param *ffo, ++ struct netlink_ext_ack *extack) + { + struct mlx5_dpll_synce_status synce_status; + struct mlx5_dpll *mdpll = pin_priv; +@@ -309,10 +310,11 @@ static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv, + err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status); + if (err) + return err; +- return mlx5_dpll_pin_ffo_get(&synce_status, ffo); ++ return mlx5_dpll_pin_ffo_get(&synce_status, &ffo->ffo); + } + + static const struct dpll_pin_ops mlx5_dpll_pins_ops = { ++ .supported_ffo = BIT(DPLL_FFO_PORT_RXTX_RATE), + .direction_get = mlx5_dpll_pin_direction_get, + .state_on_dpll_get = mlx5_dpll_state_on_dpll_get, + .state_on_dpll_set = mlx5_dpll_state_on_dpll_set, +diff --git a/include/linux/dpll.h b/include/linux/dpll.h +index c5e333a..4a8854a 100644 +--- a/include/linux/dpll.h ++++ b/include/linux/dpll.h +@@ -71,6 +71,22 @@ struct dpll_device_ops { + RH_KABI_RESERVE(10) + }; + ++enum dpll_ffo_type { ++ DPLL_FFO_PORT_RXTX_RATE, ++ DPLL_FFO_PIN_DEVICE, ++ ++ __DPLL_FFO_TYPE_MAX, ++}; ++ ++/* RHEL: we have to keep 'ffo' field to be first to preserve compatibility ++ * with older .ffo_get() callbacks that accepts 's64 *' as parameter instead ++ * of 'struct dpll_ffo_param *' ++ */ ++struct dpll_ffo_param { ++ s64 ffo; ++ enum dpll_ffo_type type; ++}; ++ + struct dpll_pin_ops { + int (*frequency_set)(const struct dpll_pin *pin, void *pin_priv, + const struct dpll_device *dpll, void *dpll_priv, +@@ -96,12 +112,6 @@ struct dpll_pin_ops { + const struct dpll_device *dpll, + void *dpll_priv, enum dpll_pin_state *state, + struct netlink_ext_ack *extack); +- int (*operstate_on_dpll_get)(const struct dpll_pin *pin, +- void *pin_priv, +- const struct dpll_device *dpll, +- void *dpll_priv, +- enum dpll_pin_operstate *operstate, +- struct netlink_ext_ack *extack); + int (*state_on_pin_set)(const struct dpll_pin *pin, void *pin_priv, + const struct dpll_pin *parent_pin, + void *parent_pin_priv, +@@ -130,9 +140,13 @@ struct dpll_pin_ops { + const struct dpll_device *dpll, void *dpll_priv, + const s32 phase_adjust, + struct netlink_ext_ack *extack); +- int (*ffo_get)(const struct dpll_pin *pin, void *pin_priv, ++ RH_KABI_REPLACE(int (*ffo_get)(const struct dpll_pin *pin, void *pin_priv, + const struct dpll_device *dpll, void *dpll_priv, +- s64 *ffo, struct netlink_ext_ack *extack); ++ s64 *ffo, struct netlink_ext_ack *extack), ++ int (*ffo_get)(const struct dpll_pin *pin, void *pin_priv, ++ const struct dpll_device *dpll, void *dpll_priv, ++ struct dpll_ffo_param *ffo, ++ struct netlink_ext_ack *extack)) + int (*esync_set)(const struct dpll_pin *pin, void *pin_priv, + const struct dpll_device *dpll, void *dpll_priv, + u64 freq, struct netlink_ext_ack *extack); +@@ -155,8 +169,13 @@ struct dpll_pin_ops { + const struct dpll_device *dpll, + void *dpll_priv, u64 *measured_freq, + struct netlink_ext_ack *extack)) +- RH_KABI_RESERVE(2) +- RH_KABI_RESERVE(3) ++ RH_KABI_USE(2, int (*operstate_on_dpll_get)(const struct dpll_pin *pin, ++ void *pin_priv, ++ const struct dpll_device *dpll, ++ void *dpll_priv, ++ enum dpll_pin_operstate *operstate, ++ struct netlink_ext_ack *extack)) ++ RH_KABI_USE(3, unsigned long supported_ffo) + RH_KABI_RESERVE(4) + RH_KABI_RESERVE(5) + RH_KABI_RESERVE(6) diff --git a/SOURCES/1291-dpll-zl3073x-report-ffo-as-dpll-vs-input-reference-offset.patch b/SOURCES/1291-dpll-zl3073x-report-ffo-as-dpll-vs-input-reference-offset.patch new file mode 100644 index 000000000..40d929bda --- /dev/null +++ b/SOURCES/1291-dpll-zl3073x-report-ffo-as-dpll-vs-input-reference-offset.patch @@ -0,0 +1,347 @@ +From 54e65df8cf18a741745645aed7ae91514d437b43 Mon Sep 17 00:00:00 2001 +From: Ivan Vecera +Date: Mon, 11 May 2026 17:58:16 +0200 +Subject: [PATCH] dpll: zl3073x: report FFO as DPLL vs input reference offset + +Replace the per-reference frequency offset measurement (which was +redundant with measured-frequency) with a direct read of the DPLL's +delta frequency offset vs its tracked input reference. + +The new implementation uses the dpll_df_offset_x register with +ref_ofst=1 via the dpll_df_read_x semaphore mechanism. This +provides 2^-48 resolution (~3.5 fE) and reports the actual +frequency difference between the DPLL and its active input. + +Switch supported_ffo from DPLL_FFO_PORT_RXTX_RATE to +DPLL_FFO_PIN_DEVICE so FFO is reported only in the per-parent +context for the active input pin. + +Use atomic64_t for freq_offset to prevent torn reads on 32-bit +architectures between the periodic worker and netlink callbacks. + +Rewrite ffo_check to compare the cached df_offset converted to PPT +instead of using the old per-reference measurement. Remove the +ref_ffo_update periodic measurement and the ref ffo field since +they are no longer needed. + +Changes v3 -> v4: +- Switch to DPLL_FFO_PIN_DEVICE, remove dpll=NULL guard +- Use atomic64_t for freq_offset (torn read on 32-bit) + +Reviewed-by: Petr Oros +Signed-off-by: Ivan Vecera +Link: https://patch.msgid.link/20260511155816.99936-3-ivecera@redhat.com +Signed-off-by: Jakub Kicinski + +diff --git a/drivers/dpll/zl3073x/chan.c b/drivers/dpll/zl3073x/chan.c +index 2f48ca2..2fe3c3d 100644 +--- a/drivers/dpll/zl3073x/chan.c ++++ b/drivers/dpll/zl3073x/chan.c +@@ -18,6 +18,7 @@ + int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index) + { + struct zl3073x_chan *chan = &zldev->chan[index]; ++ u64 val; + int rc; + + rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MON_STATUS(index), +@@ -25,8 +26,34 @@ int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index) + if (rc) + return rc; + +- return zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index), +- &chan->refsel_status); ++ rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index), ++ &chan->refsel_status); ++ if (rc) ++ return rc; ++ ++ /* Read df_offset vs tracked reference */ ++ rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index), ++ ZL_DPLL_DF_READ_SEM); ++ if (rc) ++ return rc; ++ ++ rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_DF_READ(index), ++ ZL_DPLL_DF_READ_SEM | ZL_DPLL_DF_READ_REF_OFST); ++ if (rc) ++ return rc; ++ ++ rc = zl3073x_poll_zero_u8(zldev, ZL_REG_DPLL_DF_READ(index), ++ ZL_DPLL_DF_READ_SEM); ++ if (rc) ++ return rc; ++ ++ rc = zl3073x_read_u48(zldev, ZL_REG_DPLL_DF_OFFSET(index), &val); ++ if (rc) ++ return rc; ++ ++ chan->df_offset = sign_extend64(val, 47); ++ ++ return 0; + } + + /** +diff --git a/drivers/dpll/zl3073x/chan.h b/drivers/dpll/zl3073x/chan.h +index 481da21..4353809 100644 +--- a/drivers/dpll/zl3073x/chan.h ++++ b/drivers/dpll/zl3073x/chan.h +@@ -17,6 +17,7 @@ struct zl3073x_dev; + * @ref_prio: reference priority registers (4 bits per ref, P/N packed) + * @mon_status: monitor status register value + * @refsel_status: reference selection status register value ++ * @df_offset: frequency offset vs tracked reference in 2^-48 steps + */ + struct zl3073x_chan { + struct_group(cfg, +@@ -26,6 +27,7 @@ struct zl3073x_chan { + struct_group(stat, + u8 mon_status; + u8 refsel_status; ++ s64 df_offset; + ); + }; + +@@ -37,6 +39,18 @@ int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index, + + int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index); + ++/** ++ * zl3073x_chan_df_offset_get - get cached df_offset vs tracked reference ++ * @chan: pointer to channel state ++ * ++ * Return: frequency offset in 2^-48 steps ++ */ ++static inline s64 ++zl3073x_chan_df_offset_get(const struct zl3073x_chan *chan) ++{ ++ return chan->df_offset; ++} ++ + /** + * zl3073x_chan_mode_get - get DPLL channel operating mode + * @chan: pointer to channel state +diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c +index 024f0a2..7d2ad4b 100644 +--- a/drivers/dpll/zl3073x/core.c ++++ b/drivers/dpll/zl3073x/core.c +@@ -704,44 +704,6 @@ zl3073x_ref_freq_meas_update(struct zl3073x_dev *zldev) + return 0; + } + +-/** +- * zl3073x_ref_ffo_update - update reference fractional frequency offsets +- * @zldev: pointer to zl3073x_dev structure +- * +- * The function asks device to latch the latest measured fractional +- * frequency offset values, reads and stores them into the ref state. +- * +- * Return: 0 on success, <0 on error +- */ +-static int +-zl3073x_ref_ffo_update(struct zl3073x_dev *zldev) +-{ +- int i, rc; +- +- rc = zl3073x_ref_freq_meas_latch(zldev, +- ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF); +- if (rc) +- return rc; +- +- /* Read DPLL-to-REFx frequency offset measurements */ +- for (i = 0; i < ZL3073X_NUM_REFS; i++) { +- s32 value; +- +- /* Read value stored in units of 2^-32 signed */ +- rc = zl3073x_read_u32(zldev, ZL_REG_REF_FREQ(i), &value); +- if (rc) +- return rc; +- +- /* Convert to ppt +- * ffo = (10^12 * value) / 2^32 +- * ffo = ( 5^12 * value) / 2^20 +- */ +- zldev->ref[i].ffo = mul_s64_u64_shr(value, 244140625, 20); +- } +- +- return 0; +-} +- + static void + zl3073x_dev_periodic_work(struct kthread_work *work) + { +@@ -776,13 +738,6 @@ zl3073x_dev_periodic_work(struct kthread_work *work) + } + } + +- /* Update references' fractional frequency offsets */ +- rc = zl3073x_ref_ffo_update(zldev); +- if (rc) +- dev_warn(zldev->dev, +- "Failed to update fractional frequency offsets: %pe\n", +- ERR_PTR(rc)); +- + list_for_each_entry(zldpll, &zldev->dplls, list) + zl3073x_dpll_changes_check(zldpll); + +diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c +index b159dff..6b714ec 100644 +--- a/drivers/dpll/zl3073x/dpll.c ++++ b/drivers/dpll/zl3073x/dpll.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + ++#include + #include + #include + #include +@@ -57,7 +58,7 @@ struct zl3073x_dpll_pin { + s32 phase_gran; + enum dpll_pin_operstate operstate; + s64 phase_offset; +- s64 freq_offset; ++ atomic64_t freq_offset; + u32 measured_freq; + }; + +@@ -300,7 +301,10 @@ zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv, + { + struct zl3073x_dpll_pin *pin = pin_priv; + +- ffo->ffo = pin->freq_offset; ++ if (pin->operstate != DPLL_PIN_OPERSTATE_ACTIVE) ++ return -ENODATA; ++ ++ ffo->ffo = atomic64_read(&pin->freq_offset); + + return 0; + } +@@ -1275,7 +1279,7 @@ zl3073x_dpll_freq_monitor_set(const struct dpll_device *dpll, + } + + static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = { +- .supported_ffo = BIT(DPLL_FFO_PORT_RXTX_RATE), ++ .supported_ffo = BIT(DPLL_FFO_PIN_DEVICE), + .direction_get = zl3073x_dpll_pin_direction_get, + .esync_get = zl3073x_dpll_input_pin_esync_get, + .esync_set = zl3073x_dpll_input_pin_esync_set, +@@ -1731,37 +1735,29 @@ zl3073x_dpll_pin_phase_offset_check(struct zl3073x_dpll_pin *pin) + } + + /** +- * zl3073x_dpll_pin_ffo_check - check for pin fractional frequency offset change ++ * zl3073x_dpll_pin_ffo_check - check for FFO change on active pin + * @pin: pin to check + * +- * Check for the given pin's fractional frequency change. +- * +- * Return: true on fractional frequency offset change, false otherwise ++ * Return: true on change, false otherwise + */ + static bool + zl3073x_dpll_pin_ffo_check(struct zl3073x_dpll_pin *pin) + { + struct zl3073x_dpll *zldpll = pin->dpll; + struct zl3073x_dev *zldev = zldpll->dev; +- const struct zl3073x_ref *ref; +- u8 ref_id; ++ const struct zl3073x_chan *chan; + s64 ffo; + +- /* Get reference monitor status */ +- ref_id = zl3073x_input_pin_ref_get(pin->id); +- ref = zl3073x_ref_state_get(zldev, ref_id); +- +- /* Do not report ffo changes if the reference monitor report errors */ +- if (!zl3073x_ref_is_status_ok(ref)) ++ if (pin->operstate != DPLL_PIN_OPERSTATE_ACTIVE) + return false; + +- /* Compare with previous value */ +- ffo = zl3073x_ref_ffo_get(ref); +- if (pin->freq_offset != ffo) { +- dev_dbg(zldev->dev, "%s freq offset changed: %lld -> %lld\n", +- pin->label, pin->freq_offset, ffo); +- pin->freq_offset = ffo; ++ chan = zl3073x_chan_state_get(zldpll->dev, zldpll->id); ++ ffo = mul_s64_u64_shr(zl3073x_chan_df_offset_get(chan), ++ 244140625, 36); + ++ if (atomic64_xchg(&pin->freq_offset, ffo) != ffo) { ++ dev_dbg(zldev->dev, "%s freq offset changed to: %lld\n", ++ pin->label, ffo); + return true; + } + +diff --git a/drivers/dpll/zl3073x/ref.h b/drivers/dpll/zl3073x/ref.h +index 55e80e4..e140ca3 100644 +--- a/drivers/dpll/zl3073x/ref.h ++++ b/drivers/dpll/zl3073x/ref.h +@@ -22,7 +22,6 @@ struct zl3073x_dev; + * @freq_ratio_n: FEC mode divisor + * @sync_ctrl: reference sync control + * @config: reference config +- * @ffo: current fractional frequency offset + * @meas_freq: measured input frequency in Hz + * @mon_status: reference monitor status + */ +@@ -40,7 +39,6 @@ struct zl3073x_ref { + u8 config; + ); + struct_group(stat, /* Status */ +- s64 ffo; + u32 meas_freq; + u8 mon_status; + ); +@@ -58,18 +56,6 @@ int zl3073x_ref_state_update(struct zl3073x_dev *zldev, u8 index); + + int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); + +-/** +- * zl3073x_ref_ffo_get - get current fractional frequency offset +- * @ref: pointer to ref state +- * +- * Return: the latest measured fractional frequency offset +- */ +-static inline s64 +-zl3073x_ref_ffo_get(const struct zl3073x_ref *ref) +-{ +- return ref->ffo; +-} +- + /** + * zl3073x_ref_meas_freq_get - get measured input frequency + * @ref: pointer to ref state +diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h +index 8015808..9578f00 100644 +--- a/drivers/dpll/zl3073x/regs.h ++++ b/drivers/dpll/zl3073x/regs.h +@@ -164,6 +164,11 @@ + #define ZL_DPLL_MODE_REFSEL_MODE_NCO 4 + #define ZL_DPLL_MODE_REFSEL_REF GENMASK(7, 4) + ++#define ZL_REG_DPLL_DF_READ(_idx) \ ++ ZL_REG_IDX(_idx, 5, 0x28, 1, ZL3073X_MAX_CHANNELS, 1) ++#define ZL_DPLL_DF_READ_SEM BIT(4) ++#define ZL_DPLL_DF_READ_REF_OFST BIT(3) ++ + #define ZL_REG_DPLL_MEAS_CTRL ZL_REG(5, 0x50, 1) + #define ZL_DPLL_MEAS_CTRL_EN BIT(0) + #define ZL_DPLL_MEAS_CTRL_AVG_FACTOR GENMASK(7, 4) +@@ -176,6 +181,16 @@ + #define ZL_REG_DPLL_PHASE_ERR_DATA(_idx) \ + ZL_REG_IDX(_idx, 5, 0x55, 6, ZL3073X_MAX_CHANNELS, 6) + ++/******************************* ++ * Register Pages 6-7, DPLL Data ++ *******************************/ ++ ++#define ZL_REG_DPLL_DF_OFFSET_03(_idx) \ ++ ZL_REG_IDX(_idx, 6, 0x00, 6, 4, 0x20) ++#define ZL_REG_DPLL_DF_OFFSET_4 ZL_REG(7, 0x00, 6) ++#define ZL_REG_DPLL_DF_OFFSET(_idx) \ ++ ((_idx) < 4 ? ZL_REG_DPLL_DF_OFFSET_03(_idx) : ZL_REG_DPLL_DF_OFFSET_4) ++ + /*********************************** + * Register Page 9, Synth and Output + ***********************************/ diff --git a/SOURCES/1292-mptcp-fix-slab-use-after-free-in-inet-lookup-established.patch b/SOURCES/1292-mptcp-fix-slab-use-after-free-in-inet-lookup-established.patch new file mode 100644 index 000000000..82947162c --- /dev/null +++ b/SOURCES/1292-mptcp-fix-slab-use-after-free-in-inet-lookup-established.patch @@ -0,0 +1,100 @@ +From f6e1f25fa5e733570f6d6fe37a4dfed2a0deba47 Mon Sep 17 00:00:00 2001 +From: Jiayuan Chen +Date: Mon, 6 Apr 2026 11:15:10 +0800 +Subject: [PATCH] mptcp: fix slab-use-after-free in __inet_lookup_established + +commit 9b55b253907e7431210483519c5ad711a37dafa1 upstream. + +The ehash table lookups are lockless and rely on +SLAB_TYPESAFE_BY_RCU to guarantee socket memory stability +during RCU read-side critical sections. Both tcp_prot and +tcpv6_prot have their slab caches created with this flag +via proto_register(). + +However, MPTCP's mptcp_subflow_init() copies tcpv6_prot into +tcpv6_prot_override during inet_init() (fs_initcall, level 5), +before inet6_init() (module_init/device_initcall, level 6) has +called proto_register(&tcpv6_prot). At that point, +tcpv6_prot.slab is still NULL, so tcpv6_prot_override.slab +remains NULL permanently. + +This causes MPTCP v6 subflow child sockets to be allocated via +kmalloc (falling into kmalloc-4k) instead of the TCPv6 slab +cache. The kmalloc-4k cache lacks SLAB_TYPESAFE_BY_RCU, so +when these sockets are freed without SOCK_RCU_FREE (which is +cleared for child sockets by design), the memory can be +immediately reused. Concurrent ehash lookups under +rcu_read_lock can then access freed memory, triggering a +slab-use-after-free in __inet_lookup_established. + +Fix this by splitting the IPv6-specific initialization out of +mptcp_subflow_init() into a new mptcp_subflow_v6_init(), called +from mptcp_proto_v6_init() before protocol registration. This +ensures tcpv6_prot_override.slab correctly inherits the +SLAB_TYPESAFE_BY_RCU slab cache. + +Fixes: b19bc2945b40 ("mptcp: implement delegated actions") +Cc: stable@vger.kernel.org +Signed-off-by: Jiayuan Chen +Reviewed-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260406031512.189159-1-jiayuan.chen@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index fae51f3..a8d345c 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -4248,6 +4248,8 @@ int __init mptcp_proto_v6_init(void) + { + int err; + ++ mptcp_subflow_v6_init(); ++ + mptcp_v6_prot = mptcp_prot; + strscpy(mptcp_v6_prot.name, "MPTCPv6", sizeof(mptcp_v6_prot.name)); + mptcp_v6_prot.slab = NULL; +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index fc9ad56..161ed3c 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -794,6 +794,7 @@ static inline void mptcp_subflow_tcp_fallback(struct sock *sk, + void __init mptcp_proto_init(void); + #if IS_ENABLED(CONFIG_MPTCP_IPV6) + int __init mptcp_proto_v6_init(void); ++void __init mptcp_subflow_v6_init(void); + #endif + + struct sock *mptcp_sk_clone_init(const struct sock *sk, +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index a37c9cb..b6cd4d5 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -2103,7 +2103,15 @@ void __init mptcp_subflow_init(void) + tcp_prot_override.release_cb = tcp_release_cb_override; + tcp_prot_override.diag_destroy = tcp_abort_override; + ++ mptcp_diag_subflow_init(&subflow_ulp_ops); ++ ++ if (tcp_register_ulp(&subflow_ulp_ops) != 0) ++ panic("MPTCP: failed to register subflows to ULP\n"); ++} ++ + #if IS_ENABLED(CONFIG_MPTCP_IPV6) ++void __init mptcp_subflow_v6_init(void) ++{ + /* In struct mptcp_subflow_request_sock, we assume the TCP request sock + * structures for v4 and v6 have the same size. It should not changed in + * the future but better to make sure to be warned if it is no longer +@@ -2139,10 +2147,5 @@ void __init mptcp_subflow_init(void) + tcpv6_prot_override = tcpv6_prot; + tcpv6_prot_override.release_cb = tcp_release_cb_override; + tcpv6_prot_override.diag_destroy = tcp_abort_override; +-#endif +- +- mptcp_diag_subflow_init(&subflow_ulp_ops); +- +- if (tcp_register_ulp(&subflow_ulp_ops) != 0) +- panic("MPTCP: failed to register subflows to ULP\n"); + } ++#endif diff --git a/SOURCES/1293-ice-fix-null-pointer-dereference-in-ice-vsi-set-napi-queues.patch b/SOURCES/1293-ice-fix-null-pointer-dereference-in-ice-vsi-set-napi-queues.patch new file mode 100644 index 000000000..bece3cfff --- /dev/null +++ b/SOURCES/1293-ice-fix-null-pointer-dereference-in-ice-vsi-set-napi-queues.patch @@ -0,0 +1,95 @@ +From 6985e4baf50b86327426ca5d5cf4787ac165aacd Mon Sep 17 00:00:00 2001 +From: CKI Backport Bot +Date: Thu, 23 Apr 2026 22:42:57 +0000 +Subject: [PATCH] ice: Fix NULL pointer dereference in ice_vsi_set_napi_queues + +JIRA: https://redhat.atlassian.net/browse/RHEL-99101 + +commit 9bb30be4d89ff9a8d7ab1aa0eb2edaca83431f85 +Author: Aaron Ma +Date: Thu Dec 25 14:21:21 2025 +0800 + + ice: Fix NULL pointer dereference in ice_vsi_set_napi_queues + + Add NULL pointer checks in ice_vsi_set_napi_queues() to prevent crashes + during resume from suspend when rings[q_idx]->q_vector is NULL. + + Tested adaptor: + 60:00.0 Ethernet controller [0200]: Intel Corporation Ethernet Controller E810-XXV for SFP [8086:159b] (rev 02) + Subsystem: Intel Corporation Ethernet Network Adapter E810-XXV-2 [8086:4003] + + SR-IOV state: both disabled and enabled can reproduce this issue. + + kernel version: v6.18 + + Reproduce steps: + Boot up and execute suspend like systemctl suspend or rtcwake. + + Log: + <1>[ 231.443607] BUG: kernel NULL pointer dereference, address: 0000000000000040 + <1>[ 231.444052] #PF: supervisor read access in kernel mode + <1>[ 231.444484] #PF: error_code(0x0000) - not-present page + <6>[ 231.444913] PGD 0 P4D 0 + <4>[ 231.445342] Oops: Oops: 0000 [#1] SMP NOPTI + <4>[ 231.446635] RIP: 0010:netif_queue_set_napi+0xa/0x170 + <4>[ 231.447067] Code: 31 f6 31 ff c3 cc cc cc cc 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 48 85 c9 74 0b <48> 83 79 30 00 0f 84 39 01 00 00 55 41 89 d1 49 89 f8 89 f2 48 89 + <4>[ 231.447513] RSP: 0018:ffffcc780fc078c0 EFLAGS: 00010202 + <4>[ 231.447961] RAX: ffff8b848ca30400 RBX: ffff8b848caf2028 RCX: 0000000000000010 + <4>[ 231.448443] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8b848dbd4000 + <4>[ 231.448896] RBP: ffffcc780fc078e8 R08: 0000000000000000 R09: 0000000000000000 + <4>[ 231.449345] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001 + <4>[ 231.449817] R13: ffff8b848dbd4000 R14: ffff8b84833390c8 R15: 0000000000000000 + <4>[ 231.450265] FS: 00007c7b29e9d740(0000) GS:ffff8b8c068e2000(0000) knlGS:0000000000000000 + <4>[ 231.450715] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + <4>[ 231.451179] CR2: 0000000000000040 CR3: 000000030626f004 CR4: 0000000000f72ef0 + <4>[ 231.451629] PKRU: 55555554 + <4>[ 231.452076] Call Trace: + <4>[ 231.452549] + <4>[ 231.452996] ? ice_vsi_set_napi_queues+0x4d/0x110 [ice] + <4>[ 231.453482] ice_resume+0xfd/0x220 [ice] + <4>[ 231.453977] ? __pfx_pci_pm_resume+0x10/0x10 + <4>[ 231.454425] pci_pm_resume+0x8c/0x140 + <4>[ 231.454872] ? __pfx_pci_pm_resume+0x10/0x10 + <4>[ 231.455347] dpm_run_callback+0x5f/0x160 + <4>[ 231.455796] ? dpm_wait_for_superior+0x107/0x170 + <4>[ 231.456244] device_resume+0x177/0x270 + <4>[ 231.456708] dpm_resume+0x209/0x2f0 + <4>[ 231.457151] dpm_resume_end+0x15/0x30 + <4>[ 231.457596] suspend_devices_and_enter+0x1da/0x2b0 + <4>[ 231.458054] enter_state+0x10e/0x570 + + Add defensive checks for both the ring pointer and its q_vector + before dereferencing, allowing the system to resume successfully even when + q_vectors are unmapped. + + Fixes: 2a5dc090b92cf ("ice: move netif_queue_set_napi to rtnl-protected sections") + Reviewed-by: Aleksandr Loktionov + Signed-off-by: Aaron Ma + Reviewed-by: Paul Menzel + Signed-off-by: Tony Nguyen + +Signed-off-by: CKI Backport Bot + +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 72c91bd..60b32b4 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -2789,12 +2789,14 @@ void ice_vsi_set_napi_queues(struct ice_vsi *vsi) + + ASSERT_RTNL(); + ice_for_each_rxq(vsi, q_idx) +- netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_RX, +- &vsi->rx_rings[q_idx]->q_vector->napi); ++ if (vsi->rx_rings[q_idx] && vsi->rx_rings[q_idx]->q_vector) ++ netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_RX, ++ &vsi->rx_rings[q_idx]->q_vector->napi); + + ice_for_each_txq(vsi, q_idx) +- netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_TX, +- &vsi->tx_rings[q_idx]->q_vector->napi); ++ if (vsi->tx_rings[q_idx] && vsi->tx_rings[q_idx]->q_vector) ++ netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_TX, ++ &vsi->tx_rings[q_idx]->q_vector->napi); + /* Also set the interrupt number for the NAPI */ + ice_for_each_q_vector(vsi, v_idx) { + struct ice_q_vector *q_vector = vsi->q_vectors[v_idx]; diff --git a/SOURCES/1294-bluetooth-hci-event-fix-potential-uaf-in-ssp-passkey-handler.patch b/SOURCES/1294-bluetooth-hci-event-fix-potential-uaf-in-ssp-passkey-handler.patch new file mode 100644 index 000000000..eb9557b76 --- /dev/null +++ b/SOURCES/1294-bluetooth-hci-event-fix-potential-uaf-in-ssp-passkey-handler.patch @@ -0,0 +1,89 @@ +From d28311539ac9f65e29308ea219ecaa48aa5e76e5 Mon Sep 17 00:00:00 2001 +From: Shuvam Pandey +Date: Fri, 8 May 2026 21:33:20 -0400 +Subject: [PATCH] Bluetooth: hci_event: fix potential UAF in SSP passkey + handlers + +[ Upstream commit 85fa3512048793076eef658f66489112dcc91993 ] + +hci_conn lookup and field access must be covered by hdev lock in +hci_user_passkey_notify_evt() and hci_keypress_notify_evt(), otherwise +the connection can be freed concurrently. + +Extend the hci_dev_lock critical section to cover all conn usage in both +handlers. + +Keep the existing keypress notification behavior unchanged by routing +the early exits through a common unlock path. + +Fixes: 92a25256f142 ("Bluetooth: mgmt: Implement support for passkey notification") +Cc: stable@vger.kernel.org +Signed-off-by: Shuvam Pandey +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index f5054bb..262a918 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -5418,9 +5418,11 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data, + + bt_dev_dbg(hdev, ""); + ++ hci_dev_lock(hdev); ++ + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (!conn) +- return; ++ goto unlock; + + conn->passkey_notify = __le32_to_cpu(ev->passkey); + conn->passkey_entered = 0; +@@ -5429,6 +5431,9 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data, + mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, + conn->dst_type, conn->passkey_notify, + conn->passkey_entered); ++ ++unlock: ++ hci_dev_unlock(hdev); + } + + static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data, +@@ -5439,14 +5444,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data, + + bt_dev_dbg(hdev, ""); + ++ hci_dev_lock(hdev); ++ + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (!conn) +- return; ++ goto unlock; + + switch (ev->type) { + case HCI_KEYPRESS_STARTED: + conn->passkey_entered = 0; +- return; ++ goto unlock; + + case HCI_KEYPRESS_ENTERED: + conn->passkey_entered++; +@@ -5461,13 +5468,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data, + break; + + case HCI_KEYPRESS_COMPLETED: +- return; ++ goto unlock; + } + + if (hci_dev_test_flag(hdev, HCI_MGMT)) + mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, + conn->dst_type, conn->passkey_notify, + conn->passkey_entered); ++ ++unlock: ++ hci_dev_unlock(hdev); + } + + static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data, diff --git a/SOURCES/1295-wifi-mac80211-use-safe-list-iteration-in-radar-detect-work.patch b/SOURCES/1295-wifi-mac80211-use-safe-list-iteration-in-radar-detect-work.patch new file mode 100644 index 000000000..ed2216c4f --- /dev/null +++ b/SOURCES/1295-wifi-mac80211-use-safe-list-iteration-in-radar-detect-work.patch @@ -0,0 +1,33 @@ +From ac8eb3e18f41e2cc8492cc1d358bcb786c850270 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Tue, 5 May 2026 15:15:40 +0200 +Subject: [PATCH] wifi: mac80211: use safe list iteration in radar detect work + +The call to ieee80211_dfs_cac_cancel can cause the iterated chanctx to +be freed and removed from the list. Guard against this to avoid a +slab-use-after-free error. + +Cc: stable@vger.kernel.org +Fixes: bca8bc0399ac ("wifi: mac80211: handle ieee80211_radar_detected() for MLO") +Signed-off-by: Benjamin Berg +Link: https://patch.msgid.link/20260505151539.236d63a1b736.I35dbb9e96a2d4a480be208770fdd99ba3b817b79@changeid +Signed-off-by: Johannes Berg + +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index c993153..62e1a37 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -3565,11 +3565,11 @@ void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy, + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, radar_detected_work); + struct cfg80211_chan_def chandef; +- struct ieee80211_chanctx *ctx; ++ struct ieee80211_chanctx *ctx, *tmp; + + lockdep_assert_wiphy(local->hw.wiphy); + +- list_for_each_entry(ctx, &local->chanctx_list, list) { ++ list_for_each_entry_safe(ctx, tmp, &local->chanctx_list, list) { + if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) + continue; + diff --git a/SOURCES/1296-wifi-mac80211-drop-stray-static-from-fast-rx-rx-result.patch b/SOURCES/1296-wifi-mac80211-drop-stray-static-from-fast-rx-rx-result.patch new file mode 100644 index 000000000..f38270f99 --- /dev/null +++ b/SOURCES/1296-wifi-mac80211-drop-stray-static-from-fast-rx-rx-result.patch @@ -0,0 +1,35 @@ +From 7a5b81e0c87a075afd572f659d8eb68c9c4cd2ba Mon Sep 17 00:00:00 2001 +From: Catherine +Date: Fri, 24 Apr 2026 21:14:36 +0800 +Subject: [PATCH] wifi: mac80211: drop stray 'static' from fast-RX rx_result + +ieee80211_invoke_fast_rx() is documented as safe for parallel RX, but +its per-invocation rx_result is declared static. Concurrent callers then +share one instance and can overwrite each other's result between +ieee80211_rx_mesh_data() and the switch on res. + +That can make a packet that was queued or consumed by +ieee80211_rx_mesh_data() fall through into ieee80211_rx_8023(), or make +a packet that should continue return as queued. + +Make res an automatic variable so each invocation keeps its own result. + +Fixes: 3468e1e0c639 ("wifi: mac80211: add mesh fast-rx support") +Cc: stable@vger.kernel.org +Signed-off-by: Catherine +Link: https://patch.msgid.link/20260424131435.83212-2-enderaoelyther@gmail.com +Signed-off-by: Johannes Berg + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 4e34435..02f1315 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4819,7 +4819,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, + struct sk_buff *skb = rx->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); +- static ieee80211_rx_result res; ++ ieee80211_rx_result res; + int orig_len = skb->len; + int hdrlen = ieee80211_hdrlen(hdr->frame_control); + int snap_offs = hdrlen; diff --git a/SOURCES/1297-rdma-mana-validate-rx-hash-key-len.patch b/SOURCES/1297-rdma-mana-validate-rx-hash-key-len.patch new file mode 100644 index 000000000..9f04228ad --- /dev/null +++ b/SOURCES/1297-rdma-mana-validate-rx-hash-key-len.patch @@ -0,0 +1,30 @@ +From 6dd2d4ad9c8429523b1c220c5132bd551c006425 Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Tue, 28 Apr 2026 13:17:37 -0300 +Subject: [PATCH] RDMA/mana: Validate rx_hash_key_len + +Sashiko points out that rx_hash_key_len comes from a uAPI structure and is +blindly passed to memcpy, allowing the userspace to trash kernel +memory. Bounds check it so the memcpy cannot overflow. + +Cc: stable@vger.kernel.org +Fixes: 0266a177631d ("RDMA/mana_ib: Add a driver for Microsoft Azure Network Adapter") +Link: https://sashiko.dev/#/patchset/0-v2-1c49eeb88c48%2B91-rdma_udata_rep_jgg%40nvidia.com?part=1 +Link: https://patch.msgid.link/r/4-v1-41f3135e5565+9d2-rdma_ai_fixes1_jgg@nvidia.com +Reviewed-by: Long Li +Signed-off-by: Jason Gunthorpe + +diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c +index 48c1f49..8eb956e 100644 +--- a/drivers/infiniband/hw/mana/qp.c ++++ b/drivers/infiniband/hw/mana/qp.c +@@ -21,6 +21,9 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev, + + gc = mdev_to_gc(dev); + ++ if (rx_hash_key_len > sizeof(req->hashkey)) ++ return -EINVAL; ++ + req_buf_size = struct_size(req, indir_tab, MANA_INDIRECT_TABLE_DEF_SIZE); + req = kzalloc(req_buf_size, GFP_KERNEL); + if (!req) diff --git a/SOURCES/1298-wifi-mac80211-remove-station-if-connection-prep-fails.patch b/SOURCES/1298-wifi-mac80211-remove-station-if-connection-prep-fails.patch new file mode 100644 index 000000000..9024721ad --- /dev/null +++ b/SOURCES/1298-wifi-mac80211-remove-station-if-connection-prep-fails.patch @@ -0,0 +1,56 @@ +From 283fc9e44ff5b5ac967439b4951b80bd4299f4e4 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 5 May 2026 15:15:34 +0200 +Subject: [PATCH] wifi: mac80211: remove station if connection prep fails + +If connection preparation fails for MLO connections, then the +interface is completely reset to non-MLD. In this case, we must +not keep the station since it's related to the link of the vif +being removed. Delete an existing station. Any "new_sta" is +already being removed, so that doesn't need changes. + +This fixes a use-after-free/double-free in debugfs if that's +enabled, because a vif going from MLD (and to MLD, but that's +not relevant here) recreates its entire debugfs. + +Cc: stable@vger.kernel.org +Fixes: 81151ce462e5 ("wifi: mac80211: support MLO authentication/association with one link") +Reviewed-by: Miriam Rachel Korenblit +Link: https://patch.msgid.link/20260505151533.c4e52deb06ad.Iafe56cec7de8512626169496b134bce3a6c17010@changeid +Signed-off-by: Johannes Berg + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e185f2a..7ba68a0 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -8890,7 +8890,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, + struct ieee80211_bss *bss = (void *)cbss->priv; + struct sta_info *new_sta = NULL; + struct ieee80211_link_data *link; +- bool have_sta = false; ++ struct sta_info *have_sta = NULL; + bool mlo; + int err; + u16 new_links; +@@ -8909,11 +8909,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, + mlo = false; + } + +- if (assoc) { +- rcu_read_lock(); ++ if (assoc) + have_sta = sta_info_get(sdata, ap_mld_addr); +- rcu_read_unlock(); +- } + + if (mlo && !have_sta && + WARN_ON(sdata->vif.valid_links || sdata->vif.active_links)) +@@ -9072,6 +9069,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, + out_release_chan: + ieee80211_link_release_channel(link); + out_err: ++ if (mlo && have_sta) ++ WARN_ON(__sta_info_destroy(have_sta)); + ieee80211_vif_set_links(sdata, 0, 0); + return err; + } diff --git a/SOURCES/1299-bnxt-en-fix-rss-context-delete-logic.patch b/SOURCES/1299-bnxt-en-fix-rss-context-delete-logic.patch new file mode 100644 index 000000000..8e6362aab --- /dev/null +++ b/SOURCES/1299-bnxt-en-fix-rss-context-delete-logic.patch @@ -0,0 +1,57 @@ +From e123d9302d223767bd910bfbcfe607bae909f8ac Mon Sep 17 00:00:00 2001 +From: Pavan Chebbi +Date: Thu, 19 Feb 2026 10:53:11 -0800 +Subject: [PATCH] bnxt_en: Fix RSS context delete logic + +We need to free the corresponding RSS context VNIC +in FW everytime an RSS context is deleted in driver. +Commit 667ac333dbb7 added a check to delete the VNIC +in FW only when netif_running() is true to help delete +RSS contexts with interface down. + +Having that condition will make the driver leak VNICs +in FW whenever close() happens with active RSS contexts. +On the subsequent open(), as part of RSS context restoration, +we will end up trying to create extra VNICs for which we +did not make any reservation. FW can fail this request, +thereby making us lose active RSS contexts. + +Suppose an RSS context is deleted already and we try to +process a delete request again, then the HWRM functions +will check for validity of the request and they simply +return if the resource is already freed. So, even for +delete-when-down cases, netif_running() check is not +necessary. + +Remove the netif_running() condition check when deleting +an RSS context. + +Reported-by: Jakub Kicinski +Fixes: 667ac333dbb7 ("eth: bnxt: allow deleting RSS contexts when the device is down") +Reviewed-by: Andy Gospodarek +Signed-off-by: Pavan Chebbi +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20260219185313.2682148-2-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 3177d4b..a178578 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -10731,12 +10731,10 @@ void bnxt_del_one_rss_ctx(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx, + struct bnxt_ntuple_filter *ntp_fltr; + int i; + +- if (netif_running(bp->dev)) { +- bnxt_hwrm_vnic_free_one(bp, &rss_ctx->vnic); +- for (i = 0; i < BNXT_MAX_CTX_PER_VNIC; i++) { +- if (vnic->fw_rss_cos_lb_ctx[i] != INVALID_HW_RING_ID) +- bnxt_hwrm_vnic_ctx_free_one(bp, vnic, i); +- } ++ bnxt_hwrm_vnic_free_one(bp, &rss_ctx->vnic); ++ for (i = 0; i < BNXT_MAX_CTX_PER_VNIC; i++) { ++ if (vnic->fw_rss_cos_lb_ctx[i] != INVALID_HW_RING_ID) ++ bnxt_hwrm_vnic_ctx_free_one(bp, vnic, i); + } + if (!all) + return; diff --git a/SOURCES/1300-gfs2-add-metapath-dibh-helper.patch b/SOURCES/1300-gfs2-add-metapath-dibh-helper.patch new file mode 100644 index 000000000..8302dadca --- /dev/null +++ b/SOURCES/1300-gfs2-add-metapath-dibh-helper.patch @@ -0,0 +1,40 @@ +From 602fb357b195d846887987a68024330a593ab1b9 Mon Sep 17 00:00:00 2001 +From: Andreas Gruenbacher +Date: Fri, 20 Oct 2023 01:32:15 +0200 +Subject: [PATCH] gfs2: Add metapath_dibh helper + +[ Upstream commit 92099f0c92270c8c7a79e6bc6e0312ad248ea331 ] + +Add a metapath_dibh() helper for extracting the inode's buffer head from +a metapath. + +Signed-off-by: Andreas Gruenbacher +Stable-dep-of: faddeb848305 ("gfs2: Fix use-after-free in iomap inline data write path") +Signed-off-by: Sasha Levin + +diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c +index 66e5fd0..f19f031 100644 +--- a/fs/gfs2/bmap.c ++++ b/fs/gfs2/bmap.c +@@ -317,6 +317,12 @@ static void gfs2_metapath_ra(struct gfs2_glock *gl, __be64 *start, __be64 *end) + } + } + ++static inline struct buffer_head * ++metapath_dibh(struct metapath *mp) ++{ ++ return mp->mp_bh[0]; ++} ++ + static int __fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, + unsigned int x, unsigned int h) + { +@@ -661,7 +667,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, + { + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_sbd *sdp = GFS2_SB(inode); +- struct buffer_head *dibh = mp->mp_bh[0]; ++ struct buffer_head *dibh = metapath_dibh(mp); + u64 bn; + unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0; + size_t dblks = iomap->length >> inode->i_blkbits; diff --git a/SOURCES/1301-gfs2-fix-use-after-free-in-iomap-inline-data-write-path.patch b/SOURCES/1301-gfs2-fix-use-after-free-in-iomap-inline-data-write-path.patch new file mode 100644 index 000000000..2adde52c6 --- /dev/null +++ b/SOURCES/1301-gfs2-fix-use-after-free-in-iomap-inline-data-write-path.patch @@ -0,0 +1,76 @@ +From 1cae1bafdf9caa9b462b19af06b1a06902e4e142 Mon Sep 17 00:00:00 2001 +From: Deepanshu Kartikey +Date: Fri, 30 Jan 2026 14:51:34 +0530 +Subject: [PATCH] gfs2: Fix use-after-free in iomap inline data write path + +[ Upstream commit faddeb848305e79db89ee0479bb0e33380656321 ] + +The inline data buffer head (dibh) is being released prematurely in +gfs2_iomap_begin() via release_metapath() while iomap->inline_data +still points to dibh->b_data. This causes a use-after-free when +iomap_write_end_inline() later attempts to write to the inline data +area. + +The bug sequence: +1. gfs2_iomap_begin() calls gfs2_meta_inode_buffer() to read inode + metadata into dibh +2. Sets iomap->inline_data = dibh->b_data + sizeof(struct gfs2_dinode) +3. Calls release_metapath() which calls brelse(dibh), dropping refcount + to 0 +4. kswapd reclaims the page (~39ms later in the syzbot report) +5. iomap_write_end_inline() tries to memcpy() to iomap->inline_data +6. KASAN detects use-after-free write to freed memory + +Fix by storing dibh in iomap->private and incrementing its refcount +with get_bh() in gfs2_iomap_begin(). The buffer is then properly +released in gfs2_iomap_end() after the inline write completes, +ensuring the page stays alive for the entire iomap operation. + +Note: A C reproducer is not available for this issue. The fix is based +on analysis of the KASAN report and code review showing the buffer head +is freed before use. + +[agruenba: Take buffer head reference in gfs2_iomap_begin() to avoid +leaks in gfs2_iomap_get() and gfs2_iomap_alloc().] + +Reported-by: syzbot+ea1cd4aa4d1e98458a55@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=ea1cd4aa4d1e98458a55 +Fixes: d0a22a4b03b8 ("gfs2: Fix iomap write page reclaim deadlock") +Signed-off-by: Deepanshu Kartikey +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Sasha Levin + +diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c +index f19f031..05f348c 100644 +--- a/fs/gfs2/bmap.c ++++ b/fs/gfs2/bmap.c +@@ -1122,10 +1122,18 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, + goto out_unlock; + break; + default: +- goto out_unlock; ++ goto out; + } + + ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp); ++ if (ret) ++ goto out_unlock; ++ ++out: ++ if (iomap->type == IOMAP_INLINE) { ++ iomap->private = metapath_dibh(&mp); ++ get_bh(iomap->private); ++ } + + out_unlock: + release_metapath(&mp); +@@ -1139,6 +1147,9 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length, + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_sbd *sdp = GFS2_SB(inode); + ++ if (iomap->private) ++ brelse(iomap->private); ++ + switch (flags & (IOMAP_WRITE | IOMAP_ZERO)) { + case IOMAP_WRITE: + if (flags & IOMAP_DIRECT) diff --git a/SOURCES/1302-s390-ap-expose-ap-bindings-complete-count-counter-via-sysfs.patch b/SOURCES/1302-s390-ap-expose-ap-bindings-complete-count-counter-via-sysfs.patch new file mode 100644 index 000000000..10eb740f5 --- /dev/null +++ b/SOURCES/1302-s390-ap-expose-ap-bindings-complete-count-counter-via-sysfs.patch @@ -0,0 +1,64 @@ +From ed98cf22bd574bbcd5906e0ee217dfe65f5f8c8a Mon Sep 17 00:00:00 2001 +From: Mete Durlu +Date: Fri, 13 Mar 2026 16:09:40 +0100 +Subject: [PATCH] s390/ap: Expose ap_bindings_complete_count counter via sysfs + +JIRA: https://issues.redhat.com/browse/RHEL-155897 + +commit 51d921a613b1e89a47c2c262bbef1d7b0b032ac7 +Author: Harald Freudenberger +Date: Fri Oct 17 16:51:52 2025 +0200 + + s390/ap: Expose ap_bindings_complete_count counter via sysfs + + The AP bus udev event BINDINGS=complete is sent out when the + first time all devices detected by the AP bus scan have been + bound to device drivers. This is the ideal time to for example + change the AP bus masks apmask and aqmask to re-establish a + persistent change on the decision about which cards/domains + should be available for the host and which should go into the + pool for kvm guests. + + However, if exactly this initial udev event is sent out early + in the boot process a udev rule may not have been established + yet and thus this event will never be recognized. To have + some indication about if the AP bus binding complete has + already happened, the internal ap_bindings_complete_count + counter is exposed via sysfs with this patch. + + Suggested-by: Matthew Rosato + Signed-off-by: Harald Freudenberger + Tested-by: Matthew Rosato + Signed-off-by: Heiko Carstens + +Signed-off-by: Harald Freudenberger +Signed-off-by: Mete Durlu + +diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c +index de8a250..48ffeaf 100644 +--- a/drivers/s390/crypto/ap_bus.c ++++ b/drivers/s390/crypto/ap_bus.c +@@ -1585,6 +1585,15 @@ static ssize_t bindings_show(const struct bus_type *bus, char *buf) + + static BUS_ATTR_RO(bindings); + ++static ssize_t bindings_complete_count_show(const struct bus_type *bus, ++ char *buf) ++{ ++ return sysfs_emit(buf, "%llu\n", ++ atomic64_read(&ap_bindings_complete_count)); ++} ++ ++static BUS_ATTR_RO(bindings_complete_count); ++ + static ssize_t features_show(const struct bus_type *bus, char *buf) + { + int n = 0; +@@ -1625,6 +1634,7 @@ static struct attribute *ap_bus_attrs[] = { + &bus_attr_aqmask.attr, + &bus_attr_scans.attr, + &bus_attr_bindings.attr, ++ &bus_attr_bindings_complete_count.attr, + &bus_attr_features.attr, + NULL, + }; diff --git a/SOURCES/1303-ibmveth-disable-gso-for-packets-with-small-mss.patch b/SOURCES/1303-ibmveth-disable-gso-for-packets-with-small-mss.patch new file mode 100644 index 000000000..ee26fea14 --- /dev/null +++ b/SOURCES/1303-ibmveth-disable-gso-for-packets-with-small-mss.patch @@ -0,0 +1,104 @@ +From cd82512d5e7852beab3b8cb254c60b061fc549ac Mon Sep 17 00:00:00 2001 +From: Mamatha Inamdar +Date: Thu, 30 Apr 2026 20:30:14 -0400 +Subject: [PATCH] ibmveth: Disable GSO for packets with small MSS + +JIRA: https://issues.redhat.com/browse/RHEL-164873 + +commit cc427d24ac6442ffdeafd157a63c7c5b73ed4de4 +Author: Mingming Cao +Date: Fri Apr 24 09:29:17 2026 -0700 + + ibmveth: Disable GSO for packets with small MSS + + Some physical adapters on Power systems do not support segmentation + offload when the MSS is less than 224 bytes. Attempting to send such + packets causes the adapter to freeze, stopping all traffic until + manually reset. + + Implement ndo_features_check to disable GSO for packets with small MSS + values. The network stack will perform software segmentation instead. + + The 224-byte minimum matches ibmvnic + commit ("ibmvnic: Enforce stronger sanity checks + on GSO packets") + which uses the same physical adapters in SEA configurations. + + The issue occurs specifically when the hardware attempts to perform + segmentation (gso_segs > 1) with a small MSS. Single-segment GSO packets + (gso_segs == 1) do not trigger the problematic LSO code path and are + transmitted normally without segmentation. + + Add an ndo_features_check callback to disable GSO when MSS < 224 bytes. + Also call vlan_features_check() to ensure proper handling of VLAN packets, + particularly QinQ (802.1ad) configurations where the hardware parser may + not support certain offload features. + + Validated using iptables to force small MSS values. Without the fix, + the adapter freezes. With the fix, packets are segmented in software + and transmission succeeds. Comprehensive regression testing completedd + (MSS tests, performance, stability). + + Fixes: 8641dd85799f ("ibmveth: Add support for TSO") + Cc: stable@vger.kernel.org + Reviewed-by: Brian King + Tested-by: Shaik Abdulla + Tested-by: Naveed Ahmed + Signed-off-by: Mingming Cao + Link: https://patch.msgid.link/20260424162917.65725-1-mmc@linux.ibm.com + Signed-off-by: Jakub Kicinski + +Signed-off-by: Mamatha Inamdar + +diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c +index 7f94e84..02a95cf 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -1756,6 +1756,27 @@ static int ibmveth_set_mac_addr(struct net_device *dev, void *p) + return 0; + } + ++static netdev_features_t ibmveth_features_check(struct sk_buff *skb, ++ struct net_device *dev, ++ netdev_features_t features) ++{ ++ /* Some physical adapters do not support segmentation offload with ++ * MSS < 224. Disable GSO for such packets to avoid adapter freeze. ++ * Note: Single-segment packets (gso_segs == 1) don't need this check ++ * as they bypass the LSO path and are transmitted without segmentation. ++ */ ++ if (skb_is_gso(skb)) { ++ if (skb_shinfo(skb)->gso_size < IBMVETH_MIN_LSO_MSS) { ++ netdev_warn_once(dev, ++ "MSS %u too small for LSO, disabling GSO\n", ++ skb_shinfo(skb)->gso_size); ++ features &= ~NETIF_F_GSO_MASK; ++ } ++ } ++ ++ return vlan_features_check(skb, features); ++} ++ + static const struct net_device_ops ibmveth_netdev_ops = { + .ndo_open = ibmveth_open, + .ndo_stop = ibmveth_close, +@@ -1767,6 +1788,7 @@ static const struct net_device_ops ibmveth_netdev_ops = { + .ndo_set_features = ibmveth_set_features, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = ibmveth_set_mac_addr, ++ .ndo_features_check = ibmveth_features_check, + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ibmveth_poll_controller, + #endif +diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h +index dc8aae1..059ca49 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.h ++++ b/drivers/net/ethernet/ibm/ibmveth.h +@@ -37,6 +37,7 @@ + #define IBMVETH_ILLAN_IPV4_TCP_CSUM 0x0000000000000002UL + #define IBMVETH_ILLAN_ACTIVE_TRUNK 0x0000000000000001UL + ++#define IBMVETH_MIN_LSO_MSS 224 /* Minimum MSS for LSO */ + /* hcall macros */ + #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ + plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac) diff --git a/SOURCES/1304-s390-mm-add-missing-secure-storage-access-fixups-for-donated.patch b/SOURCES/1304-s390-mm-add-missing-secure-storage-access-fixups-for-donated.patch new file mode 100644 index 000000000..54199c094 --- /dev/null +++ b/SOURCES/1304-s390-mm-add-missing-secure-storage-access-fixups-for-donated.patch @@ -0,0 +1,66 @@ +From 532af53c2c278d6a7197be0afd8b5d3839e686e3 Mon Sep 17 00:00:00 2001 +From: Mete Durlu +Date: Thu, 16 Apr 2026 18:10:09 +0200 +Subject: [PATCH] s390/mm: Add missing secure storage access fixups for donated + memory + +JIRA: https://redhat.atlassian.net/browse/RHEL-168793 +Conflicts: Conflicts due to rhel9 kernel version, no functional changes. + +commit b00be77302d7ec4ad0367bb236494fce7172b730 +Author: Janosch Frank +Date: Wed Mar 4 10:18:37 2026 +0000 + + s390/mm: Add missing secure storage access fixups for donated memory + + There are special cases where secure storage access exceptions happen + in a kernel context for pages that don't have the PG_arch_1 bit + set. That bit is set for non-exported guest secure storage (memory) + but is absent on storage donated to the Ultravisor since the kernel + isn't allowed to export donated pages. + + Prior to this patch we would try to export the page by calling + arch_make_folio_accessible() which would instantly return since the + arch bit is absent signifying that the page was already exported and + no further action is necessary. This leads to secure storage access + exception loops which can never be resolved. + + With this patch we unconditionally try to export and if that fails we + fixup. + + Fixes: 084ea4d611a3 ("s390/mm: add (non)secure page access exceptions handlers") + Reported-by: Heiko Carstens + Suggested-by: Heiko Carstens + Reviewed-by: Claudio Imbrenda + Tested-by: Christian Borntraeger + Signed-off-by: Janosch Frank + Signed-off-by: Christian Borntraeger + +Signed-off-by: Janosch Frank +Signed-off-by: Mete Durlu + +diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c +index 78adfec..1fb5815 100644 +--- a/arch/s390/mm/fault.c ++++ b/arch/s390/mm/fault.c +@@ -547,10 +547,18 @@ void do_secure_storage_access(struct pt_regs *regs) + page = phys_to_page(addr); + if (unlikely(!try_get_page(page))) + break; +- rc = arch_make_page_accessible(page); ++ ++ rc = uv_convert_from_secure(addr); ++ if (!rc) ++ clear_bit(PG_arch_1, &page->flags); + put_page(page); ++ /* ++ * There are some valid fixup types for kernel ++ * accesses to donated secure memory. zeropad is one ++ * of them. ++ */ + if (rc) +- BUG(); ++ return handle_fault_error_nolock(regs, 0); + break; + default: + unreachable(); diff --git a/SOURCES/1305-alsa-usb-audio-add-sanity-check-for-oob-writes-at-silencing.patch b/SOURCES/1305-alsa-usb-audio-add-sanity-check-for-oob-writes-at-silencing.patch new file mode 100644 index 000000000..22ae62c7a --- /dev/null +++ b/SOURCES/1305-alsa-usb-audio-add-sanity-check-for-oob-writes-at-silencing.patch @@ -0,0 +1,107 @@ +From 0a6ada5e5f985332a38b2ab39c21a5696a4cfdfb Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 23 Apr 2026 11:04:41 +0200 +Subject: [PATCH] ALSA: usb-audio: Add sanity check for OOB writes at silencing + +JIRA: https://issues.redhat.com/browse/RHEL-168091 + +commit fba2105a157fffcf19825e4eea498346738c9948 +Author: Takashi Iwai +Date: Mon Feb 16 15:12:07 2026 +0100 + + ALSA: usb-audio: Add sanity check for OOB writes at silencing + + At silencing the playback URB packets in the implicit fb mode before + the actual playback, we blindly assume that the received packets fit + with the buffer size. But when the setup in the capture stream + differs from the playback stream (e.g. due to the USB core limitation + of max packet size), such an inconsistency may lead to OOB writes to + the buffer, resulting in a crash. + + For addressing it, add a sanity check of the transfer buffer size at + prepare_silent_urb(), and stop the data copy if the received data + overflows. Also, report back the transfer error properly from there, + too. + + Note that this doesn't fix the root cause of the playback error + itself, but this merely covers the kernel Oops. + + Link: https://bugzilla.kernel.org/show_bug.cgi?id=221076 + Link: https://patch.msgid.link/20260216141209.1849200-4-tiwai@suse.de + Signed-off-by: Takashi Iwai + +Signed-off-by: Jaroslav Kysela + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index fc6c0cc..d30d1d4 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -275,8 +275,8 @@ static inline bool has_tx_length_quirk(struct snd_usb_audio *chip) + return chip->quirk_flags & QUIRK_FLAG_TX_LENGTH; + } + +-static void prepare_silent_urb(struct snd_usb_endpoint *ep, +- struct snd_urb_ctx *ctx) ++static int prepare_silent_urb(struct snd_usb_endpoint *ep, ++ struct snd_urb_ctx *ctx) + { + struct urb *urb = ctx->urb; + unsigned int offs = 0; +@@ -289,28 +289,34 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, + extra = sizeof(packet_length); + + for (i = 0; i < ctx->packets; ++i) { +- unsigned int offset; +- unsigned int length; +- int counts; +- +- counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); +- length = counts * ep->stride; /* number of silent bytes */ +- offset = offs * ep->stride + extra * i; +- urb->iso_frame_desc[i].offset = offset; ++ int length; ++ ++ length = snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); ++ if (length < 0) ++ return length; ++ length *= ep->stride; /* number of silent bytes */ ++ if (offs + length + extra > ctx->buffer_size) ++ break; ++ urb->iso_frame_desc[i].offset = offs; + urb->iso_frame_desc[i].length = length + extra; + if (extra) { + packet_length = cpu_to_le32(length); +- memcpy(urb->transfer_buffer + offset, ++ memcpy(urb->transfer_buffer + offs, + &packet_length, sizeof(packet_length)); ++ offs += extra; + } +- memset(urb->transfer_buffer + offset + extra, ++ memset(urb->transfer_buffer + offs, + ep->silence_value, length); +- offs += counts; ++ offs += length; + } + +- urb->number_of_packets = ctx->packets; +- urb->transfer_buffer_length = offs * ep->stride + ctx->packets * extra; ++ if (!offs) ++ return -EPIPE; ++ ++ urb->number_of_packets = i; ++ urb->transfer_buffer_length = offs; + ctx->queued = 0; ++ return 0; + } + + /* +@@ -332,8 +338,7 @@ static int prepare_outbound_urb(struct snd_usb_endpoint *ep, + if (data_subs && ep->prepare_data_urb) + return ep->prepare_data_urb(data_subs, urb, in_stream_lock); + /* no data provider, so send silence */ +- prepare_silent_urb(ep, ctx); +- break; ++ return prepare_silent_urb(ep, ctx); + + case SND_USB_ENDPOINT_TYPE_SYNC: + if (snd_usb_get_speed(ep->chip->dev) >= USB_SPEED_HIGH) { diff --git a/SOURCES/1306-exit-prevent-preemption-of-oopsing-task-dead-task.patch b/SOURCES/1306-exit-prevent-preemption-of-oopsing-task-dead-task.patch new file mode 100644 index 000000000..078b7935d --- /dev/null +++ b/SOURCES/1306-exit-prevent-preemption-of-oopsing-task-dead-task.patch @@ -0,0 +1,56 @@ +From 2f3e5b5a77374869a5c36c783c310be9c26493e0 Mon Sep 17 00:00:00 2001 +From: CKI Backport Bot +Date: Thu, 28 May 2026 15:18:57 +0000 +Subject: [PATCH] exit: prevent preemption of oopsing TASK_DEAD task + +JIRA: https://redhat.atlassian.net/browse/RHEL-180008 +CVE: CVE-2026-46173 +Backported from tree(s): linux + +commit c1fa0bb633e4a6b11e83ffc57fa5abe8ebb87891 +Author: Jann Horn +Date: Mon May 11 08:55:11 2026 -0700 + + exit: prevent preemption of oopsing TASK_DEAD task + + When an already-exiting task oopses, make_task_dead() currently calls + do_task_dead() with preemption enabled. That is forbidden: + do_task_dead() calls __schedule(), which has a comment saying "WARNING: + must be called with preemption disabled!". + + If an oopsing task is preempted in do_task_dead(), between becoming + TASK_DEAD and entering the scheduler explicitly, bad things happen: + finish_task_switch() assumes that once the scheduler has switched away + from a TASK_DEAD task, the task can never run again and its stack is no + longer needed; but that assumption apparently doesn't hold if the dead + task was preempted (the SM_PREEMPT case). + + This means that the scheduler ends up repeatedly dropping references on + the dead task's stack, which can lead to use-after-free or double-free + of the entire task stack; in other words, two tasks can end up running + on the same stack, resulting in various kinds of memory corruption. + + (This does not just affect "recursively oopsing" tasks; it is enough to + oops once during task exit, for example in a file_operations::release + handler) + + Fixes: 7f80a2fd7db9 ("exit: Stop poorly open coding do_task_dead in make_task_dead") + Cc: stable@kernel.org + Signed-off-by: Jann Horn + Acked-by: Peter Zijlstra + Signed-off-by: Linus Torvalds + +Signed-off-by: CKI Backport Bot + +diff --git a/kernel/exit.c b/kernel/exit.c +index aa08b46..6a1081a 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -959,6 +959,7 @@ void __noreturn make_task_dead(int signr) + futex_exit_recursive(tsk); + tsk->exit_state = EXIT_DEAD; + refcount_inc(&tsk->rcu_users); ++ preempt_disable(); + do_task_dead(); + } + diff --git a/SOURCES/1307-rdma-mana-remove-user-triggerable-warn-on-in-mana-ib-create-.patch b/SOURCES/1307-rdma-mana-remove-user-triggerable-warn-on-in-mana-ib-create-.patch new file mode 100644 index 000000000..e03ee2f1a --- /dev/null +++ b/SOURCES/1307-rdma-mana-remove-user-triggerable-warn-on-in-mana-ib-create-.patch @@ -0,0 +1,35 @@ +From 159f2efabc89d3f931d38f2d35876535d4abf0a3 Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Tue, 28 Apr 2026 13:17:38 -0300 +Subject: [PATCH] RDMA/mana: Remove user triggerable WARN_ON() in + mana_ib_create_qp_rss() + +Sashiko points out that the user can specify WQs sharing the same CQ as a +part of the uAPI and this will trigger the WARN_ON() then go on to corrupt +the kernel. + +Just reject it outright and fail the QP creation. + +Cc: stable@vger.kernel.org +Fixes: c15d7802a424 ("RDMA/mana_ib: Add CQ interrupt support for RAW QP") +Link: https://sashiko.dev/#/patchset/0-v2-1c49eeb88c48%2B91-rdma_udata_rep_jgg%40nvidia.com?part=1 +Link: https://patch.msgid.link/r/5-v1-41f3135e5565+9d2-rdma_ai_fixes1_jgg@nvidia.com +Reviewed-by: Long Li +Signed-off-by: Jason Gunthorpe + +diff --git a/drivers/infiniband/hw/mana/cq.c b/drivers/infiniband/hw/mana/cq.c +index 1becc87..e3c3c7e 100644 +--- a/drivers/infiniband/hw/mana/cq.c ++++ b/drivers/infiniband/hw/mana/cq.c +@@ -140,8 +140,9 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq) + + if (cq->queue.id >= gc->max_num_cqs) + return -EINVAL; +- /* Create CQ table entry */ +- WARN_ON(gc->cq_table[cq->queue.id]); ++ /* Create CQ table entry, sharing a CQ between WQs is not supported */ ++ if (gc->cq_table[cq->queue.id]) ++ return -EINVAL; + if (cq->queue.kmem) + gdma_cq = cq->queue.kmem; + else diff --git a/SOURCES/1308-nvmet-tcp-fix-race-between-icreq-handling-and-queue-teardown.patch b/SOURCES/1308-nvmet-tcp-fix-race-between-icreq-handling-and-queue-teardown.patch new file mode 100644 index 000000000..6e75ad667 --- /dev/null +++ b/SOURCES/1308-nvmet-tcp-fix-race-between-icreq-handling-and-queue-teardown.patch @@ -0,0 +1,94 @@ +From 5293a8882c549fab4a878bc76b0b6c951f980a61 Mon Sep 17 00:00:00 2001 +From: Chaitanya Kulkarni +Date: Wed, 8 Apr 2026 00:51:31 -0700 +Subject: [PATCH] nvmet-tcp: fix race between ICReq handling and queue teardown + +nvmet_tcp_handle_icreq() updates queue->state after sending an +Initialization Connection Response (ICResp), but it does so without +serializing against target-side queue teardown. + +If an NVMe/TCP host sends an Initialization Connection Request +(ICReq) and immediately closes the connection, target-side teardown +may start in softirq context before io_work drains the already +buffered ICReq. In that case, nvmet_tcp_schedule_release_queue() +sets queue->state to NVMET_TCP_Q_DISCONNECTING and drops the queue +reference under state_lock. + +If io_work later processes that ICReq, nvmet_tcp_handle_icreq() can +still overwrite the state back to NVMET_TCP_Q_LIVE. That defeats the +DISCONNECTING-state guard in nvmet_tcp_schedule_release_queue() and +allows a later socket state change to re-enter teardown and issue a +second kref_put() on an already released queue. + +The ICResp send failure path has the same problem. If teardown has +already moved the queue to DISCONNECTING, a send error can still +overwrite the state with NVMET_TCP_Q_FAILED, again reopening the +window for a second teardown path to drop the queue reference. + +Fix this by serializing both post-send state transitions with +state_lock and bailing out if teardown has already started. + +Use -ESHUTDOWN as an internal sentinel for that bail-out path rather +than propagating it as a transport error like -ECONNRESET. Keep +nvmet_tcp_socket_error() setting rcv_state to NVMET_TCP_RECV_ERR before +honoring that sentinel so receive-side parsing stays quiesced until the +existing release path completes. + +Fixes: c46a6465bac2 ("nvmet-tcp: add NVMe over TCP target driver") +Cc: stable@vger.kernel.org +Reported-by: Shivam Kumar +Tested-by: Shivam Kumar +Signed-off-by: Chaitanya Kulkarni +Signed-off-by: Keith Busch + +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index f899bf6..515df00 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -390,6 +390,19 @@ static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue) + + static void nvmet_tcp_socket_error(struct nvmet_tcp_queue *queue, int status) + { ++ /* ++ * Keep rcv_state at RECV_ERR even for the internal -ESHUTDOWN path. ++ * nvmet_tcp_handle_icreq() can return -ESHUTDOWN after the ICReq has ++ * already been consumed and queue teardown has started. ++ * ++ * If nvmet_tcp_data_ready() or nvmet_tcp_write_space() queues ++ * nvmet_tcp_io_work() again before nvmet_tcp_release_queue_work() ++ * cancels it, the queue must not keep that old receive state. ++ * Otherwise the next nvmet_tcp_io_work() run can reach ++ * nvmet_tcp_done_recv_pdu() and try to handle the same ICReq again. ++ * ++ * That is why queue->rcv_state needs to be updated before we return. ++ */ + queue->rcv_state = NVMET_TCP_RECV_ERR; + if (status == -EPIPE || status == -ECONNRESET) + kernel_sock_shutdown(queue->sock, SHUT_RDWR); +@@ -893,10 +906,25 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue) + iov.iov_base = icresp; + iov.iov_len = sizeof(*icresp); + ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len); +- if (ret < 0) ++ if (ret < 0) { ++ spin_lock_bh(&queue->state_lock); ++ if (queue->state == NVMET_TCP_Q_DISCONNECTING) { ++ spin_unlock_bh(&queue->state_lock); ++ return -ESHUTDOWN; ++ } ++ queue->state = NVMET_TCP_Q_FAILED; ++ spin_unlock_bh(&queue->state_lock); + return ret; /* queue removal will cleanup */ ++ } + ++ spin_lock_bh(&queue->state_lock); ++ if (queue->state == NVMET_TCP_Q_DISCONNECTING) { ++ spin_unlock_bh(&queue->state_lock); ++ /* Tell nvmet_tcp_socket_error() teardown is in progress. */ ++ return -ESHUTDOWN; ++ } + queue->state = NVMET_TCP_Q_LIVE; ++ spin_unlock_bh(&queue->state_lock); + nvmet_prepare_receive_pdu(queue); + return 0; + } diff --git a/SOURCES/1309-scsi-qla2xxx-completely-fix-fcport-double-free.patch b/SOURCES/1309-scsi-qla2xxx-completely-fix-fcport-double-free.patch new file mode 100644 index 000000000..ff863739a --- /dev/null +++ b/SOURCES/1309-scsi-qla2xxx-completely-fix-fcport-double-free.patch @@ -0,0 +1,39 @@ +From c0b7da13a04bd70ef6070bfb9ea85f582294560a Mon Sep 17 00:00:00 2001 +From: Vladimir Riabchun +Date: Tue, 10 Feb 2026 11:08:22 +0100 +Subject: [PATCH] scsi: qla2xxx: Completely fix fcport double free + +In qla24xx_els_dcmd_iocb() sp->free is set to qla2x00_els_dcmd_sp_free(). +When an error happens, this function is called by qla2x00_sp_release(), +when kref_put() releases the first and the last reference. + +qla2x00_els_dcmd_sp_free() frees fcport by calling qla2x00_free_fcport(). +Doing it one more time after kref_put() is a bad idea. + +Fixes: 82f522ae0d97 ("scsi: qla2xxx: Fix double free of fcport") +Fixes: 4895009c4bb7 ("scsi: qla2xxx: Prevent command send on chip reset") +Signed-off-by: Vladimir Riabchun +Signed-off-by: Farhat Abbas +Link: https://patch.msgid.link/aYsDln9NFQQsPDgg@vova-pc +Signed-off-by: Martin K. Petersen + +diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c +index 0b41e8a..faec66b 100644 +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -2751,7 +2751,6 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, + if (!elsio->u.els_logo.els_logo_pyld) { + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); +- qla2x00_free_fcport(fcport); + return QLA_FUNCTION_FAILED; + } + +@@ -2776,7 +2775,6 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, + if (rval != QLA_SUCCESS) { + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); +- qla2x00_free_fcport(fcport); + return QLA_FUNCTION_FAILED; + } + diff --git a/SOURCES/1310-rbd-eliminate-a-race-in-lock-dwork-draining-on-unmap.patch b/SOURCES/1310-rbd-eliminate-a-race-in-lock-dwork-draining-on-unmap.patch new file mode 100644 index 000000000..991e9a9be --- /dev/null +++ b/SOURCES/1310-rbd-eliminate-a-race-in-lock-dwork-draining-on-unmap.patch @@ -0,0 +1,106 @@ +From 8bf586044031efd9d9883a8b63a4eb28b111fa8f Mon Sep 17 00:00:00 2001 +From: CKI Backport Bot +Date: Thu, 28 May 2026 19:40:07 +0000 +Subject: [PATCH] rbd: eliminate a race in lock_dwork draining on unmap + +JIRA: https://redhat.atlassian.net/browse/RHEL-180190 +Backported from tree(s): linux + +commit 9fc75b71fdd38465c76c6f6a884cdd4ae3c72d90 +Author: Ilya Dryomov +Date: Tue May 19 23:07:26 2026 +0200 + + rbd: eliminate a race in lock_dwork draining on unmap + + Given how rbd_lock_add_request() and rbd_img_exclusive_lock() are + written, lock_dwork may be (re)queued more than it's actually needed: + for example in case a new I/O request comes in while we are in the + middle of rbd_acquire_lock() on behalf of another I/O request. This is + expected and with rbd_release_lock() preemptively canceling lock_dwork + is benign under normal operation. + + A more problematic example is maybe_kick_acquire(): + + if (have_requests || delayed_work_pending(&rbd_dev->lock_dwork)) { + dout("%s rbd_dev %p kicking lock_dwork\n", __func__, rbd_dev); + mod_delayed_work(rbd_dev->task_wq, &rbd_dev->lock_dwork, 0); + } + + It's not unrealistic for lock_dwork to get canceled right after + delayed_work_pending() returns true and for mod_delayed_work() to + requeue it right there anyway. This is a classic TOCTOU race. + + When it comes to unmapping the image, there is an implicit assumption + of no self-initiated exclusive lock activity past the point of return + from rbd_dev_image_unlock() which unlocks the lock if it happens to be + held. This unlock is assumed to be final and lock_dwork (as well as + all other exclusive lock tasks, really) isn't expected to get queued + again. However, lock_dwork is canceled only in cancel_tasks_sync() + (i.e. later in the unmap sequence) and on top of that the cancellation + can get in effect nullified by maybe_kick_acquire(). This may result + in rbd_acquire_lock() executing after rbd_dev_device_release() and + rbd_dev_image_release() run and free and/or reset a bunch of things. + One of the possible failure modes then is a violated + + rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); + + in rbd_dev_header_info() which is called via rbd_dev_refresh() from + rbd_post_acquire_action(). + + Redo exclusive lock task draining to provide saner semantics and try + to meet the assumptions around rbd_dev_image_unlock(). + + Cc: stable@vger.kernel.org + Signed-off-by: Ilya Dryomov + Reviewed-by: Viacheslav Dubeyko + +Signed-off-by: CKI Backport Bot + +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index c82ec46..bfa3bae 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -4547,24 +4547,12 @@ static int rbd_register_watch(struct rbd_device *rbd_dev) + return ret; + } + +-static void cancel_tasks_sync(struct rbd_device *rbd_dev) +-{ +- dout("%s rbd_dev %p\n", __func__, rbd_dev); +- +- cancel_work_sync(&rbd_dev->acquired_lock_work); +- cancel_work_sync(&rbd_dev->released_lock_work); +- cancel_delayed_work_sync(&rbd_dev->lock_dwork); +- cancel_work_sync(&rbd_dev->unlock_work); +-} +- + /* + * header_rwsem must not be held to avoid a deadlock with + * rbd_dev_refresh() when flushing notifies. + */ + static void rbd_unregister_watch(struct rbd_device *rbd_dev) + { +- cancel_tasks_sync(rbd_dev); +- + mutex_lock(&rbd_dev->watch_mutex); + if (rbd_dev->watch_state == RBD_WATCH_STATE_REGISTERED) + __rbd_unregister_watch(rbd_dev); +@@ -6541,10 +6529,18 @@ static int rbd_add_parse_args(const char *buf, + + static void rbd_dev_image_unlock(struct rbd_device *rbd_dev) + { ++ dout("%s rbd_dev %p\n", __func__, rbd_dev); ++ ++ disable_delayed_work_sync(&rbd_dev->lock_dwork); ++ disable_work_sync(&rbd_dev->unlock_work); ++ + down_write(&rbd_dev->lock_rwsem); + if (__rbd_is_lock_owner(rbd_dev)) + __rbd_release_lock(rbd_dev); + up_write(&rbd_dev->lock_rwsem); ++ ++ flush_work(&rbd_dev->acquired_lock_work); ++ flush_work(&rbd_dev->released_lock_work); + } + + /* diff --git a/SOURCES/1311-net-sched-fix-pedit-partial-cow-leading-to-page-cache-corrup.patch b/SOURCES/1311-net-sched-fix-pedit-partial-cow-leading-to-page-cache-corrup.patch new file mode 100644 index 000000000..637016ac4 --- /dev/null +++ b/SOURCES/1311-net-sched-fix-pedit-partial-cow-leading-to-page-cache-corrup.patch @@ -0,0 +1,224 @@ +From 899ee91156e57784090c5565e4f31bd7dbffbc5a Mon Sep 17 00:00:00 2001 +From: Rajat Gupta +Date: Sun, 31 May 2026 08:32:21 -0400 +Subject: [PATCH] net/sched: fix pedit partial COW leading to page cache + corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +tcf_pedit_act() computes the COW range for skb_ensure_writable() +once before the key loop using tcfp_off_max_hint, but the hint does +not account for the runtime header offset added by typed keys. This +can leave part of the write region un-COW'd. + +Fix by moving skb_ensure_writable() inside the per-key loop where +the actual write offset is known, and add overflow checking on the +offset arithmetic. For negative offsets (e.g. Ethernet header edits +at ingress), use skb_cow() to COW the headroom instead. Guard +offset_valid() against INT_MIN, where negation is undefined. + +Fixes: 8b796475fd78 ("net/sched: act_pedit: really ensure the skb is writable") +Reported-by: Yiming Qian +Reported-by: Keenan Dong +Reported-by: Han Guidong <2045gemini@gmail.com> +Reported-by: Zhang Cen +Reviewed-by: Han Guidong <2045gemini@gmail.com> +Tested-by: Han Guidong <2045gemini@gmail.com> +Reviewed-by: Davide Caratti +Tested-by: Davide Caratti +Reviewed-by: Toke Høiland-Jørgensen +Tested-by: Toke Høiland-Jørgensen +Reviewed-by: Victor Nogueira +Tested-by: Victor Nogueira +Acked-by: Jamal Hadi Salim +Signed-off-by: Rajat Gupta +Link: https://patch.msgid.link/20260531123221.48732-1-jhs@mojatatu.com +Signed-off-by: Jakub Kicinski + +diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h +index 83fe399..a26d4cd 100644 +--- a/include/net/tc_act/tc_pedit.h ++++ b/include/net/tc_act/tc_pedit.h +@@ -14,7 +14,6 @@ struct tcf_pedit_key_ex { + struct tcf_pedit_parms { + struct tc_pedit_key *tcfp_keys; + struct tcf_pedit_key_ex *tcfp_keys_ex; +- u32 tcfp_off_max_hint; + unsigned char tcfp_nkeys; + unsigned char tcfp_flags; + struct rcu_head rcu; +diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c +index fc0a35a..495cc56 100644 +--- a/net/sched/act_pedit.c ++++ b/net/sched/act_pedit.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -24,6 +25,7 @@ + #include + #include + #include ++#include + + static struct tc_action_ops act_pedit_ops; + +@@ -242,7 +244,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, + goto out_free_ex; + } + +- nparms->tcfp_off_max_hint = 0; + nparms->tcfp_flags = parm->flags; + nparms->tcfp_nkeys = parm->nkeys; + +@@ -268,14 +269,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, + BITS_PER_TYPE(int) - 1, + nparms->tcfp_keys[i].shift); + +- /* The AT option can read a single byte, we can bound the actual +- * value with uchar max. +- */ +- cur += (0xff & offmask) >> nparms->tcfp_keys[i].shift; +- +- /* Each key touches 4 bytes starting from the computed offset */ +- nparms->tcfp_off_max_hint = +- max(nparms->tcfp_off_max_hint, cur + 4); + } + + p = to_pedit(*a); +@@ -318,15 +311,12 @@ static void tcf_pedit_cleanup(struct tc_action *a) + call_rcu(&parms->rcu, tcf_pedit_cleanup_rcu); + } + +-static bool offset_valid(struct sk_buff *skb, int offset) ++static bool offset_valid(struct sk_buff *skb, int offset, int len) + { +- if (offset > 0 && offset > skb->len) +- return false; +- +- if (offset < 0 && -offset > skb_headroom(skb)) ++ if (offset < -(int)skb_headroom(skb)) + return false; + +- return true; ++ return offset <= (int)skb->len - len; + } + + static int pedit_l4_skb_offset(struct sk_buff *skb, int *hoffset, const int header_type) +@@ -393,18 +383,10 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb, + struct tcf_pedit_key_ex *tkey_ex; + struct tcf_pedit_parms *parms; + struct tc_pedit_key *tkey; +- u32 max_offset; + int i; + + parms = rcu_dereference_bh(p->parms); + +- max_offset = (skb_transport_header_was_set(skb) ? +- skb_transport_offset(skb) : +- skb_network_offset(skb)) + +- parms->tcfp_off_max_hint; +- if (skb_ensure_writable(skb, min(skb->len, max_offset))) +- goto done; +- + tcf_lastuse_update(&p->tcf_tm); + tcf_action_update_bstats(&p->common, skb); + +@@ -412,10 +394,11 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb, + tkey_ex = parms->tcfp_keys_ex; + + for (i = parms->tcfp_nkeys; i > 0; i--, tkey++) { ++ int write_offset, write_len; + int offset = tkey->off; + int hoffset = 0; +- u32 *ptr, hdata; +- u32 val; ++ u32 cur_val, val; ++ u32 *ptr; + int rc; + + if (tkey_ex) { +@@ -433,13 +416,15 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb, + + if (tkey->offmask) { + u8 *d, _d; ++ int at_offset; + +- if (!offset_valid(skb, hoffset + tkey->at)) { ++ if (check_add_overflow(hoffset, (int)tkey->at, &at_offset) || ++ !offset_valid(skb, at_offset, sizeof(_d))) { + pr_info_ratelimited("tc action pedit 'at' offset %d out of bounds\n", + hoffset + tkey->at); + goto bad; + } +- d = skb_header_pointer(skb, hoffset + tkey->at, ++ d = skb_header_pointer(skb, at_offset, + sizeof(_d), &_d); + if (!d) + goto bad; +@@ -451,31 +436,51 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb, + } + } + +- if (!offset_valid(skb, hoffset + offset)) { +- pr_info_ratelimited("tc action pedit offset %d out of bounds\n", hoffset + offset); ++ if (check_add_overflow(hoffset, offset, &write_offset)) { ++ pr_info_ratelimited("tc action pedit offset overflow\n"); + goto bad; + } + +- ptr = skb_header_pointer(skb, hoffset + offset, +- sizeof(hdata), &hdata); +- if (!ptr) ++ if (!offset_valid(skb, write_offset, sizeof(*ptr))) { ++ pr_info_ratelimited("tc action pedit offset %d out of bounds\n", ++ write_offset); + goto bad; ++ } ++ ++ if (write_offset < 0) { ++ if (skb_cow(skb, -write_offset)) ++ goto bad; ++ if (write_offset + (int)sizeof(*ptr) > 0) { ++ if (skb_ensure_writable(skb, ++ min_t(int, skb->len, ++ write_offset + (int)sizeof(*ptr)))) ++ goto bad; ++ } ++ } else { ++ if (check_add_overflow(write_offset, (int)sizeof(*ptr), ++ &write_len)) ++ goto bad; ++ if (skb_ensure_writable(skb, min_t(int, skb->len, ++ write_len))) ++ goto bad; ++ } ++ ++ ptr = (u32 *)(skb->data + write_offset); ++ cur_val = get_unaligned(ptr); + /* just do it, baby */ + switch (cmd) { + case TCA_PEDIT_KEY_EX_CMD_SET: + val = tkey->val; + break; + case TCA_PEDIT_KEY_EX_CMD_ADD: +- val = (*ptr + tkey->val) & ~tkey->mask; ++ val = (cur_val + tkey->val) & ~tkey->mask; + break; + default: + pr_info_ratelimited("tc action pedit bad command (%d)\n", cmd); + goto bad; + } + +- *ptr = ((*ptr & tkey->mask) ^ val); +- if (ptr == &hdata) +- skb_store_bits(skb, hoffset + offset, ptr, 4); ++ put_unaligned((cur_val & tkey->mask) ^ val, ptr); + } + + goto done; diff --git a/SPECS/kernel.spec b/SPECS/kernel.spec index 06f642988..ef3e48315 100644 --- a/SPECS/kernel.spec +++ b/SPECS/kernel.spec @@ -176,13 +176,13 @@ Summary: The Linux kernel # define buildid .local %define specversion 5.14.0 %define patchversion 5.14 -%define pkgrelease 687.15.1 +%define pkgrelease 687.17.1 %define kversion 5 %define tarfile_release 5.14.0-687.5.1.el9_8 # This is needed to do merge window version magic %define patchlevel 14 # This allows pkg_release to have configurable %%{?dist} tag -%define specrelease 687.15.1%{?buildid}%{?dist} +%define specrelease 687.17.1%{?buildid}%{?dist} # This defines the kabi tarball version %define kabiversion 5.14.0-687.5.1.el9_8 @@ -1162,6 +1162,33 @@ Patch1281: 1281-ipv6-rpl-headroom.patch Patch1282: 1282-rdma-mlx4-srq.patch Patch1283: 1283-dpll-series-RHEL.patch Patch1284: 1284-ice-rss-queues-RHEL.patch +Patch1285: 1285-xen-privcmd-fix-double-free-via-vma-splitting.patch +Patch1286: 1286-bluetooth-hci-sync-fix-stack-buffer-overflow-in-hci-le-big-c.patch +Patch1287: 1287-can-isotp-fix-tx-buf-use-after-free-in-isotp-sendmsg.patch +Patch1288: 1288-dpll-add-pin-operational-state.patch +Patch1289: 1289-dpll-zl3073x-implement-pin-operational-state-reporting.patch +Patch1290: 1290-dpll-add-fractional-frequency-offset-to-pin-parent-device.patch +Patch1291: 1291-dpll-zl3073x-report-ffo-as-dpll-vs-input-reference-offset.patch +Patch1292: 1292-mptcp-fix-slab-use-after-free-in-inet-lookup-established.patch +Patch1293: 1293-ice-fix-null-pointer-dereference-in-ice-vsi-set-napi-queues.patch +Patch1294: 1294-bluetooth-hci-event-fix-potential-uaf-in-ssp-passkey-handler.patch +Patch1295: 1295-wifi-mac80211-use-safe-list-iteration-in-radar-detect-work.patch +Patch1296: 1296-wifi-mac80211-drop-stray-static-from-fast-rx-rx-result.patch +Patch1297: 1297-rdma-mana-validate-rx-hash-key-len.patch +Patch1298: 1298-wifi-mac80211-remove-station-if-connection-prep-fails.patch +Patch1299: 1299-bnxt-en-fix-rss-context-delete-logic.patch +Patch1300: 1300-gfs2-add-metapath-dibh-helper.patch +Patch1301: 1301-gfs2-fix-use-after-free-in-iomap-inline-data-write-path.patch +Patch1302: 1302-s390-ap-expose-ap-bindings-complete-count-counter-via-sysfs.patch +Patch1303: 1303-ibmveth-disable-gso-for-packets-with-small-mss.patch +Patch1304: 1304-s390-mm-add-missing-secure-storage-access-fixups-for-donated.patch +Patch1305: 1305-alsa-usb-audio-add-sanity-check-for-oob-writes-at-silencing.patch +Patch1306: 1306-exit-prevent-preemption-of-oopsing-task-dead-task.patch +Patch1307: 1307-rdma-mana-remove-user-triggerable-warn-on-in-mana-ib-create-.patch +Patch1308: 1308-nvmet-tcp-fix-race-between-icreq-handling-and-queue-teardown.patch +Patch1309: 1309-scsi-qla2xxx-completely-fix-fcport-double-free.patch +Patch1310: 1310-rbd-eliminate-a-race-in-lock-dwork-draining-on-unmap.patch +Patch1311: 1311-net-sched-fix-pedit-partial-cow-leading-to-page-cache-corrup.patch # END OF PATCH DEFINITIONS %description @@ -2091,6 +2118,33 @@ ApplyPatch 1281-ipv6-rpl-headroom.patch ApplyPatch 1282-rdma-mlx4-srq.patch ApplyPatch 1283-dpll-series-RHEL.patch ApplyPatch 1284-ice-rss-queues-RHEL.patch +ApplyPatch 1285-xen-privcmd-fix-double-free-via-vma-splitting.patch +ApplyPatch 1286-bluetooth-hci-sync-fix-stack-buffer-overflow-in-hci-le-big-c.patch +ApplyPatch 1287-can-isotp-fix-tx-buf-use-after-free-in-isotp-sendmsg.patch +ApplyPatch 1288-dpll-add-pin-operational-state.patch +ApplyPatch 1289-dpll-zl3073x-implement-pin-operational-state-reporting.patch +ApplyPatch 1290-dpll-add-fractional-frequency-offset-to-pin-parent-device.patch +ApplyPatch 1291-dpll-zl3073x-report-ffo-as-dpll-vs-input-reference-offset.patch +ApplyPatch 1292-mptcp-fix-slab-use-after-free-in-inet-lookup-established.patch +ApplyPatch 1293-ice-fix-null-pointer-dereference-in-ice-vsi-set-napi-queues.patch +ApplyPatch 1294-bluetooth-hci-event-fix-potential-uaf-in-ssp-passkey-handler.patch +ApplyPatch 1295-wifi-mac80211-use-safe-list-iteration-in-radar-detect-work.patch +ApplyPatch 1296-wifi-mac80211-drop-stray-static-from-fast-rx-rx-result.patch +ApplyPatch 1297-rdma-mana-validate-rx-hash-key-len.patch +ApplyPatch 1298-wifi-mac80211-remove-station-if-connection-prep-fails.patch +ApplyPatch 1299-bnxt-en-fix-rss-context-delete-logic.patch +ApplyPatch 1300-gfs2-add-metapath-dibh-helper.patch +ApplyPatch 1301-gfs2-fix-use-after-free-in-iomap-inline-data-write-path.patch +ApplyPatch 1302-s390-ap-expose-ap-bindings-complete-count-counter-via-sysfs.patch +ApplyPatch 1303-ibmveth-disable-gso-for-packets-with-small-mss.patch +ApplyPatch 1304-s390-mm-add-missing-secure-storage-access-fixups-for-donated.patch +ApplyPatch 1305-alsa-usb-audio-add-sanity-check-for-oob-writes-at-silencing.patch +ApplyPatch 1306-exit-prevent-preemption-of-oopsing-task-dead-task.patch +ApplyPatch 1307-rdma-mana-remove-user-triggerable-warn-on-in-mana-ib-create-.patch +ApplyPatch 1308-nvmet-tcp-fix-race-between-icreq-handling-and-queue-teardown.patch +ApplyPatch 1309-scsi-qla2xxx-completely-fix-fcport-double-free.patch +ApplyPatch 1310-rbd-eliminate-a-race-in-lock-dwork-draining-on-unmap.patch +ApplyPatch 1311-net-sched-fix-pedit-partial-cow-leading-to-page-cache-corrup.patch # END OF PATCH APPLICATIONS # Any further pre-build tree manipulations happen here. @@ -4165,6 +4219,42 @@ fi # # %changelog +* Mon Jun 22 2026 Andrew Lukoshko - 5.14.0-687.17.1 +- Recreate RHEL 5.14.0-687.17.1 from CentOS Stream 9 and upstream stable backports (1285-1311) +- RHEL changelog for 687.16.1..687.17.1 follows: + +* Thu Jun 18 2026 CKI KWF Bot [5.14.0-687.17.1.el9_8] +- net/sched: fix pedit partial COW leading to page cache corruption (Ivan Vecera) [RHEL-177392] {CVE-2026-46331} +- gitlab-ci: use rhel9.8 builder image (Michael Krausch-Hofmann) +- rbd: eliminate a race in lock_dwork draining on unmap (CKI Backport Bot) [RHEL-183130] +- scsi: qla2xxx: Completely fix fcport double free (Ewan D. Milne) [RHEL-179754] {CVE-2026-43414} +- nvmet-tcp: fix race between ICReq handling and queue teardown (Chris Leech) [RHEL-180102] {CVE-2026-46135} +- RDMA/mana: Remove user triggerable WARN_ON() in mana_ib_create_qp_rss() (CKI Backport Bot) [RHEL-180158] {CVE-2026-46117} +- exit: prevent preemption of oopsing TASK_DEAD task (CKI Backport Bot) [RHEL-180016] {CVE-2026-46173} +- ALSA: usb-audio: Add sanity check for OOB writes at silencing (CKI Backport Bot) [RHEL-173941] {CVE-2026-43279} + +* Tue Jun 16 2026 CKI KWF Bot [5.14.0-687.16.1.el9_8] +- s390/mm: Add missing secure storage access fixups for donated memory (Jan Polensky) [RHEL-183317] +- ibmveth: Disable GSO for packets with small MSS (Mamatha Inamdar) [RHEL-178308] +- s390/ap: Expose ap_bindings_complete_count counter via sysfs (Jan Polensky) [RHEL-166048] +- gfs2: Fix use-after-free in iomap inline data write path (Andrew Price) [RHEL-179589] {CVE-2026-45984} +- gfs2: Add metapath_dibh helper (Andrew Price) [RHEL-179589] {CVE-2026-45984} +- bnxt_en: Fix RSS context delete logic (CKI Backport Bot) [RHEL-180308] {CVE-2026-43260} +- wifi: mac80211: remove station if connection prep fails (CKI Backport Bot) [RHEL-180121] {CVE-2026-46125} +- RDMA/mana: Validate rx_hash_key_len (CKI Backport Bot) [RHEL-180085] {CVE-2026-46145} +- wifi: mac80211: drop stray 'static' from fast-RX rx_result (CKI Backport Bot) [RHEL-180057] {CVE-2026-46152} +- wifi: mac80211: use safe list iteration in radar detect work (CKI Backport Bot) [RHEL-180025] {CVE-2026-46166} +- Bluetooth: hci_event: fix potential UAF in SSP passkey handlers (CKI Backport Bot) [RHEL-179359] {CVE-2026-46056} +- ice: Fix NULL pointer dereference in ice_vsi_set_napi_queues (CKI Backport Bot) [RHEL-175699] +- mptcp: fix slab-use-after-free in __inet_lookup_established (Davide Caratti) [RHEL-171506] {CVE-2026-31669} +- dpll: zl3073x: report FFO as DPLL vs input reference offset (Ivan Vecera) [RHEL-175823] +- dpll: add fractional frequency offset to pin-parent-device (Ivan Vecera) [RHEL-175823] +- dpll: zl3073x: implement pin operational state reporting (Ivan Vecera) [RHEL-175820] +- dpll: add pin operational state (Ivan Vecera) [RHEL-175820] +- can: isotp: fix tx.buf use-after-free in isotp_sendmsg() (CKI Backport Bot) [RHEL-175525] {CVE-2026-31474} +- Bluetooth: hci_sync: fix stack buffer overflow in hci_le_big_create_sync (CKI Backport Bot) [RHEL-172858] {CVE-2026-31772} +- xen/privcmd: fix double free via VMA splitting (CKI Backport Bot) [RHEL-172488] {CVE-2026-31787} + * Wed Jun 11 2026 Andrew Lukoshko - 5.14.0-687.15.1 - Recreate RHEL 5.14.0-687.15.1 from CentOS Stream 9 and upstream stable backports (1270-1284) - redhat: Remove the mlx5 symbols from kabi: applied via updated Module.kabi_{aarch64,s390x,x86_64} (RHEL-181822)