Re: [PATCH net 15/20] can: rcar_canfd: change the initializing flow for clocks and resets

[email protected] Thu, 30 Jul 2026 10:29:56 +0000
Newsgroups org.kernel.vger.linux-can
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 2 potential issue(=
s) to consider:

Pre-existing issues:
- [High] If `rcar_canfd_global_init()` fails, `rcar_canfd_probe()` incorrec=
tly calls `rcar_canfd_global_deinit()`, causing a kernel panic from accessi=
ng registers with disabled clocks, followed by a double-disable of clocks a=
nd double-assertion of resets.
- [High] If `register_candev()` fails during channel probe, the network dev=
ice is freed, but the global context retains a dangling pointer to it, whic=
h is subsequently dereferenced and double-freed during the driver probe err=
or teardown.
--

--- Patch [15]: [PATCH net 15/20] can: rcar_canfd: change the initializing =
flow for clocks and resets ---
commit 4a859a221c1b4bd83a846c702809583b08a6af18
Author: Tu Nguyen <[email protected]>

can: rcar_canfd: change the initializing flow for clocks and resets

This patch updates the initialization order for clocks and resets to match
the hardware manual, ensuring clocks are supplied before resets are
deasserted. It also updates the teardown path in rcar_canfd_global_deinit()
to mirror this new init ordering.

Link: https://patch.msgid.link/[email protected]=
as.com

> --- a/drivers/net/can/rcar/rcar_canfd.c
> +++ b/drivers/net/can/rcar/rcar_canfd.c
[ ... ]
> @@ -2068,14 +2068,14 @@ static int rcar_canfd_global_init(struct rcar_can=
fd_global *gpriv)
> =20
>  fail_mode:
>  	rcar_canfd_disable_global_interrupts(gpriv);
[ ... ]
> +fail_ram_clk:
> +	clk_disable_unprepare(gpriv->clk_ram);
> +fail_clk:
> +	clk_disable_unprepare(gpriv->clkp);
>  	return err;
>  }

[Severity: High]
This isn't a bug introduced by this patch, but does the probe error path
cause a panic and double-disable of clocks here?

When rcar_canfd_global_init() fails, it correctly cleans up its state and
disables the clocks. However, in rcar_canfd_probe(), the failure jumps to
the fail_mode label:

rcar_canfd_probe() {
    ...
    err =3D rcar_canfd_global_init(gpriv);
    if (err)
        goto fail_mode;
    ...
fail_mode:
    rcar_canfd_global_deinit(gpriv, false);
    ...
}

Since the clocks were already disabled by the initialization failure path,
calling rcar_canfd_global_deinit() will access hardware registers with
disabled clocks via rcar_canfd_disable_global_interrupts(). Can this trigger
a precise or imprecise external abort? It also looks like it will redundant=
ly
assert the resets and disable the clocks a second time.

[Severity: High]
This is also a pre-existing issue, but could this probe error cleanup seque=
nce
trigger a double-free on a channel probe failure?

In rcar_canfd_channel_probe(), the device pointer is saved to the global
array before registration:

rcar_canfd_channel_probe() {
    ...
    gpriv->ch[priv->channel] =3D priv;
    err =3D register_candev(ndev);
    if (err) {
        ...
        goto fail_candev;
    }
    ...
fail:
    free_candev(ndev);
}

If register_candev() fails, the memory is freed but the dangling pointer
remains in the global array. Back in rcar_canfd_probe(), the error is caught
and rcar_canfd_channel_remove() is called for all channels in the mask. Does
the cleanup loop find this dangling pointer and try to operate on the
already-freed network device, causing a use-after-free and double-free?

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260729102802.5051=
[email protected]?part=3D15