From 2a48602615e0a2f563549c7d5c8d507f904cf96e Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Thu, 22 Nov 2018 18:23:47 +0900 Subject: tty: do not set TTY_IO_ERROR flag if console port Since Commit 761ed4a94582 ('tty: serial_core: convert uart_close to use tty_port_close') and Commit 4dda864d7307 ('tty: serial_core: Fix serial console crash on port shutdown), a serial port which is used as console can be stuck when logging out if there is a remained process. After logged out, agetty will try to grab the serial port but it will be failed because the previous process did not release the port correctly. To fix this, TTY_IO_ERROR bit should not be enabled of tty_port_close if the port is console port. Reproduce step: - Run background processes from serial console $ while true; do sleep 10; done & - Log out $ logout -> Stuck - Read journal log by journalctl | tail Jan 28 16:07:01 ubuntu systemd[1]: Stopped Serial Getty on ttyAMA0. Jan 28 16:07:01 ubuntu systemd[1]: Started Serial Getty on ttyAMA0. Jan 28 16:07:02 ubuntu agetty[1643]: /dev/ttyAMA0: not a tty Fixes: 761ed4a94582 ("tty: serial_core: convert uart_close to use tty_port_close") Cc: Geert Uytterhoeven Cc: Rob Herring Cc: Jiri Slaby Signed-off-by: Chanho Park Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index cb6075096a5b..044c3cbdcfa4 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -633,7 +633,8 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty, if (tty_port_close_start(port, tty, filp) == 0) return; tty_port_shutdown(port, tty); - set_bit(TTY_IO_ERROR, &tty->flags); + if (!port->console) + set_bit(TTY_IO_ERROR, &tty->flags); tty_port_close_end(port, tty); tty_port_tty_set(port, NULL); } -- cgit v1.2.3 From dac097c4546e4c5b16dd303a1e97c1d319c8ab3e Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 21 Nov 2018 10:22:54 -0500 Subject: drivers/tty: add missing of_node_put() of_find_node_by_path() acquires a reference to the node returned by it and that reference needs to be dropped by its caller. This place is not doing this, so fix it. Signed-off-by: Yangtao Li Signed-off-by: David S. Miller --- drivers/tty/serial/suncore.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/suncore.c b/drivers/tty/serial/suncore.c index 70a4ea4eaa6e..990376576970 100644 --- a/drivers/tty/serial/suncore.c +++ b/drivers/tty/serial/suncore.c @@ -112,6 +112,7 @@ void sunserial_console_termios(struct console *con, struct device_node *uart_dp) mode = of_get_property(dp, mode_prop, NULL); if (!mode) mode = "9600,8,n,1,-"; + of_node_put(dp); } cflag = CREAD | HUPCL | CLOCAL; -- cgit v1.2.3 From f51ccf46217c28758b1f3b5bc0ccfc00eca658b2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 4 Dec 2018 17:00:36 +0100 Subject: USB: serial: console: fix reported terminal settings The USB-serial console implementation has never reported the actual terminal settings used. Despite storing the corresponding cflags in its struct console, these were never honoured on later tty open() where the tty termios would be left initialised to the driver defaults. Unlike the serial console implementation, the USB-serial code calls subdriver open() already at console setup. While calling set_termios() and write() before open() looks like it could work for some USB-serial drivers, others definitely do not expect this, so modelling this after serial core is going to be intrusive, if at all possible. Instead, use a (renamed) tty helper to save the termios data used at console setup so that the tty termios reflects the actual terminal settings after a subsequent tty open(). Note that the calls to tty_init_termios() (tty_driver_install()) and tty_save_termios() are serialised using the disconnect mutex. This specifically fixes a regression that was triggered by a recent change adding software flow control to the pl2303 driver: a getty trying to disable flow control while leaving the baud rate unchanged would now also set the baud rate to the driver default (prior to the flow-control change this had been a noop). Fixes: 7041d9c3f01b ("USB: serial: pl2303: add support for tx xon/xoff flow control") Cc: stable # 4.18 Cc: Florian Zumbiehl Reported-by: Jarkko Nikula Tested-by: Jarkko Nikula Acked-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold --- drivers/tty/tty_io.c | 11 +++++++++-- drivers/usb/serial/console.c | 2 +- include/linux/tty.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index ee80dfbd5442..687250ec8032 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1373,7 +1373,13 @@ err_release_lock: return ERR_PTR(retval); } -static void tty_free_termios(struct tty_struct *tty) +/** + * tty_save_termios() - save tty termios data in driver table + * @tty: tty whose termios data to save + * + * Locking: Caller guarantees serialisation with tty_init_termios(). + */ +void tty_save_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; @@ -1392,6 +1398,7 @@ static void tty_free_termios(struct tty_struct *tty) } *tp = tty->termios; } +EXPORT_SYMBOL_GPL(tty_save_termios); /** * tty_flush_works - flush all works of a tty/pty pair @@ -1491,7 +1498,7 @@ static void release_tty(struct tty_struct *tty, int idx) WARN_ON(!mutex_is_locked(&tty_mutex)); if (tty->ops->shutdown) tty->ops->shutdown(tty); - tty_free_termios(tty); + tty_save_termios(tty); tty_driver_remove_tty(tty->driver, tty); tty->port->itty = NULL; if (tty->link) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 17940589c647..7d289302ff6c 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -101,7 +101,6 @@ static int usb_console_setup(struct console *co, char *options) cflag |= PARENB; break; } - co->cflag = cflag; /* * no need to check the index here: if the index is wrong, console @@ -164,6 +163,7 @@ static int usb_console_setup(struct console *co, char *options) serial->type->set_termios(tty, port, &dummy); tty_port_tty_set(&port->port, NULL); + tty_save_termios(tty); tty_kref_put(tty); } tty_port_set_initialized(&port->port, 1); diff --git a/include/linux/tty.h b/include/linux/tty.h index 414db2bce715..392138fe59b6 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -556,6 +556,7 @@ extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); extern void tty_release_struct(struct tty_struct *tty, int idx); extern int tty_release(struct inode *inode, struct file *filp); extern void tty_init_termios(struct tty_struct *tty); +extern void tty_save_termios(struct tty_struct *tty); extern int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty); -- cgit v1.2.3 From 100bc3e2bebf95506da57cbdf5f26b25f6da4c81 Mon Sep 17 00:00:00 2001 From: Peter Shih Date: Tue, 27 Nov 2018 12:49:50 +0800 Subject: tty: serial: 8250_mtk: always resume the device in probe. serial8250_register_8250_port calls uart_config_port, which calls config_port on the port before it tries to power on the port. So we need the port to be on before calling serial8250_register_8250_port. Change the code to always do a runtime resume in probe before registering port, and always do a runtime suspend in remove. This basically reverts the change in commit 68e5fc4a255a ("tty: serial: 8250_mtk: use pm_runtime callbacks for enabling"), but still use pm_runtime callbacks. Fixes: 68e5fc4a255a ("tty: serial: 8250_mtk: use pm_runtime callbacks for enabling") Signed-off-by: Peter Shih Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_mtk.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index dd5e1cede2b5..c3f933d10295 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -213,17 +213,17 @@ static int mtk8250_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); - pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - err = mtk8250_runtime_resume(&pdev->dev); - if (err) - return err; - } + err = mtk8250_runtime_resume(&pdev->dev); + if (err) + return err; data->line = serial8250_register_8250_port(&uart); if (data->line < 0) return data->line; + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; } @@ -234,13 +234,11 @@ static int mtk8250_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); serial8250_unregister_port(data->line); + mtk8250_runtime_suspend(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - mtk8250_runtime_suspend(&pdev->dev); - return 0; } -- cgit v1.2.3 From dada6a43b0402eba438a17ac86fdc64ac56a4607 Mon Sep 17 00:00:00 2001 From: Macpaul Lin Date: Wed, 17 Oct 2018 23:08:38 +0800 Subject: kgdboc: fix KASAN global-out-of-bounds bug in param_set_kgdboc_var() This patch is trying to fix KE issue due to "BUG: KASAN: global-out-of-bounds in param_set_kgdboc_var+0x194/0x198" reported by Syzkaller scan." [26364:syz-executor0][name:report8t]BUG: KASAN: global-out-of-bounds in param_set_kgdboc_var+0x194/0x198 [26364:syz-executor0][name:report&]Read of size 1 at addr ffffff900e44f95f by task syz-executor0/26364 [26364:syz-executor0][name:report&] [26364:syz-executor0]CPU: 7 PID: 26364 Comm: syz-executor0 Tainted: G W 0 [26364:syz-executor0]Call trace: [26364:syz-executor0][] dump_bacIctrace+Ox0/0x470 [26364:syz-executor0][] show_stack+0x20/0x30 [26364:syz-executor0][] dump_stack+Oxd8/0x128 [26364:syz-executor0][] print_address_description +0x80/0x4a8 [26364:syz-executor0][] kasan_report+Ox178/0x390 [26364:syz-executor0][] _asan_report_loadi_noabort+Ox18/0x20 [26364:syz-executor0][] param_set_kgdboc_var+Ox194/0x198 [26364:syz-executor0][] param_attr_store+Ox14c/0x270 [26364:syz-executor0][] module_attr_store+0x60/0x90 [26364:syz-executor0][] sysfs_kl_write+Ox100/0x158 [26364:syz-executor0][] kernfs_fop_write+0x27c/0x3a8 [26364:syz-executor0][] do_loop_readv_writev+0x114/0x1b0 [26364:syz-executor0][] do_readv_writev+0x4f8/0x5e0 [26364:syz-executor0][] vfs_writev+0x7c/Oxb8 [26364:syz-executor0][] SyS_writev+Oxcc/0x208 [26364:syz-executor0][] elO_svc_naked +0x24/0x28 [26364:syz-executor0][name:report&] [26364:syz-executor0][name:report&]The buggy address belongs to the variable: [26364:syz-executor0][name:report&] kgdb_tty_line+Ox3f/0x40 [26364:syz-executor0][name:report&] [26364:syz-executor0][name:report&]Memory state around the buggy address: [26364:syz-executor0] ffffff900e44f800: 00 00 00 00 00 04 fa fa fa fa fa fa 00 fa fa fa [26364:syz-executor0] ffffff900e44f880: fa fa fa fa 00 fa fa fa fa fa fa fa 00 fa fa fa [26364:syz-executor0]> ffffff900e44f900: fa fa fa fa 04 fa fa fa fa fa fa fa 00 00 00 00 [26364:syz-executor0][name:report&] ^ [26364:syz-executor0] ffffff900e44f980: 00 fa fa fa fa fa fa fa 04 fa fa fa fa fa fa fa [26364:syz-executor0] ffffff900e44fa00: 04 fa fa fa fa fa fa fa 00 fa fa fa fa fa fa fa [26364:syz-executor0][name:report&] [26364:syz-executor0][name:panic&]Disabling lock debugging due to kernel taint [26364:syz-executor0]------------[cut here]------------ After checking the source code, we've found there might be an out-of-bounds access to "config[len - 1]" array when the variable "len" is zero. Signed-off-by: Macpaul Lin Acked-by: Daniel Thompson Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/kgdboc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index baeeeaec3f03..6fb312e7af71 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -233,7 +233,7 @@ static void kgdboc_put_char(u8 chr) static int param_set_kgdboc_var(const char *kmessage, const struct kernel_param *kp) { - int len = strlen(kmessage); + size_t len = strlen(kmessage); if (len >= MAX_CONFIG_LEN) { pr_err("config string too long\n"); @@ -254,7 +254,7 @@ static int param_set_kgdboc_var(const char *kmessage, strcpy(config, kmessage); /* Chop out \n char as a result of echo */ - if (config[len - 1] == '\n') + if (len && config[len - 1] == '\n') config[len - 1] = '\0'; if (configured == 1) -- cgit v1.2.3