All of lore.kernel.org
 help / color / mirror / Atom feed
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


             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.