| From bb8a4fcb2136508224c596a7e665bdba1d7c3c27 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Fri, 17 Sep 2021 13:46:21 +0200 |
| Subject: ipack: ipoctal: fix module reference leak |
| |
| From: Johan Hovold <johan@kernel.org> |
| |
| commit bb8a4fcb2136508224c596a7e665bdba1d7c3c27 upstream. |
| |
| A reference to the carrier module was taken on every open but was only |
| released once when the final reference to the tty struct was dropped. |
| |
| Fix this by taking the module reference and initialising the tty driver |
| data when installing the tty. |
| |
| Fixes: 82a82340bab6 ("ipoctal: get carrier driver to avoid rmmod") |
| Cc: stable@vger.kernel.org # 3.18 |
| Cc: Federico Vaga <federico.vaga@cern.ch> |
| Acked-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com> |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Link: https://lore.kernel.org/r/20210917114622.5412-6-johan@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/ipack/devices/ipoctal.c | 29 +++++++++++++++++++++-------- |
| 1 file changed, 21 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/ipack/devices/ipoctal.c |
| +++ b/drivers/ipack/devices/ipoctal.c |
| @@ -84,22 +84,34 @@ static int ipoctal_port_activate(struct |
| return 0; |
| } |
| |
| -static int ipoctal_open(struct tty_struct *tty, struct file *file) |
| +static int ipoctal_install(struct tty_driver *driver, struct tty_struct *tty) |
| { |
| struct ipoctal_channel *channel = dev_get_drvdata(tty->dev); |
| struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); |
| - int err; |
| - |
| - tty->driver_data = channel; |
| + int res; |
| |
| if (!ipack_get_carrier(ipoctal->dev)) |
| return -EBUSY; |
| |
| - err = tty_port_open(&channel->tty_port, tty, file); |
| - if (err) |
| - ipack_put_carrier(ipoctal->dev); |
| + res = tty_standard_install(driver, tty); |
| + if (res) |
| + goto err_put_carrier; |
| + |
| + tty->driver_data = channel; |
| + |
| + return 0; |
| + |
| +err_put_carrier: |
| + ipack_put_carrier(ipoctal->dev); |
| + |
| + return res; |
| +} |
| + |
| +static int ipoctal_open(struct tty_struct *tty, struct file *file) |
| +{ |
| + struct ipoctal_channel *channel = tty->driver_data; |
| |
| - return err; |
| + return tty_port_open(&channel->tty_port, tty, file); |
| } |
| |
| static void ipoctal_reset_stats(struct ipoctal_stats *stats) |
| @@ -665,6 +677,7 @@ static void ipoctal_cleanup(struct tty_s |
| |
| static const struct tty_operations ipoctal_fops = { |
| .ioctl = NULL, |
| + .install = ipoctal_install, |
| .open = ipoctal_open, |
| .close = ipoctal_close, |
| .write = ipoctal_write_tty, |