Recreate RHEL 5.14.0-687.17.1 from CS9/upstream backports
This commit is contained in:
parent
018222497a
commit
6e8d3350cc
@ -0,0 +1,59 @@
|
||||
From 2b985d3a024b9e8c24e21671b34e855569763808 Mon Sep 17 00:00:00 2001
|
||||
From: Juergen Gross <jgross@suse.com>
|
||||
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 <atharva.a.vartak@gmail.com>
|
||||
Suggested-by: Atharva Vartak <atharva.a.vartak@gmail.com>
|
||||
Signed-off-by: Juergen Gross <jgross@suse.com>
|
||||
Reviewed-by: Jan Beulich <jbeulich@suse.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
From 3eefd9e9213a567e4b2121832ee201264486407c Mon Sep 17 00:00:00 2001
|
||||
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
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 <hkbinbinbin@gmail.com>
|
||||
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 <hkbinbinbin@gmail.com>
|
||||
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
|
||||
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
|
||||
|
||||
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
|
||||
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;
|
||||
@ -0,0 +1,77 @@
|
||||
From 424e95d62110cdbc8fd12b40918f37e408e35a92 Mon Sep 17 00:00:00 2001
|
||||
From: Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
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 <ali.norouzi@keysight.com>
|
||||
Co-developed-by: Ali Norouzi <ali.norouzi@keysight.com>
|
||||
Signed-off-by: Ali Norouzi <ali.norouzi@keysight.com>
|
||||
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
Link: https://patch.msgid.link/20260319-fix-can-gw-and-can-isotp-v2-2-c45d52c6d2d8@pengutronix.de
|
||||
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
279
SOURCES/1288-dpll-add-pin-operational-state.patch
Normal file
279
SOURCES/1288-dpll-add-pin-operational-state.patch
Normal file
@ -0,0 +1,279 @@
|
||||
From 781c8893a5da8522ae4ded93e5ef3adbe9559300 Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Vecera <ivecera@redhat.com>
|
||||
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 <ivecera@redhat.com>
|
||||
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
|
||||
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
|
||||
Reviewed-by: Petr Oros <poros@redhat.com>
|
||||
Link: https://patch.msgid.link/20260428154907.2820654-2-ivecera@redhat.com
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
|
||||
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 <uapi/linux/dpll.h>
|
||||
|
||||
/* 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 <uapi/linux/dpll.h>
|
||||
|
||||
/* 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)
|
||||
@ -0,0 +1,239 @@
|
||||
From c53f8f8dce776e032b1a11fb4d9b6e12bb63d958 Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Vecera <ivecera@redhat.com>
|
||||
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 <ivecera@redhat.com>
|
||||
Reviewed-by: Petr Oros <poros@redhat.com>
|
||||
Link: https://patch.msgid.link/20260428154907.2820654-3-ivecera@redhat.com
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
|
||||
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)
|
||||
@ -0,0 +1,354 @@
|
||||
From 9c11fcb2e9a54d0f1467380831e2e4bb68f7498d Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Vecera <ivecera@redhat.com>
|
||||
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 <jiri@nvidia.com>
|
||||
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
|
||||
Link: https://patch.msgid.link/20260511155816.99936-2-ivecera@redhat.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
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)
|
||||
@ -0,0 +1,347 @@
|
||||
From 54e65df8cf18a741745645aed7ae91514d437b43 Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Vecera <ivecera@redhat.com>
|
||||
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 <poros@redhat.com>
|
||||
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
|
||||
Link: https://patch.msgid.link/20260511155816.99936-3-ivecera@redhat.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
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 <linux/atomic.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bug.h>
|
||||
@@ -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
|
||||
***********************************/
|
||||
@ -0,0 +1,100 @@
|
||||
From f6e1f25fa5e733570f6d6fe37a4dfed2a0deba47 Mon Sep 17 00:00:00 2001
|
||||
From: Jiayuan Chen <jiayuan.chen@linux.dev>
|
||||
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 <jiayuan.chen@linux.dev>
|
||||
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Link: https://patch.msgid.link/20260406031512.189159-1-jiayuan.chen@linux.dev
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
|
||||
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
|
||||
@ -0,0 +1,95 @@
|
||||
From 6985e4baf50b86327426ca5d5cf4787ac165aacd Mon Sep 17 00:00:00 2001
|
||||
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
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 <aaron.ma@canonical.com>
|
||||
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] <TASK>
|
||||
<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 <aleksandr.loktionov@intel.com>
|
||||
Signed-off-by: Aaron Ma <aaron.ma@canonical.com>
|
||||
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
|
||||
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
|
||||
|
||||
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
|
||||
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];
|
||||
@ -0,0 +1,89 @@
|
||||
From d28311539ac9f65e29308ea219ecaa48aa5e76e5 Mon Sep 17 00:00:00 2001
|
||||
From: Shuvam Pandey <shuvampandey1@gmail.com>
|
||||
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 <shuvampandey1@gmail.com>
|
||||
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
|
||||
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
|
||||
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,
|
||||
@ -0,0 +1,33 @@
|
||||
From ac8eb3e18f41e2cc8492cc1d358bcb786c850270 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Berg <benjamin.berg@intel.com>
|
||||
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 <benjamin.berg@intel.com>
|
||||
Link: https://patch.msgid.link/20260505151539.236d63a1b736.I35dbb9e96a2d4a480be208770fdd99ba3b817b79@changeid
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
|
||||
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;
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
From 7a5b81e0c87a075afd572f659d8eb68c9c4cd2ba Mon Sep 17 00:00:00 2001
|
||||
From: Catherine <enderaoelyther@gmail.com>
|
||||
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 <enderaoelyther@gmail.com>
|
||||
Link: https://patch.msgid.link/20260424131435.83212-2-enderaoelyther@gmail.com
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
|
||||
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;
|
||||
30
SOURCES/1297-rdma-mana-validate-rx-hash-key-len.patch
Normal file
30
SOURCES/1297-rdma-mana-validate-rx-hash-key-len.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 6dd2d4ad9c8429523b1c220c5132bd551c006425 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Gunthorpe <jgg@nvidia.com>
|
||||
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 <longli@microsoft.com>
|
||||
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
|
||||
|
||||
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)
|
||||
@ -0,0 +1,56 @@
|
||||
From 283fc9e44ff5b5ac967439b4951b80bd4299f4e4 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
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 <miriam.rachel.korenblit@intel.com>
|
||||
Link: https://patch.msgid.link/20260505151533.c4e52deb06ad.Iafe56cec7de8512626169496b134bce3a6c17010@changeid
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
|
||||
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;
|
||||
}
|
||||
57
SOURCES/1299-bnxt-en-fix-rss-context-delete-logic.patch
Normal file
57
SOURCES/1299-bnxt-en-fix-rss-context-delete-logic.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From e123d9302d223767bd910bfbcfe607bae909f8ac Mon Sep 17 00:00:00 2001
|
||||
From: Pavan Chebbi <pavan.chebbi@broadcom.com>
|
||||
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 <kicinski@meta.com>
|
||||
Fixes: 667ac333dbb7 ("eth: bnxt: allow deleting RSS contexts when the device is down")
|
||||
Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
|
||||
Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
|
||||
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
|
||||
Link: https://patch.msgid.link/20260219185313.2682148-2-michael.chan@broadcom.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
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;
|
||||
40
SOURCES/1300-gfs2-add-metapath-dibh-helper.patch
Normal file
40
SOURCES/1300-gfs2-add-metapath-dibh-helper.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 602fb357b195d846887987a68024330a593ab1b9 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Gruenbacher <agruenba@redhat.com>
|
||||
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 <agruenba@redhat.com>
|
||||
Stable-dep-of: faddeb848305 ("gfs2: Fix use-after-free in iomap inline data write path")
|
||||
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
||||
|
||||
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;
|
||||
@ -0,0 +1,76 @@
|
||||
From 1cae1bafdf9caa9b462b19af06b1a06902e4e142 Mon Sep 17 00:00:00 2001
|
||||
From: Deepanshu Kartikey <kartikey406@gmail.com>
|
||||
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 <kartikey406@gmail.com>
|
||||
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
|
||||
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
||||
|
||||
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)
|
||||
@ -0,0 +1,64 @@
|
||||
From ed98cf22bd574bbcd5906e0ee217dfe65f5f8c8a Mon Sep 17 00:00:00 2001
|
||||
From: Mete Durlu <mdurlu@redhat.com>
|
||||
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 <freude@linux.ibm.com>
|
||||
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 <mjrosato@linux.ibm.com>
|
||||
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
|
||||
Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
|
||||
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
|
||||
|
||||
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
|
||||
Signed-off-by: Mete Durlu <mdurlu@redhat.com>
|
||||
|
||||
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,
|
||||
};
|
||||
@ -0,0 +1,104 @@
|
||||
From cd82512d5e7852beab3b8cb254c60b061fc549ac Mon Sep 17 00:00:00 2001
|
||||
From: Mamatha Inamdar <minamdar@redhat.com>
|
||||
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 <mmc@linux.ibm.com>
|
||||
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 <f10b09ef687f> ("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 <bjking1@linux.ibm.com>
|
||||
Tested-by: Shaik Abdulla <shaik.abdulla1@ibm.com>
|
||||
Tested-by: Naveed Ahmed <naveedaus@in.ibm.com>
|
||||
Signed-off-by: Mingming Cao <mmc@linux.ibm.com>
|
||||
Link: https://patch.msgid.link/20260424162917.65725-1-mmc@linux.ibm.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
Signed-off-by: Mamatha Inamdar <minamdar@redhat.com>
|
||||
|
||||
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)
|
||||
@ -0,0 +1,66 @@
|
||||
From 532af53c2c278d6a7197be0afd8b5d3839e686e3 Mon Sep 17 00:00:00 2001
|
||||
From: Mete Durlu <mdurlu@redhat.com>
|
||||
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 <frankja@linux.ibm.com>
|
||||
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 <hca@linux.ibm.com>
|
||||
Suggested-by: Heiko Carstens <hca@linux.ibm.com>
|
||||
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
|
||||
Tested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
|
||||
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||
|
||||
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
|
||||
Signed-off-by: Mete Durlu <mdurlu@redhat.com>
|
||||
|
||||
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();
|
||||
@ -0,0 +1,107 @@
|
||||
From 0a6ada5e5f985332a38b2ab39c21a5696a4cfdfb Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <jkysela@redhat.com>
|
||||
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 <tiwai@suse.de>
|
||||
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 <tiwai@suse.de>
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <jkysela@redhat.com>
|
||||
|
||||
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) {
|
||||
@ -0,0 +1,56 @@
|
||||
From 2f3e5b5a77374869a5c36c783c310be9c26493e0 Mon Sep 17 00:00:00 2001
|
||||
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
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 <jannh@google.com>
|
||||
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 <jannh@google.com>
|
||||
Acked-by: Peter Zijlstra <peterz@infradead.org>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
|
||||
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
From 159f2efabc89d3f931d38f2d35876535d4abf0a3 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Gunthorpe <jgg@nvidia.com>
|
||||
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 <longli@microsoft.com>
|
||||
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
|
||||
|
||||
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
|
||||
@ -0,0 +1,94 @@
|
||||
From 5293a8882c549fab4a878bc76b0b6c951f980a61 Mon Sep 17 00:00:00 2001
|
||||
From: Chaitanya Kulkarni <kch@nvidia.com>
|
||||
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 <skumar47@syr.edu>
|
||||
Tested-by: Shivam Kumar <kumar.shivam43666@gmail.com>
|
||||
Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com>
|
||||
Signed-off-by: Keith Busch <kbusch@kernel.org>
|
||||
|
||||
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;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
From c0b7da13a04bd70ef6070bfb9ea85f582294560a Mon Sep 17 00:00:00 2001
|
||||
From: Vladimir Riabchun <ferr.lambarginio@gmail.com>
|
||||
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 <ferr.lambarginio@gmail.com>
|
||||
Signed-off-by: Farhat Abbas <fabbas@cloudlinux.com>
|
||||
Link: https://patch.msgid.link/aYsDln9NFQQsPDgg@vova-pc
|
||||
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -0,0 +1,106 @@
|
||||
From 8bf586044031efd9d9883a8b63a4eb28b111fa8f Mon Sep 17 00:00:00 2001
|
||||
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
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 <idryomov@gmail.com>
|
||||
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 <idryomov@gmail.com>
|
||||
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
|
||||
|
||||
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -0,0 +1,224 @@
|
||||
From 899ee91156e57784090c5565e4f31bd7dbffbc5a Mon Sep 17 00:00:00 2001
|
||||
From: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
|
||||
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 <yimingqian591@gmail.com>
|
||||
Reported-by: Keenan Dong <keenanat2000@gmail.com>
|
||||
Reported-by: Han Guidong <2045gemini@gmail.com>
|
||||
Reported-by: Zhang Cen <rollkingzzc@gmail.com>
|
||||
Reviewed-by: Han Guidong <2045gemini@gmail.com>
|
||||
Tested-by: Han Guidong <2045gemini@gmail.com>
|
||||
Reviewed-by: Davide Caratti <dcaratti@redhat.com>
|
||||
Tested-by: Davide Caratti <dcaratti@redhat.com>
|
||||
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Tested-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Reviewed-by: Victor Nogueira <victor@mojatatu.com>
|
||||
Tested-by: Victor Nogueira <victor@mojatatu.com>
|
||||
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
|
||||
Signed-off-by: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
|
||||
Link: https://patch.msgid.link/20260531123221.48732-1-jhs@mojatatu.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
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 <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/overflow.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
@@ -24,6 +25,7 @@
|
||||
#include <uapi/linux/tc_act/tc_pedit.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/tc_wrapper.h>
|
||||
+#include <asm/unaligned.h>
|
||||
|
||||
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;
|
||||
@ -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 <alukoshko@almalinux.org> - 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 <cki-ci-bot+kwf-gitlab-com@redhat.com> [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 <cki-ci-bot+kwf-gitlab-com@redhat.com> [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 <alukoshko@almalinux.org> - 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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user