From cdda0fdf37db6d4242c5e04d7a26e500104e204b Mon Sep 17 00:00:00 2001 From: norly Date: Fri, 11 Jan 2019 03:38:35 +0100 Subject: [PATCH] Avoid ldisc_ioctl() racing unregister_candev() When getting the CAN interface's name via the SIOCGIFNAME ioctl, elm->dev->name may no longer exist because the interface is being shut down. Also, print the name of the interface to dmesg. --- module/elmcan.c | 21 ++++++++++++++++++--- readme.rst | 2 -- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/module/elmcan.c b/module/elmcan.c index 0bf1b8b..a62135e 100644 --- a/module/elmcan.c +++ b/module/elmcan.c @@ -78,7 +78,7 @@ struct elmcan { struct tty_struct *tty; struct net_device *dev; - int magic; + char ifname[IFNAMSIZ]; /* Per-channel lock */ spinlock_t lock; @@ -684,6 +684,18 @@ static void elm327_parse_rxbuf(struct elmcan *elm) * (takes elm->lock) * ************************************************************************/ +static int elmcan_netdev_init(struct net_device *dev) +{ + struct elmcan *elm = netdev_priv(dev); + + /* Copy the interface name here, so the SIOCGIFNAME case in + * elmcan_ldisc_ioctl() doesn't race against unregister_candev(). + */ + memcpy(elm->ifname, dev->name, IFNAMSIZ); + + return 0; +} + /* Netdevice DOWN -> UP routine */ static int elmcan_netdev_open(struct net_device *dev) { @@ -791,6 +803,7 @@ static int elmcan_netdev_change_mtu(struct net_device *dev, int new_mtu) } static const struct net_device_ops elmcan_netdev_ops = { + .ndo_init = elmcan_netdev_init, .ndo_open = elmcan_netdev_open, .ndo_stop = elmcan_netdev_close, .ndo_start_xmit = elmcan_netdev_start_xmit, @@ -982,6 +995,8 @@ static int elmcan_ldisc_open(struct tty_struct *tty) return err; } + netdev_info(elm->dev, "elmcan on %s.\n", tty->name); + return 0; } @@ -1036,8 +1051,8 @@ static int elmcan_ldisc_ioctl(struct tty_struct *tty, struct file *file, switch (cmd) { case SIOCGIFNAME: - tmp = strlen(elm->dev->name) + 1; - if (copy_to_user((void __user *)arg, elm->dev->name, tmp)) + tmp = strlen(elm->ifname) + 1; + if (copy_to_user((void __user *)arg, elm->ifname, tmp)) return -EFAULT; return 0; diff --git a/readme.rst b/readme.rst index 4911664..1c3c6d1 100644 --- a/readme.rst +++ b/readme.rst @@ -270,8 +270,6 @@ To Do list for future development - ``if (!elm)``: Race with ``ldisc_close()`` -- ``elm->dev``: Race in ``ldisc_ioctl()`` - - DMA capable rx/tx buffers - fixup constants, constant for '``>``' -- 2.30.2