[PATCH v2 0/4] Fix unsafe uart port access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Greg,

This is a redo of the initial series from last December. Whereas v1
used RCU to prevent uart driver removal while serial core operations
were in progress, this version uses reference counting which is
easier to mix with operations that might sleep like send_xchar().

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.

First, 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.

Second, 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.

Third, 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 reference counting.

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).

For serial core operations unprotected by tty port mutex, reference
counting is used to defer actual uart port teardown after detach
until the refcount drops to zero. The ref counting mechanism is
careful not to allow a reference after the refcount has dropped
to 0 (meaning the port has been removed), and uart_remove_one_port()
waits for serial core operations to 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 (4):
  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/serial_core.c | 386 +++++++++++++++++++++++++++------------
 include/linux/serial_core.h      |   2 +
 2 files changed, 268 insertions(+), 120 deletions(-)

-- 
2.8.1

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux