From: Jakub Kicinski <kuba@kernel.org>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com,
andrew+netdev@lunn.ch, horms@kernel.org,
Jakub Kicinski <kuba@kernel.org>,
vadim.fedorenko@linux.dev, arkadiusz.kubalewski@intel.com,
jiri@resnulli.us, ivecera@redhat.com, milena.olech@intel.com,
przemyslaw.kitszel@intel.com
Subject: [PATCH net] dpll: reject a reference sync pin which is not on the pin's dpll
Date: Tue, 15 Sep 2026 14:30:47 -0700 [thread overview]
Message-ID: <20260915213047.1352286-1-kuba@kernel.org> (raw)
dpll_pin_ref_sync_state_set() resolves the partner's driver private data
with dpll_pin_on_dpll_priv() and passes the result to ref_sync_get() and
ref_sync_set() without looking at it. The helper returns NULL when the
partner holds no ref on that dpll. Of the two drivers implementing the
feature only zl3073x dereferences the pointer (sync_pin->id); ice ignores
it, so ice cannot fault here.
The NULL is a teardown race, not a steady state - zl3073x registers every
input pin with every channel, so the partner is normally present on the
dpll the base pin resolves to. zl3073x_dev_stop() unregisters pins one at
a time, taking and dropping dpll_lock for each, and between the partner's
turn and the base pin's the partner is out of that dpll's pin_refs while
still registered with the channels not yet torn down, so
dpll_pin_available() keeps passing. That path is not only driver removal:
devlink reload and devlink dev flash both run zl3073x_dev_stop().
Reproduced by holding that state open with a mock dpll device, which is
where the frame name comes from:
BUG: kernel NULL pointer dereference, address: 0000000000000000
Oops: Oops: 0000 [#1] SMP NOPTI
RIP: 0010:mock_ref_sync_get+0x5/0x30
Call Trace:
<TASK>
dpll_pin_ref_sync_set+0x19f/0x4a0
dpll_nl_pin_set_doit+0x17d/0x840
genl_family_rcv_msg_doit+0xd6/0x130
genl_rcv_msg+0x181/0x2b0
netlink_rcv_skb+0x55/0x100
genl_rcv+0x23/0x30
netlink_unicast+0x24d/0x370
netlink_sendmsg+0x1e2/0x420
__sys_sendto+0x1db/0x1f0
__x64_sys_sendto+0x1f/0x30
do_syscall_64+0xe1/0x490
Commit d2e914a4a0d0 ("dpll: fix NULL pointer dereference in
dpll_msg_add_pin_ref_sync()") added the same guard to the read side, which
the kernel walks into by itself because the delete notification is emitted
from inside the unregister; the write side needs a pin-set to land in the
window and was left alone. Test the priv rather than look up pin_refs
directly, so that the two halves key off the same condition.
Fixes: 58256a26bfb3 ("dpll: add reference sync get/set")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: vadim.fedorenko@linux.dev
CC: arkadiusz.kubalewski@intel.com
CC: jiri@resnulli.us
CC: ivecera@redhat.com
CC: milena.olech@intel.com
CC: przemyslaw.kitszel@intel.com
---
drivers/dpll/dpll_netlink.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index d4f133ac9fea..9a90733b2da3 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -1201,6 +1201,7 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin, u32 ref_sync_pin_id,
const enum dpll_pin_state state,
struct netlink_ext_ack *extack)
{
+ void *pin_priv, *ref_sync_pin_priv;
const struct dpll_pin_ops *ops;
enum dpll_pin_state old_state;
struct dpll_pin *ref_sync_pin;
@@ -1228,9 +1229,15 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin, u32 ref_sync_pin_id,
return -EOPNOTSUPP;
}
dpll = ref->dpll;
- ret = ops->ref_sync_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
- ref_sync_pin,
- dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
+ pin_priv = dpll_pin_on_dpll_priv(dpll, pin);
+ ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin);
+ /* Pin may have been unregistered from this dpll already */
+ if (!ref_sync_pin_priv) {
+ NL_SET_ERR_MSG(extack,
+ "reference sync pin not registered with the dpll");
+ return -ENODEV;
+ }
+ ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin, ref_sync_pin_priv,
&old_state, extack);
if (ret) {
NL_SET_ERR_MSG(extack, "unable to get old reference sync state");
@@ -1239,9 +1246,7 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin, u32 ref_sync_pin_id,
if (state == old_state)
return 0;
- ret = ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
- ref_sync_pin,
- dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
+ ret = ops->ref_sync_set(pin, pin_priv, ref_sync_pin, ref_sync_pin_priv,
state, extack);
if (ret) {
NL_SET_ERR_MSG_FMT(extack,
--
2.55.0
next reply other threads:[~2026-09-15 21:30 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 21:30 Jakub Kicinski [this message]
2026-09-16 23:37 ` [PATCH net] dpll: reject a reference sync pin which is not on the pin's dpll Jakub Kicinski
2026-09-17 8:32 ` Ivan Vecera
2026-09-17 8:29 ` Ivan Vecera
2026-09-17 12:50 ` Paolo Abeni
2026-09-17 13:00 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260915213047.1352286-1-kuba@kernel.org \
--to=kuba@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=arkadiusz.kubalewski@intel.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=ivecera@redhat.com \
--cc=jiri@resnulli.us \
--cc=milena.olech@intel.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=przemyslaw.kitszel@intel.com \
--cc=vadim.fedorenko@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.