Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751352AbbLMAgs (ORCPT ); Sat, 12 Dec 2015 19:36:48 -0500 Received: from mail-pa0-f42.google.com ([209.85.220.42]:35358 "EHLO mail-pa0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751172AbbLMAgq (ORCPT ); Sat, 12 Dec 2015 19:36:46 -0500 From: Peter Hurley To: Greg Kroah-Hartman Cc: Jiri Slaby , linux-kernel@vger.kernel.org, Peter Hurley Subject: [PATCH 0/8] Fix unsafe uart port access Date: Sat, 12 Dec 2015 16:36:24 -0800 Message-Id: <1449966992-4033-1-git-send-email-peter@hurleysoftware.com> X-Mailer: git-send-email 2.6.3 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3822 Lines: 90 Hi Greg, The serial core has always intended to allow uart drivers to detach and unload, even while ttys are open and running. Since the serial core is the actual tty driver, it acts as a proxy for the uart driver, which allows the uart driver to remove the port (which hangs up the tty) and then unload. However, all of this is broken. Firstly, there is no mechanism for blocking the uart port removal until current operations are complete. The tty core does not, and never has, serialized ioctl() or any other tty operation other than open/close with hangup. Secondly, uart_register_driver() directly binds data from the uart driver with the tty core, rather than providing proxy copies _without taking module references to the uart driver_. This produces some spectacular results if the tty is in-use when the uart driver unloads. Thirdly, uart_unregister_driver() immediately destroys the tty port despite that it may be in use, and will continue to be for the lifetime of the tty, which is unbounded (userspace may retain open ttys forever). This series addresses the first problem of ensuring safe uart port dereferencing with concurrent uart port removal. Two distinct mechanisms are used to provide the necessary safe dereference: the tty_port mutex and RCU. By serializing the uart port detach (ie, reset to NULL) with the tty_port mutex, existing sections of the serial core that already hold the port mutex are guaranteed the uart port detach will not be concurrent, and so can simply test for NULL value before first dereference. Most of the existing serial core that holds the port mutex is ioctl-related and so can return -EIO as if the tty has been hungup (which it has been). Other portions of the serial core that sleep (eg. uart_wait_until_sent()) also now claim the port mutex to prevent concurrent uart port detach, and thus protect the reference. The port mutex is dropped for the actual sleep, retaken on wakeup and the uart port is re-checked for NULL. For portions of the serial core that don't sleep, RCU is used to defer actual uart port teardown after detach (with synchronize_rcu()) until the current holders of rcu_read_lock() are complete. The xmit buffer operations that don't modify the buffer indexes -- uart_write_room() and uart_chars_in_buffer() -- just report the state of the xmit buffer anyway if the uart port has been removed, despite that the xmit buffer is no longer lockable (the lock is in the uart_port that is now gone). Xmit buffer operations that do modify the buffer indexes are aborted. Extra care is taken with the close/hangup/shutdown paths since this must continue to perform other work even if the uart port has been removed (for example, if the uart port was /dev/console and so will only be closed when the file descriptor is released). I do have a plan for the second and third problems but this series does not implement those. Regards, Peter Hurley (8): serial: core: Fold __uart_put_char() into caller serial: core: Fold do_uart_get_info() into caller serial: core: Use tty->index for port # in debug messages serial: core: Take port mutex for send_xchar() tty method serial: core: Expand port mutex section in uart_poll_init() serial: core: Prevent unsafe uart port access, part 1 serial: core: Prevent unsafe uart port access, part 2 serial: core: Prevent unsafe uart port access, part 3 drivers/tty/serial/8250/8250_port.c | 6 +- drivers/tty/serial/serial_core.c | 547 +++++++++++++++++++++++------------- 2 files changed, 355 insertions(+), 198 deletions(-) -- 2.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/