From: sashiko-bot@kernel.org
To: "Ali Rouhi" <rouhi.ali@gmail.com>
Cc: krzk+dt@kernel.org, devicetree@vger.kernel.org, robh@kernel.org,
conor+dt@kernel.org
Subject: Re: [PATCH net-next 3/3] dpll: add SiTime SiT9531x DPLL clock driver
Date: Wed, 13 May 2026 00:52:51 +0000 [thread overview]
Message-ID: <20260513005252.34EA0C2BCB0@smtp.kernel.org> (raw)
In-Reply-To: <20260511211453.20671-2-arouhi@sitime.com>
Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [Critical] DPLL pin properties (`package_label` and `freq_supported`) are freed immediately after registration, causing a critical use-after-free vulnerability.
- [High] The driver uses a non-existent macro `kzalloc_obj` for memory allocation, causing a build failure.
- [High] The crystal oscillator frequency (`xtal_freq`) is never initialized, permanently breaking core frequency and phase calculations.
- [High] The INTRB threaded IRQ is registered before the kthread worker is initialized and torn down after the worker is destroyed, causing a NULL pointer dereference race.
- [High] The driver fails to clear hardware interrupt notifications, causing an unhandled interrupt storm.
- [High] Phase adjustments are written to the wrong hardware registers because the logical output index is used instead of the physical slot.
- [High] Unsigned 32-bit hardware fractional numerators are read into signed integers, causing a sign-extension bug that corrupts DCO math.
- [Medium] Hardware state cache arrays are updated and read concurrently without locking, leading to data races.
- [Medium] DCO frequency adjustment and SYSREF/SYNCB output modes are fully implemented but entirely unreachable (Dead Code).
--
commit 7809f8a3992ad8b550d7f2507263595d95f3b3d8
Author: Ali Rouhi <rouhi.ali@gmail.com>
dpll: add SiTime SiT9531x DPLL clock driver
Adds a DPLL subsystem driver for the SiTime SiT95316 and SiT95317
clock generators.
The driver exposes all inputs and outputs through the Linux DPLL
subsystem, supporting:
[ ... ]
- DCO (digitally controlled oscillator) frequency adjustment
[ ... ]
- SYSREF/SYNCB/Pulser output mode control
This isn't a bug, but the commit message indicates that the driver supports
DCO frequency adjustment and SYSREF/SYNCB output mode control. However,
these features do not appear to be hooked into sit9531x_dpll_device_ops or
otherwise exposed to the DPLL subsystem.
> diff --git a/drivers/dpll/sit9531x/core.c b/drivers/dpll/sit9531x/core.c
> new file mode 100644
> index 0000000000000..4c15a10aaa0ae
> --- /dev/null
> +++ b/drivers/dpll/sit9531x/core.c
[ ... ]
> +static int sit9531x_dco_read_divn(struct sit9531x_dev *sitdev, u8 pll_idx,
> + u32 *int_part, s32 *fracn, u32 *fracd)
> +{
[ ... ]
> + /* Numerator (4 bytes, little-endian) */
> + *fracn = 0;
> + for (i = 3; i >= 0; i--) {
> + rc = sit9531x_read_pll_u8(sitdev, pll_idx,
> + SIT9531X_PLL_REG_DIVN_NUM + i, &v);
> + if (rc)
> + return rc;
> + *fracn = (*fracn << 8) | v;
> + }
Could this left shift into a signed 32-bit integer result in a negative
value?
If the hardware fractional numerator represents a value greater than or
equal to 0.5, the most significant bit will be set. This might sign-extend
when cast later and alter the calculation in sit9531x_dco_calc_inner.
[ ... ]
> +static u64 sit9531x_get_fvco(struct sit9531x_dev *sitdev, u8 pll_idx)
> +{
[ ... ]
> + doubler = sit9531x_is_xo_doubler_enabled(sitdev);
> + if (doubler < 0)
> + return 0;
> +
> + fref = (u64)sitdev->xtal_freq << doubler;
Where is sitdev->xtal_freq populated?
If it remains zero-initialized from the initial allocation, fref will
evaluate to zero. This would cause fvco to return zero and affect
subsequent frequency calculations and hardware state updates.
[ ... ]
> +int sit9531x_output_phase_adjust_set(struct sit9531x_dev *sitdev,
> + u8 out_idx, s32 phase_ps)
> +{
[ ... ]
> + page = (out_idx < 6) ? SIT9531X_PAGE_OUTSYS0
> + : SIT9531X_PAGE_OUTSYS1;
> + base = SIT9531X_OUT_PRG_DELAY_BASE +
> + SIT9531X_OUT_PRG_SLOT_STRIDE * (out_idx % 6);
Should this use the physical slot mapping instead of the logical index?
Using out_idx directly here might cause the driver to write to the phase
delay registers of a different output port. sit9531x_output_freq_set() uses
info->clkout_map to resolve this correctly.
[ ... ]
> +static irqreturn_t sit9531x_irq_thread_fn(int irq, void *data)
> +{
> + struct sit9531x_dev *sitdev = data;
> +
> + kthread_mod_delayed_work(sitdev->kworker, &sitdev->work, 0);
> + return IRQ_HANDLED;
> +}
Does the hardware require interrupt notifications to be explicitly cleared?
The handler returns IRQ_HANDLED after waking the worker, but
sit9531x_clear_notifications() is never called. If this is a level-triggered
interrupt line, leaving the notification active might cause an interrupt
storm.
[ ... ]
> +int sit9531x_dev_probe(struct sit9531x_dev *sitdev)
> +{
[ ... ]
> + if (sitdev->irq > 0) {
> + rc = devm_request_threaded_irq(sitdev->dev, sitdev->irq,
> + NULL, sit9531x_irq_thread_fn,
> + IRQF_ONESHOT,
> + dev_name(sitdev->dev), sitdev);
> + if (rc)
> + return dev_err_probe(sitdev->dev, rc,
> + "Failed to request IRQ %d\n",
> + sitdev->irq);
> + dev_info(sitdev->dev,
> + "INTRB IRQ %d wired (threaded handler kicks periodic poll)\n",
> + sitdev->irq);
> + }
> +
> + /* Register DPLL channels */
> + rc = sit9531x_devm_dpll_init(sitdev);
What happens if the interrupt fires right after it is registered?
Since devm_request_threaded_irq is called before the kworker is initialized
inside sit9531x_devm_dpll_init, an early interrupt could cause the thread
handler to dereference a null pointer when interacting with the worker.
> diff --git a/drivers/dpll/sit9531x/dpll.c b/drivers/dpll/sit9531x/dpll.c
> new file mode 100644
> index 0000000000000..c766c7c2dd366
> --- /dev/null
> +++ b/drivers/dpll/sit9531x/dpll.c
[ ... ]
> +static int
> +sit9531x_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv,
> + enum dpll_lock_status *status,
> + enum dpll_lock_status_error *status_error,
> + struct netlink_ext_ack *extack)
> +{
> + struct sit9531x_dpll *sitdpll = dpll_priv;
> + const struct sit9531x_chan *chan;
> +
> + if (status_error)
> + *status_error = DPLL_LOCK_STATUS_ERROR_NONE;
> +
> + chan = sit9531x_chan_state_get(sitdpll->dev, sitdpll->id);
> +
> + if (chan->locked) {
Is it safe to read the channel state here without holding a lock?
The periodic worker locklessly updates the hardware state cache arrays.
Concurrent reads in the netlink callbacks could potentially see torn data
or mismatched state vectors.
[ ... ]
> +static struct sit9531x_dpll_pin *
> +sit9531x_dpll_pin_alloc(struct sit9531x_dpll *sitdpll,
> + enum dpll_pin_direction dir, u8 id)
> +{
> + struct sit9531x_dpll_pin *pin;
> +
> + pin = kzalloc_obj(*pin, GFP_KERNEL);
> + if (!pin)
> + return ERR_PTR(-ENOMEM);
Does the macro kzalloc_obj exist in the tree?
It looks like this might cause a build failure since kzalloc is the standard
allocation macro. This same pattern seems to be used in sit9531x_dpll_alloc
and sit9531x_pin_props_get.
[ ... ]
> +static int sit9531x_dpll_pin_register(struct sit9531x_dpll_pin *pin,
> + u32 index)
> +{
[ ... ]
> + /* Register the pin */
> + rc = dpll_pin_register(sitdpll->dpll_dev, pin->dpll_pin, ops, pin);
> + if (rc)
> + goto err_register;
> +
> + /* Free pin properties */
> + sit9531x_pin_props_put(props);
> +
> + return 0;
Are the pointers for package_label and freq_supported safely copied?
Looking at the DPLL core, dpll_pin_get() appears to perform a shallow copy.
Freeing the properties right after registration could result in a use after
free when the subsystem later attempts to read them.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511211453.20671-1-arouhi@sitime.com?part=3
next prev parent reply other threads:[~2026-05-13 0:52 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-11 21:11 [PATCH net-next 0/3] dpll: add SiTime SiT9531x DPLL clock driver Ali Rouhi
2026-05-11 21:11 ` [PATCH net-next 1/3] dt-bindings: vendor-prefixes: add SiTime Corporation Ali Rouhi
2026-05-12 17:46 ` Conor Dooley
2026-05-13 0:09 ` sashiko-bot
2026-05-11 21:14 ` [PATCH net-next 2/3] dt-bindings: dpll: add SiTime SiT9531x clock generator Ali Rouhi
2026-05-11 21:14 ` [PATCH net-next 3/3] dpll: add SiTime SiT9531x DPLL clock driver Ali Rouhi
2026-05-13 0:52 ` sashiko-bot [this message]
2026-05-12 17:52 ` [PATCH net-next 2/3] dt-bindings: dpll: add SiTime SiT9531x clock generator Conor Dooley
[not found] ` <CALFSGurCGzyk3mOPnyP_p2o+s9kCCQZc4MjBsDpPxqSPV1ZseA@mail.gmail.com>
2026-05-12 20:23 ` Ali Rouhi
2026-05-13 0:18 ` sashiko-bot
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=20260513005252.34EA0C2BCB0@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=robh@kernel.org \
--cc=rouhi.ali@gmail.com \
--cc=sashiko-reviews@lists.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox