[PATCH net-next 2/2] can: can327: publish tty->disc_data only after register_candev()

From: Chaosheng Qu

Date: Fri Oct 16 2026 - 02:15:28 EST


can327_ldisc_open() publishes the private structure to the tty layer
before registering the net_device:

tty->disc_data = elm;

err = register_candev(elm->dev);
if (err) {
free_candev(elm->dev);
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 can327 structure in its private area, while
tty->disc_data still points at the freed memory.

Publish the pointer only after the device is registered, so the error
path has nothing to unwind. slcan does the same after its own patch, as
do ppp_async and nci_uart.

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_CAN327 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 <chaosheng.qu.linux@xxxxxxxxx>
---
drivers/net/can/can327.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/can327.c b/drivers/net/can/can327.c
index 90f5e35f3c8f..d40dadbb5733 100644
--- a/drivers/net/can/can327.c
+++ b/drivers/net/can/can327.c
@@ -1037,7 +1037,6 @@ static int can327_ldisc_open(struct tty_struct *tty)

/* Mark ldisc channel as alive */
elm->tty = tty;
- tty->disc_data = elm;

/* Let 'er rip */
err = register_candev(elm->dev);
@@ -1046,6 +1045,8 @@ static int can327_ldisc_open(struct tty_struct *tty)
return err;
}

+ tty->disc_data = elm;
+
netdev_info(elm->dev, "can327 on %s.\n", tty->name);

return 0;
--
2.43.0