slcan_open() publishes the private structure to the tty layer before registering the net_device: tty->disc_data = sl; err = register_candev(dev); if (err) { free_candev(dev); pr_err("can't register candev\n"); return err; } register_candev() fails with -ENOMEM from register_netdevice() when the device name node or the kobject cannot be allocated. The error path then frees the net_device and the slcan structure in its private area, while tty->disc_data still points at the freed memory. This is a regression from the 2022 rewrite. From the driver's addition in 2010 until then the error path cleared the pointer: err_free_chan: sl->tty = NULL; tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); Commit cfcb4465e992 ("can: slcan: remove legacy infrastructure") folded that label away and dropped the tty->disc_data = NULL with it. Publish the pointer only after the device is registered, so the error path has nothing to unwind. ppp_async and nci_uart assign it the same way; nci_uart was changed to that in commit fc27ab48904c ("NFC: nci: uart: Set tty->disc_data only in success path"). The stale pointer is not observable today: tty_set_termios_ldisc() clears tty->disc_data before .open() runs and again when a failed ldisc change falls back, and the ldisc entry points are serialised against .open() by tty_ldisc_ref() (async) and tty_ldisc_ref_wait() (syscall). The change removes a trap for the next modification of these functions. The success path was tested by attaching N_SLCAN to a pty under QEMU: the ldisc opens, creates the net_device and SIOCGIFNAME returns its name. The register_candev() failure path cannot be forced from userspace and is only compile tested. Assisted-by: LLM Signed-off-by: Chaosheng Qu --- drivers/net/can/slcan/slcan-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c index c9414faafe66..fc6ecf110aab 100644 --- a/drivers/net/can/slcan/slcan-core.c +++ b/drivers/net/can/slcan/slcan-core.c @@ -849,7 +849,6 @@ static int slcan_open(struct tty_struct *tty) /* Mark ldisc channel as alive */ sl->tty = tty; - tty->disc_data = sl; err = register_candev(dev); if (err) { @@ -858,6 +857,8 @@ static int slcan_open(struct tty_struct *tty) return err; } + tty->disc_data = sl; + netdev_info(dev, "slcan on %s.\n", tty->name); /* TTY layer expects 0 on success */ return 0; -- 2.43.0