From abdefcedf2010a5b584d89f3f72964fdb737a0b8 Mon Sep 17 00:00:00 2001 From: Kale Yuzik Date: Wed, 30 Jun 2021 08:48:54 -0600 Subject: [PATCH] Implement fix for kernel error when opening TTY device file on kernel 3.7.0 or greater Error message: "tty_init_dev: ttyEC driver does not set tty->port. This would crash the kernel. Fix the driver!" --- tty/module.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/tty/module.c b/tty/module.c index 620e1d80..fd843259 100644 --- a/tty/module.c +++ b/tty/module.c @@ -181,6 +181,18 @@ out_return: */ void __exit ec_tty_cleanup_module(void) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + int i; + + // Confirm that all kalloc'd ports have had kfree() called on them + for (i = 0; i < EC_TTY_MAX_DEVICES; i++) { + if (!tty_driver->ports[i]) continue; + tty_port_destroy(tty_driver->ports[i]); + kfree(tty_driver->ports[i]); + tty_driver->ports[i] = NULL; + } +#endif + tty_unregister_driver(tty_driver); put_tty_driver(tty_driver); printk(KERN_INFO PFX "Module unloading.\n"); @@ -240,6 +252,15 @@ int ec_tty_init(ec_tty_t *t, int minor, cflag = tty_driver->init_termios.c_cflag; } ret = t->ops.cflag_changed(t->cb_data, cflag); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + tty_driver->ports[minor] = kmalloc(sizeof(**tty_driver->ports), + GFP_KERNEL); + if (!tty_driver->ports[minor]) { + ret = -ENOMEM; + } +#endif + if (ret) { printk(KERN_ERR PFX "ERROR: Initial cflag 0x%x not accepted.\n", cflag); @@ -247,6 +268,10 @@ int ec_tty_init(ec_tty_t *t, int minor, return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + tty_port_init(tty_driver->ports[minor]); +#endif + t->timer.expires = jiffies + 10; add_timer(&t->timer); return 0; @@ -772,10 +797,18 @@ ec_tty_t *ectty_create(const ec_tty_operations_t *ops, void *cb_data) void ectty_free(ec_tty_t *tty) { - printk(KERN_INFO PFX "Freeing TTY interface %i.\n", tty->minor); + int minor = tty->minor; + + printk(KERN_INFO PFX "Freeing TTY interface %i.\n", minor); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + tty_port_destroy(tty_driver->ports[minor]); + kfree(tty_driver->ports[minor]); + tty_driver->ports[minor] = NULL; +#endif ec_tty_clear(tty); - ttys[tty->minor] = NULL; + ttys[minor] = NULL; kfree(tty); }